diff --git a/pkg/rpc/tx_blob.go b/pkg/rpc/tx_blob.go index 99da02046..9ae2d6c65 100644 --- a/pkg/rpc/tx_blob.go +++ b/pkg/rpc/tx_blob.go @@ -2,6 +2,7 @@ package rpc import ( "errors" + "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -11,6 +12,10 @@ import ( "github.com/holiman/uint256" ) +var ( + preLenBlob = 32 +) + var ( errBlobInvalid = errors.New("invalid blob encoding") ) @@ -124,7 +129,7 @@ func MakeSidecar(data []byte) (*types.BlobTxSidecar, error) { } func encode(origin []byte) []byte { - var res []byte + var res = make([]byte, preLenBlob, len(origin)/31*32+32) for ; len(origin) >= 31; origin = origin[31:] { data := [32]byte{} copy(data[1:], origin[:31]) @@ -135,9 +140,20 @@ func encode(origin []byte) []byte { copy(data[1:], origin) res = append(res, data...) } + + // Add length prefix + blobLen := big.NewInt(int64(len(res))).Bytes() + copy(res[preLenBlob-len(blobLen):preLenBlob], blobLen) + return res } +func decode(data []byte) []byte { + blobLen := new(big.Int).SetBytes(data[:preLenBlob]) + var lenBytes = blobLen.Uint64() + return data[preLenBlob:lenBytes] +} + // EncodeBlobs encodes bytes into a EIP-4844 blob. func EncodeBlobs(origin []byte) []kzg4844.Blob { data := encode(origin) @@ -160,13 +176,7 @@ func DecodeBlob(blob []byte) ([]byte, error) { if len(blob) != BlobBytes { return nil, errBlobInvalid } - var i = len(blob) - 1 - for ; i >= 0; i-- { - if blob[i] != 0 { - break - } - } - blob = blob[:i+1] + blob = decode(blob) var res []byte for ; len(blob) >= 32; blob = blob[32:] { diff --git a/pkg/rpc/tx_blob_test.go b/pkg/rpc/tx_blob_test.go index 821b0586b..8a467a182 100644 --- a/pkg/rpc/tx_blob_test.go +++ b/pkg/rpc/tx_blob_test.go @@ -2,6 +2,7 @@ package rpc import ( "context" + "encoding/json" "os" "testing" "time" @@ -10,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/assert" "github.com/taikoxyz/taiko-client/internal/utils" @@ -69,3 +71,24 @@ func TestMakeSideCar(t *testing.T) { assert.NoError(t, dErr) assert.Equal(t, origin, origin1) } + +func TestSpecialEndWith0(t *testing.T) { + // nolint: lll + var txsData = ` +[{"type":"0x2","chainId":"0x28c59","nonce":"0x1cca","to":"0x0167001000000000000000000000000000010099","gas":"0x86b3","gasPrice":null,"maxPriorityFeePerGas":"0x59682f00","maxFeePerGas":"0x59682f02","value":"0x0","input":"0xa9059cbb00000000000000000000000001670010000000000000000000000000000100990000000000000000000000000000000000000000000000000000000000000001","accessList":[],"v":"0x0","r":"0x2d554e149d15575030f271403a3b359cd9d5df8acb47ae7df5845aadc54b1ee2","s":"0x39b7ce8e803c443d8fd33679948fbd0a485d88b6a55812a53d9a03a922142100","yParity":"0x0","hash":"0x27aa02a44ea343a72131fc67734c67d410ab6f65429637fbb17a08f781e77f7e"}] +` + + var txs types.Transactions + err := json.Unmarshal([]byte(txsData), &txs) + assert.NoError(t, err) + + origin, err := rlp.EncodeToBytes(txs) + assert.NoError(t, err) + + blobs := EncodeBlobs(origin) + + data, dErr := DecodeBlobs(blobs) + assert.NoError(t, dErr) + + assert.Equal(t, crypto.Keccak256Hash(origin), crypto.Keccak256Hash(data)) +}