Skip to content

Commit

Permalink
Merge pull request #1 from Inphi/eip-4844-fix-blob-tx-enc
Browse files Browse the repository at this point in the history
Use minimal transaction format as block codec
  • Loading branch information
mdehoog committed Jun 13, 2022
2 parents 372dbc7 + 2ba73e3 commit f15311b
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 18 deletions.
2 changes: 1 addition & 1 deletion core/beacon/types.go
Expand Up @@ -133,7 +133,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
var txs = make([]*types.Transaction, len(enc))
for i, encTx := range enc {
var tx types.Transaction
if err := tx.UnmarshalBinary(encTx); err != nil {
if err := tx.UnmarshalMinimal(encTx); err != nil {
return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
}
txs[i] = &tx
Expand Down
14 changes: 7 additions & 7 deletions core/types/block.go
Expand Up @@ -232,25 +232,25 @@ func (tx *minimalTx) EncodeRLP(w io.Writer) error {
// a view over a regular transactions slice, to RLP decode/encode the transactions all the minimal way
type extBlockTxs []*Transaction

func (txs *extBlockTxs) DecodeRLP(s *rlp.Stream) error {
func (txs extBlockTxs) DecodeRLP(s *rlp.Stream) error {
// we need generics to do this nicely...
var out []*minimalTx
for i, tx := range *txs {
for i, tx := range txs {
out[i] = (*minimalTx)(tx)
}
if err := s.Decode(&out); err != nil {
return fmt.Errorf("failed to decode list of minimal txs: %v", err)
}
*txs = make([]*Transaction, len(out))
txs = make([]*Transaction, len(out))
for i, tx := range out {
(*txs)[i] = (*Transaction)(tx)
txs[i] = (*Transaction)(tx)
}
return nil
}

func (txs *extBlockTxs) EncodeRLP(w io.Writer) error {
out := make([]*minimalTx, len(*txs))
for i, tx := range *txs {
func (txs extBlockTxs) EncodeRLP(w io.Writer) error {
out := make([]*minimalTx, len(txs))
for i, tx := range txs {
out[i] = (*minimalTx)(tx)
}
return rlp.Encode(w, &out)
Expand Down
74 changes: 69 additions & 5 deletions core/types/transaction.go
Expand Up @@ -137,7 +137,7 @@ func (tx *Transaction) EncodeRLP(w io.Writer) error {
buf := encodeBufferPool.Get().(*bytes.Buffer)
defer encodeBufferPool.Put(buf)
buf.Reset()
if err := tx.encodeTyped(buf); err != nil {
if err := tx.encodeTypedMinimal(buf); err != nil {
return err
}
return rlp.Encode(w, buf.Bytes())
Expand All @@ -156,7 +156,12 @@ func (tx *Transaction) encodeTypedMinimal(w io.Writer) error {
if _, err := w.Write([]byte{tx.Type()}); err != nil {
return err
}
return rlp.Encode(w, tx.inner)
// TODO(inphi): clean
if tx.Type() == BlobTxType {
return EncodeSSZ(w, tx.inner.(*SignedBlobTx))
} else {
return rlp.Encode(w, tx.inner)
}
}

// MarshalBinary returns the canonical encoding of the transaction.
Expand Down Expand Up @@ -201,10 +206,9 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
if b, err = s.Bytes(); err != nil {
return err
}
inner, wrapData, err := tx.decodeTyped(b)
inner, err := tx.decodeTypedMinimal(b)
if err == nil {
tx.setDecoded(inner, len(b))
tx.wrapData = wrapData
}
return err
}
Expand Down Expand Up @@ -568,7 +572,7 @@ func (s Transactions) EncodeIndex(i int, w *bytes.Buffer) {
if tx.Type() == LegacyTxType {
rlp.Encode(w, tx.inner)
} else {
tx.encodeTyped(w)
tx.encodeTypedMinimal(w)
}
}

Expand Down Expand Up @@ -812,3 +816,63 @@ func copyAddressPtr(a *common.Address) *common.Address {
cpy := *a
return &cpy
}

// NetworkTransaction is a Transaction wrapper that encodes its maximal representation
type NetworkTransaction struct {
Tx *Transaction
}

func NewNetworkTransaction(tx *Transaction) *NetworkTransaction {
return &NetworkTransaction{Tx: tx}
}

// EncodeRLP implements rlp.Encoder
func (tx *NetworkTransaction) EncodeRLP(w io.Writer) error {
if tx.Tx.Type() == LegacyTxType {
return rlp.Encode(w, tx.Tx)
}
// It's an EIP-2718 typed TX envelope.
buf := encodeBufferPool.Get().(*bytes.Buffer)
defer encodeBufferPool.Put(buf)
buf.Reset()
if err := tx.Tx.encodeTyped(buf); err != nil {
return err
}
return rlp.Encode(w, buf.Bytes())
}

// DecodeRLP implements rlp.Decoder
func (tx *NetworkTransaction) DecodeRLP(s *rlp.Stream) error {
kind, size, err := s.Kind()
switch {
case err != nil:
return err
case kind == rlp.List:
// It's a legacy transaction.
var inner LegacyTx
err := s.Decode(&inner)
if err == nil {
tx.Tx.setDecoded(&inner, int(rlp.ListSize(size)))
}
return err
default:
// It's an EIP-2718 typed TX envelope.
var b []byte
if b, err = s.Bytes(); err != nil {
return err
}
inner, wrapData, err := tx.Tx.decodeTyped(b)
if err == nil {
tx.Tx.setDecoded(inner, len(b))
tx.Tx.wrapData = wrapData
}
return err
}
}

// Hash returns the transaction hash.
func (tx *NetworkTransaction) Hash() common.Hash {
return tx.Tx.Hash()
}

type NetworkTransactions []*NetworkTransaction
3 changes: 2 additions & 1 deletion eth/handler_eth_test.go
Expand Up @@ -278,7 +278,8 @@ func testRecvTransactions(t *testing.T, protocol uint) {
tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)

if err := src.SendTransactions([]*types.Transaction{tx}); err != nil {
ntx := types.NewNetworkTransaction(tx)
if err := src.SendTransactions([]*types.NetworkTransaction{ntx}); err != nil {
t.Fatalf("failed to send transaction: %v", err)
}
select {
Expand Down
4 changes: 2 additions & 2 deletions eth/protocols/eth/broadcast.go
Expand Up @@ -76,12 +76,12 @@ func (p *Peer) broadcastTransactions() {
// Pile transaction until we reach our allowed network limit
var (
hashesCount uint64
txs []*types.Transaction
txs []*types.NetworkTransaction
size common.StorageSize
)
for i := 0; i < len(queue) && size < maxTxPacketSize; i++ {
if tx := p.txpool.Get(queue[i]); tx != nil {
txs = append(txs, tx)
txs = append(txs, types.NewNetworkTransaction(tx))
size += tx.Size()
}
hashesCount++
Expand Down
2 changes: 1 addition & 1 deletion eth/protocols/eth/handlers.go
Expand Up @@ -474,7 +474,7 @@ func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsPac
continue
}
// If known, encode and queue for response packet
if encoded, err := rlp.EncodeToBytes(tx); err != nil {
if encoded, err := rlp.EncodeToBytes(types.NewNetworkTransaction(tx)); err != nil {
log.Error("Failed to encode transaction", "err", err)
} else {
hashes = append(hashes, hash)
Expand Down
2 changes: 1 addition & 1 deletion eth/protocols/eth/peer.go
Expand Up @@ -189,7 +189,7 @@ func (p *Peer) markTransaction(hash common.Hash) {
//
// The reasons this is public is to allow packages using this protocol to write
// tests that directly send messages without having to do the asyn queueing.
func (p *Peer) SendTransactions(txs types.Transactions) error {
func (p *Peer) SendTransactions(txs types.NetworkTransactions) error {
// Mark all the transactions as known, but ensure we don't overflow our limits
for _, tx := range txs {
p.knownTxs.Add(tx.Hash())
Expand Down

0 comments on commit f15311b

Please sign in to comment.