diff --git a/pkg/rpc/tx_blob.go b/pkg/rpc/tx_blob.go index 796317881..46dad1200 100644 --- a/pkg/rpc/tx_blob.go +++ b/pkg/rpc/tx_blob.go @@ -2,14 +2,11 @@ package rpc import ( "errors" - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" ) @@ -106,69 +103,82 @@ func (c *EthClient) createBlobTx( return types.NewTx(blobTx), nil } -// MakeSidecarWithSingleBlob make a sidecar that just include one blob. -func MakeSidecarWithSingleBlob(data []byte) (*types.BlobTxSidecar, error) { - if len(data) > BlobBytes { - return nil, fmt.Errorf("data is bigger than 128k") - } - blob := EncodeBlobs(data)[0] - commitment, err := kzg4844.BlobToCommitment(blob) - if err != nil { - return nil, err - } - proof, err := kzg4844.ComputeBlobProof(blob, commitment) - if err != nil { - return nil, err +// MakeSidecar make a sidecar that just include one blob. +func MakeSidecar(data []byte) (*types.BlobTxSidecar, error) { + sideCar := &types.BlobTxSidecar{Blobs: EncodeBlobs(data)} + for _, blob := range sideCar.Blobs { + commitment, err := kzg4844.BlobToCommitment(blob) + if err != nil { + return nil, err + } + proof, err := kzg4844.ComputeBlobProof(blob, commitment) + if err != nil { + return nil, err + } + sideCar.Commitments = append(sideCar.Commitments, commitment) + sideCar.Proofs = append(sideCar.Proofs, proof) } - return &types.BlobTxSidecar{ - Blobs: []kzg4844.Blob{blob}, - Commitments: []kzg4844.Commitment{commitment}, - Proofs: []kzg4844.Proof{proof}, - }, nil + return sideCar, nil +} + +func encode(origin []byte) []byte { + var res []byte + for ; len(origin) >= 31; origin = origin[31:] { + data := [32]byte{} + copy(data[1:], origin[:31]) + res = append(res, data[:]...) + } + if len(origin) > 0 { + data := make([]byte, len(origin)+1) + copy(data[1:], origin) + res = append(res, data...) + } + return res } // EncodeBlobs encode bytes into Blob type. -func EncodeBlobs(data []byte) []kzg4844.Blob { - blobs := []kzg4844.Blob{{}} - blobIndex := 0 - fieldIndex := -1 - numOfElems := BlobBytes / 32 - for i := 0; i < len(data); i += 31 { - fieldIndex++ - if fieldIndex == numOfElems { - if blobIndex >= 1 { - break - } - blobs = append(blobs, kzg4844.Blob{}) - blobIndex++ - fieldIndex = 0 - } - max := i + 31 - if max > len(data) { - max = len(data) - } - copy(blobs[blobIndex][fieldIndex*32+1:], data[i:max]) +func EncodeBlobs(origin []byte) []kzg4844.Blob { + data := encode(origin) + var blobs []kzg4844.Blob + for ; len(data) >= BlobBytes; data = data[BlobBytes:] { + blob := kzg4844.Blob{} + copy(blob[:], data[:BlobBytes]) + blobs = append(blobs, blob) + } + if len(data) > 0 { + blob := kzg4844.Blob{} + copy(blob[:], data) + blobs = append(blobs, blob) } return blobs } -// DecodeBlob decode blob data. -func DecodeBlob(blob []byte) []byte { - if len(blob) != params.BlobTxFieldElementsPerBlob*32 { - panic("invalid blob encoding") - } - var data []byte - for i, j := 0, 0; i < params.BlobTxFieldElementsPerBlob; i++ { - data = append(data, blob[j:j+31]...) - j += 32 - } - - i := len(data) - 1 +func decode(origin []byte) []byte { + var i = len(origin) - 1 for ; i >= 0; i-- { - if data[i] != 0x00 { + if origin[i] != 0 { break } } - data = data[:i+1] - return data + origin = origin[:i+1] + + var res []byte + for ; len(origin) >= 32; origin = origin[32:] { + data := [31]byte{} + copy(data[:], origin[1:]) + res = append(res, data[:]...) + } + if len(origin) > 0 { + res = append(res, origin[1:]...) + } + return res +} + +// DecodeBlobs decode blob data. +func DecodeBlobs(blobs []kzg4844.Blob) ([]byte, error) { + var res []byte + for _, blob := range blobs { + res = append(res, decode(blob[:])...) + } + return res, nil } diff --git a/pkg/rpc/tx_blob_test.go b/pkg/rpc/tx_blob_test.go index 47239226d..7ee983af8 100644 --- a/pkg/rpc/tx_blob_test.go +++ b/pkg/rpc/tx_blob_test.go @@ -2,6 +2,7 @@ package rpc import ( "context" + "math/big" "os" "testing" "time" @@ -13,6 +14,12 @@ import ( "github.com/stretchr/testify/assert" ) +var _modulus big.Int // q stored as big.Int + +func init() { + _modulus.SetString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16) +} + func TestBlockTx(t *testing.T) { t.SkipNow() ctx, cancel := context.WithCancel(context.Background()) @@ -38,10 +45,13 @@ func TestBlockTx(t *testing.T) { assert.NoError(t, err) t.Logf("address: %s, balance: %s", opts.From.String(), balance.String()) - sidecar, err := MakeSidecarWithSingleBlob([]byte("s")) - assert.NoError(t, err) + data, dErr := os.ReadFile("./tx_blob.go") + assert.NoError(t, dErr) + //data := []byte{'s'} + sideCar, sErr := MakeSidecar(data) + assert.NoError(t, sErr) - tx, err := l1Client.TransactBlobTx(opts, nil, nil, sidecar) + tx, err := l1Client.TransactBlobTx(opts, nil, nil, sideCar) assert.NoError(t, err) receipt, err := bind.WaitMined(ctx, l1Client, tx) @@ -52,3 +62,15 @@ func TestBlockTx(t *testing.T) { t.Log("block number: ", receipt.BlockNumber.Uint64()) t.Log("tx hash: ", receipt.TxHash.String()) } + +func TestMakeSideCar(t *testing.T) { + origin, err := os.ReadFile("./tx_blob.go") + assert.NoError(t, err) + + sideCar, mErr := MakeSidecar(origin) + assert.NoError(t, mErr) + + origin1, dErr := DecodeBlobs(sideCar.Blobs) + assert.NoError(t, dErr) + assert.Equal(t, origin, origin1) +} diff --git a/proposer/proposer.go b/proposer/proposer.go index d1aaa0af1..6e8809eea 100644 --- a/proposer/proposer.go +++ b/proposer/proposer.go @@ -314,7 +314,7 @@ func (p *Proposer) sendProposeBlockTxWithBlobHash( isReplacement bool, ) (*types.Transaction, error) { // Make sidecar in order to get blob hash. - sideCar, err := rpc.MakeSidecarWithSingleBlob(txListBytes) + sideCar, err := rpc.MakeSidecar(txListBytes) if err != nil { return nil, err }