Skip to content

Commit

Permalink
gateway: Refactor outlining
Browse files Browse the repository at this point in the history
  • Loading branch information
lukechampine committed Sep 15, 2023
1 parent 57e896a commit 3ca4ff7
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 33 deletions.
24 changes: 17 additions & 7 deletions gateway/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,24 +84,32 @@ func (h *V2BlockHeader) decodeFrom(d *types.Decoder) {
}

func (ot *OutlineTransaction) encodeTo(e *types.Encoder) {
ot.Hash.EncodeTo(e)
if ot.Transaction != nil {
e.WriteBool(true)
e.WriteUint8(0)
ot.Transaction.EncodeTo(e)
} else {
e.WriteBool(false)
} else if ot.V2Transaction != nil {
e.WriteUint8(1)
ot.V2Transaction.EncodeTo(e)
} else {
e.WriteUint8(2)
ot.Hash.EncodeTo(e)
}
}

func (ot *OutlineTransaction) decodeFrom(d *types.Decoder) {
ot.Hash.DecodeFrom(d)
if d.ReadBool() {
switch t := d.ReadUint8(); t {
case 0:
ot.Transaction = new(types.Transaction)
ot.Transaction.DecodeFrom(d)
} else {
ot.Hash = ot.Transaction.FullHash()
case 1:
ot.V2Transaction = new(types.V2Transaction)
ot.V2Transaction.DecodeFrom(d)
ot.Hash = ot.V2Transaction.FullHash()
case 2:
ot.Hash.DecodeFrom(d)
default:
d.SetErr(fmt.Errorf("invalid outline transaction type (%d)", t))
}
}

Expand Down Expand Up @@ -484,6 +492,8 @@ func objectForID(id types.Specifier) object {
case idSendTransactions:
return new(RPCSendTransactions)
case idRelayV2Header:
return new(RPCRelayV2Header)
case idRelayV2BlockOutline:
return new(RPCRelayV2BlockOutline)
case idRelayV2TransactionSet:
return new(RPCRelayV2TransactionSet)
Expand Down
76 changes: 52 additions & 24 deletions gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,26 +130,26 @@ type V2BlockOutline struct {
Transactions []OutlineTransaction
}

func (pb V2BlockOutline) commitment(cs consensus.State) types.Hash256 {
func (bo V2BlockOutline) commitment(cs consensus.State) types.Hash256 {
var acc blake2b.Accumulator
for _, txn := range pb.Transactions {
for _, txn := range bo.Transactions {
acc.AddLeaf(txn.Hash)
}
return cs.Commitment(acc.Root(), pb.MinerAddress)
return cs.Commitment(acc.Root(), bo.MinerAddress)
}

// ID returns a hash that uniquely identifies the block.
func (pb V2BlockOutline) ID(cs consensus.State) types.BlockID {
func (bo V2BlockOutline) ID(cs consensus.State) types.BlockID {
return (&types.Block{
Nonce: pb.Nonce,
Timestamp: pb.Timestamp,
V2: &types.V2BlockData{Commitment: pb.commitment(cs)},
Nonce: bo.Nonce,
Timestamp: bo.Timestamp,
V2: &types.V2BlockData{Commitment: bo.commitment(cs)},
}).ID()
}

// Missing returns the hashes of transactions that are missing from the block.
func (pb V2BlockOutline) Missing() (missing []types.Hash256) {
for _, txn := range pb.Transactions {
func (bo V2BlockOutline) Missing() (missing []types.Hash256) {
for _, txn := range bo.Transactions {
if txn.Transaction == nil && txn.V2Transaction == nil {
missing = append(missing, txn.Hash)
}
Expand All @@ -160,7 +160,7 @@ func (pb V2BlockOutline) Missing() (missing []types.Hash256) {
// Complete attempts to reconstruct the original block using the supplied
// transactions. If the block cannot be fully reconstructed, it returns the
// hashes of the missing transactions.
func (pb *V2BlockOutline) Complete(cs consensus.State, txns []types.Transaction, v2txns []types.V2Transaction) (types.Block, []types.Hash256) {
func (bo *V2BlockOutline) Complete(cs consensus.State, txns []types.Transaction, v2txns []types.V2Transaction) (types.Block, []types.Hash256) {
var v1hashes map[types.Hash256]types.Transaction
var v2hashes map[types.Hash256]types.V2Transaction
completeTxn := func(ptxn *OutlineTransaction) {
Expand Down Expand Up @@ -190,17 +190,17 @@ func (pb *V2BlockOutline) Complete(cs consensus.State, txns []types.Transaction,
}

b := types.Block{
ParentID: pb.ParentID,
Nonce: pb.Nonce,
Timestamp: pb.Timestamp,
MinerPayouts: []types.SiacoinOutput{{Address: pb.MinerAddress, Value: cs.BlockReward()}},
ParentID: bo.ParentID,
Nonce: bo.Nonce,
Timestamp: bo.Timestamp,
MinerPayouts: []types.SiacoinOutput{{Address: bo.MinerAddress, Value: cs.BlockReward()}},
V2: &types.V2BlockData{
Height: pb.Height,
Commitment: pb.commitment(cs),
Height: bo.Height,
Commitment: bo.commitment(cs),
},
}
for i := range pb.Transactions {
ptxn := &pb.Transactions[i]
for i := range bo.Transactions {
ptxn := &bo.Transactions[i]
completeTxn(ptxn)
if ptxn.Transaction != nil {
b.Transactions = append(b.Transactions, *ptxn.Transaction)
Expand All @@ -212,26 +212,54 @@ func (pb *V2BlockOutline) Complete(cs consensus.State, txns []types.Transaction,
b.MinerPayouts[0].Value = b.MinerPayouts[0].Value.Add(ptxn.V2Transaction.MinerFee)
}
}
return b, pb.Missing()
return b, bo.Missing()
}

// RemoveTransactions removes the specified transactions from the block.
func (pb *V2BlockOutline) RemoveTransactions(txns []types.Transaction, v2txns []types.V2Transaction) {
func (bo *V2BlockOutline) RemoveTransactions(txns []types.Transaction, v2txns []types.V2Transaction) {
remove := make(map[types.Hash256]bool)
for _, txn := range txns {
remove[txn.FullHash()] = true
}
for _, txn := range v2txns {
remove[txn.FullHash()] = true
}
for i := range pb.Transactions {
if remove[pb.Transactions[i].Hash] {
pb.Transactions[i].Transaction = nil
pb.Transactions[i].V2Transaction = nil
for i := range bo.Transactions {
if remove[bo.Transactions[i].Hash] {
bo.Transactions[i].Transaction = nil
bo.Transactions[i].V2Transaction = nil
}
}
}

// OutlineBlock returns a block outline for b that omits the specified
// transactions.
func OutlineBlock(b types.Block, txns []types.Transaction, v2txns []types.V2Transaction) V2BlockOutline {
var otxns []OutlineTransaction
for _, txn := range b.Transactions {
otxns = append(otxns, OutlineTransaction{
Hash: txn.FullHash(),
Transaction: &txn,
})
}
for _, txn := range b.V2Transactions() {
otxns = append(otxns, OutlineTransaction{
Hash: txn.FullHash(),
V2Transaction: &txn,
})
}
bo := V2BlockOutline{
Height: b.V2.Height,
ParentID: b.ParentID,
Nonce: b.Nonce,
Timestamp: b.Timestamp,
MinerAddress: b.MinerPayouts[0].Address,
Transactions: otxns,
}
bo.RemoveTransactions(txns, v2txns)
return bo
}

// Dial initiates the gateway handshake with a peer.
func Dial(conn net.Conn, ourHeader Header) (*Peer, error) {
p := &Peer{
Expand Down
4 changes: 2 additions & 2 deletions gateway/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ type RPCHandler interface {
// v2
Transactions(index types.ChainIndex, txns []types.Hash256) ([]types.Transaction, []types.V2Transaction, error)
Checkpoint(index types.ChainIndex) (types.Block, consensus.State, error)
RelayV2BlockHeader(h V2BlockHeader, origin *Peer)
RelayV2Header(h V2BlockHeader, origin *Peer)
RelayV2BlockOutline(b V2BlockOutline, origin *Peer)
RelayV2TransactionSet(txns []types.V2Transaction, origin *Peer)
}
Expand Down Expand Up @@ -196,7 +196,7 @@ func (p *Peer) HandleRPC(id types.Specifier, stream net.Conn, h RPCHandler) erro
if err := p.withDecoder(stream, r.maxRequestLen(), r.decodeRequest); err != nil {
return err
}
h.RelayV2BlockHeader(r.Header, p)
h.RelayV2Header(r.Header, p)
return nil
case *RPCRelayV2BlockOutline:
if err := p.withDecoder(stream, r.maxRequestLen(), r.decodeRequest); err != nil {
Expand Down

0 comments on commit 3ca4ff7

Please sign in to comment.