Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go-ethereum
2 changes: 1 addition & 1 deletion node/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/go-kit/kit v0.12.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v1.0.2
github.com/holiman/uint256 v1.2.4
github.com/klauspost/compress v1.17.9
github.com/morph-l2/go-ethereum v1.10.14-0.20250904090403-2bccdaee12d9
github.com/prometheus/client_golang v1.17.0
Expand Down Expand Up @@ -64,7 +65,6 @@ require (
github.com/hashicorp/go-bexpr v0.1.13 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/iden3/go-iden3-crypto v0.0.16 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
Expand Down
223 changes: 4 additions & 219 deletions node/types/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,147 +121,8 @@ func CompressBatchBytes(batchBytes []byte) ([]byte, error) {
return compressedBatchBytes, nil
}

func EncodeTxsPayloadToBlob(batchBytes []byte) (*eth.BlobTxSidecar, error) {
if len(batchBytes) == 0 {
return MakeBlobTxSidecar(batchBytes)
}
compressedBatchBytes, err := zstd.CompressBatchBytes(batchBytes)
if err != nil {
return nil, err
}
return MakeBlobTxSidecar(compressedBatchBytes)
}

// Deprecated: DecodeTxsFromBlob is recommended
func DecodeLegacyTxsFromBlob(b *kzg4844.Blob) (eth.Transactions, error) {
data, err := RetrieveBlobBytes(b)
if err != nil {
return nil, err
}

// metadata || tx_payload
// metadata consists of num_chunks (2 bytes) and chunki_size (4 bytes per chunk)
dataReader := bytes.NewReader(data[2:])
var txPayloadSize uint32
for i := 0; i < 15; i++ {
var size uint32
if err := binary.Read(dataReader, binary.BigEndian, size); err != nil {
return nil, err
}
txPayloadSize += size
}
txPayload := data[62 : 62+txPayloadSize]

var byteOccupied int
var sizeBytes []byte
b3 := byte(txPayloadSize >> 16)
b2 := byte(txPayloadSize >> 8)
b1 := byte(txPayloadSize)
if b3 > 0 {
byteOccupied = 3
sizeBytes = []byte{b3, b2, b1}
} else if b2 > 0 {
byteOccupied = 2
sizeBytes = []byte{b2, b1}
} else {
byteOccupied = 1
sizeBytes = []byte{b1}
}

fistByte := byte(247 + byteOccupied)
simulatedRLP := append(append([]byte{fistByte}, sizeBytes...), txPayload...)
decoded := make([]*eth.Transaction, 0)
if err := rlp.DecodeBytes(simulatedRLP, &decoded); err != nil {
return nil, err
}
return decoded, nil
}

func DecodeTxsFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
if isEmptyBlob(blob) {
return eth.Transactions{}, nil
}
data, err := RetrieveBlobBytes(blob)
if err != nil {
return nil, err
}
batchBytes, err := zstd.DecompressBatchBytes(data)
if err != nil {
return nil, err
}
reader := bytes.NewReader(batchBytes)
txs := make(eth.Transactions, 0)
for {
var (
firstByte byte
fullTxBytes []byte
innerTx eth.TxData
err error
)
if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// if the blob byte array is completely consumed, then break the loop
if err == io.EOF {
break
}
return nil, err
}
// zero byte is found after valid tx bytes, break the loop
if firstByte == 0 {
break
}

switch firstByte {
case eth.AccessListTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.AccessListTx)
case eth.DynamicFeeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
}
innerTx = new(eth.LegacyTx)
}

// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
// // the firstByte here is used to indicate tx type, so skip it
// if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// return nil, err
// }
//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
// return nil, fmt.Errorf("not supported tx type: %d", firstByte)
//}
fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
if err != nil {
return nil, err
}
if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
return nil, err
}
txs = append(txs, eth.NewTx(innerTx))
}
return txs, nil
}

func DecodeBlocksFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
if isEmptyBlob(blob) {
return eth.Transactions{}, nil
}
data, err := RetrieveBlobBytes(blob)
if err != nil {
return nil, err
}
batchBytes, err := zstd.DecompressBatchBytes(data)
if err != nil {
return nil, err
}
reader := bytes.NewReader(batchBytes)
func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) {
reader := bytes.NewReader(txsBytes)
txs := make(eth.Transactions, 0)
for {
var (
Expand Down Expand Up @@ -293,78 +154,11 @@ func DecodeBlocksFromBlob(blob *kzg4844.Blob) (eth.Transactions, error) {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
}
innerTx = new(eth.LegacyTx)
}

// we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType
//if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType {
// // the firstByte here is used to indicate tx type, so skip it
// if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// return nil, err
// }
//} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
// return nil, fmt.Errorf("not supported tx type: %d", firstByte)
//}
fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader)
if err != nil {
return nil, err
}
if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil {
return nil, err
}
txs = append(txs, eth.NewTx(innerTx))
}
return txs, nil
}

func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) {
//if isEmptyBlob(blob) {
// return eth.Transactions{}, nil
//}
//data, err := RetrieveBlobBytes(blob)
//if err != nil {
// return nil, err
//}
//batchBytes, err := zstd.DecompressBatchBytes(data)
//if err != nil {
// return nil, err
//}
reader := bytes.NewReader(txsBytes)
txs := make(eth.Transactions, 0)
for {
var (
firstByte byte
fullTxBytes []byte
innerTx eth.TxData
err error
)
if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
// if the blob byte array is completely consumed, then break the loop
if err == io.EOF {
break
}
return nil, err
}
// zero byte is found after valid tx bytes, break the loop
if firstByte == 0 {
break
}

switch firstByte {
case eth.AccessListTxType:
case eth.SetCodeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.AccessListTx)
case eth.DynamicFeeTxType:
if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil {
return nil, err
}
innerTx = new(eth.DynamicFeeTx)
innerTx = new(eth.SetCodeTx)
default:
if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247)
return nil, fmt.Errorf("not supported tx type: %d", firstByte)
Expand Down Expand Up @@ -393,15 +187,6 @@ func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) {
return txs, nil
}

func isEmptyBlob(blob *kzg4844.Blob) bool {
for _, b := range blob {
if b != 0 {
return false
}
}
return true
}

func extractInnerTxFullBytes(firstByte byte, reader io.Reader) ([]byte, error) {
//the occupied byte length for storing the size of the following rlp encoded bytes
sizeByteLen := firstByte - 0xf7
Expand Down
43 changes: 34 additions & 9 deletions node/types/blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package types

import (
"math/big"
"morph-l2/node/zstd"
"testing"

"github.com/holiman/uint256"
"github.com/morph-l2/go-ethereum/accounts/abi/bind"
"github.com/morph-l2/go-ethereum/common"
eth "github.com/morph-l2/go-ethereum/core/types"
Expand Down Expand Up @@ -97,7 +97,31 @@ func generateContractTx(isLegacy bool) (*eth.Transaction, error) {
return auth.Signer(address, contractTx)
}

func TestDecodeTxsFromBlob(t *testing.T) {
func generateSetCodeTx() *eth.Transaction {
privKey, _ := crypto.GenerateKey()
address := crypto.PubkeyToAddress(privKey.PublicKey)
to := common.BigToAddress(big.NewInt(100))
data := rand.Bytes(100)
inner := &eth.SetCodeTx{
ChainID: uint256.NewInt(2810),
Nonce: 1,
GasFeeCap: uint256.NewInt(1e10),
GasTipCap: uint256.NewInt(1e8),
Gas: 500000,
To: to,
Value: uint256.NewInt(1),
Data: data,
AccessList: []eth.AccessTuple{{
Address: address,
StorageKeys: []common.Hash{common.BigToHash(big.NewInt(2))},
}},
AuthList: []eth.SetCodeAuthorization{},
}
return eth.NewTx(inner)

}

func TestDecodeTxsFromBytes(t *testing.T) {
transferTx, err := generateTransferTx(false)
require.NoError(t, err)
transferTxBz, err := transferTx.MarshalBinary()
Expand All @@ -113,16 +137,17 @@ func TestDecodeTxsFromBlob(t *testing.T) {
contractTxBz, err := contractTx.MarshalBinary()
require.NoError(t, err)

cks := BatchData{
txsPayload: append(append(transferTxBz, legacyContractTxBz...), contractTxBz...),
}
compressedBlobBytes, err := zstd.CompressBatchBytes(cks.TxsPayload())
setCodeTx := generateSetCodeTx()
require.NoError(t, err)
b, err := MakeBlobCanonical(compressedBlobBytes)
setCodeTxBz, err := setCodeTx.MarshalBinary()
require.NoError(t, err)
txs, err := DecodeTxsFromBlob(b)

cks := BatchData{
txsPayload: append(append(append(transferTxBz, legacyContractTxBz...), contractTxBz...), setCodeTxBz...),
}
txs, err := DecodeTxsFromBytes(cks.TxsPayload())
require.NoError(t, err)
require.EqualValues(t, 3, txs.Len())
require.EqualValues(t, 4, txs.Len())
require.EqualValues(t, transferTx.Hash(), txs[0].Hash())
require.EqualValues(t, legacyContractTx.Hash(), txs[1].Hash())
require.EqualValues(t, contractTx.Hash(), txs[2].Hash())
Expand Down
Loading