From 45ef240fe40026d7648b4c6cdbf9cc83ba4d5ee9 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 27 Mar 2024 08:09:58 +0800 Subject: [PATCH] fix(transaction_builder): fix an issue in `BlobTransactionBuilder.Build` (#662) --- driver/config_test.go | 2 +- driver/txlist_fetcher/blob.go | 5 +- pkg/rpc/beaconclient.go | 89 +++++++++++++++++++--------- proposer/transaction_builder/blob.go | 4 +- 4 files changed, 66 insertions(+), 34 deletions(-) diff --git a/driver/config_test.go b/driver/config_test.go index 8d9e3e56a..5232aa03f 100644 --- a/driver/config_test.go +++ b/driver/config_test.go @@ -36,9 +36,9 @@ func (s *DriverTestSuite) TestNewConfigFromCliContext() { s.Equal(120*time.Second, c.P2PSyncTimeout) s.Equal(rpcTimeout, c.RPCTimeout) s.NotEmpty(c.JwtSecret) - s.Nil(new(Driver).InitFromCli(context.Background(), ctx)) s.True(c.P2PSyncVerifiedBlocks) s.Equal(l2CheckPoint, c.L2CheckPoint) + s.NotNil(new(Driver).InitFromCli(context.Background(), ctx)) return err } diff --git a/driver/txlist_fetcher/blob.go b/driver/txlist_fetcher/blob.go index 3f17da247..4acc4d5d7 100644 --- a/driver/txlist_fetcher/blob.go +++ b/driver/txlist_fetcher/blob.go @@ -3,7 +3,6 @@ package txlistdecoder import ( "context" "crypto/sha256" - "math/big" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" @@ -36,12 +35,12 @@ func (d *BlobFetcher) Fetch( } // Fetch the L1 block sidecars. - sidecars, err := d.rpc.L1Beacon.GetBlobs(ctx, new(big.Int).SetUint64(meta.L1Height+1)) + sidecars, err := d.rpc.L1Beacon.GetBlobs(ctx, meta.Timestamp) if err != nil { return nil, err } - log.Info("Fetch sidecars", "slot", meta.L1Height+1, "sidecars", len(sidecars)) + log.Info("Fetch sidecars", "blockNumber", meta.L1Height+1, "sidecars", len(sidecars)) // Compare the blob hash with the sidecar's kzg commitment. for i, sidecar := range sidecars { diff --git a/pkg/rpc/beaconclient.go b/pkg/rpc/beaconclient.go index f69be6833..06e3b5ac6 100644 --- a/pkg/rpc/beaconclient.go +++ b/pkg/rpc/beaconclient.go @@ -2,16 +2,12 @@ package rpc import ( "context" - "crypto/sha256" "encoding/json" - "errors" "fmt" - "math/big" + "strconv" "time" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/log" "github.com/prysmaticlabs/prysm/v4/api/client" "github.com/prysmaticlabs/prysm/v4/api/client/beacon" "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/blob" @@ -20,12 +16,25 @@ import ( var ( // Request urls. sidecarsRequestURL = "eth/v1/beacon/blob_sidecars/%d" + genesisRequestURL = "eth/v1/beacon/genesis" ) +type ConfigSpec struct { + SecondsPerSlot string `json:"SECONDS_PER_SLOT"` +} + +type GenesisResponse struct { + Data struct { + GenesisTime string `json:"genesis_time"` + } `json:"data"` +} + type BeaconClient struct { *beacon.Client - timeout time.Duration + timeout time.Duration + genesisTime uint64 + secondsPerSlot uint64 } // NewBeaconClient returns a new beacon client. @@ -34,43 +43,67 @@ func NewBeaconClient(endpoint string, timeout time.Duration) (*BeaconClient, err if err != nil { return nil, err } - return &BeaconClient{cli, timeout}, nil -} -// GetBlobs returns the sidecars for a given slot. -func (c *BeaconClient) GetBlobs(ctx context.Context, slot *big.Int) ([]*blob.Sidecar, error) { - ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, c.timeout) + ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - var sidecars *blob.SidecarsResponse - resBytes, err := c.Get(ctxWithTimeout, fmt.Sprintf(sidecarsRequestURL, slot)) + // Get the genesis time. + var genesisDetail *GenesisResponse + resBytes, err := cli.Get(ctx, genesisRequestURL) if err != nil { return nil, err } - return sidecars.Data, json.Unmarshal(resBytes, &sidecars) + if err := json.Unmarshal(resBytes, &genesisDetail); err != nil { + return nil, err + } + + genesisTime, err := strconv.Atoi(genesisDetail.Data.GenesisTime) + if err != nil { + return nil, err + } + + log.Info("L1 genesis time", "time", genesisTime) + + // Get the seconds per slot. + spec, err := cli.GetConfigSpec(ctx) + if err != nil { + return nil, err + } + + secondsPerSlot, err := strconv.Atoi(spec.Data.(map[string]interface{})["SECONDS_PER_SLOT"].(string)) + if err != nil { + return nil, err + } + + log.Info("L1 seconds per slot", "seconds", secondsPerSlot) + + return &BeaconClient{cli, timeout, uint64(genesisTime), uint64(secondsPerSlot)}, nil } -// GetBlobByHash returns the sidecars for a given slot. -func (c *BeaconClient) GetBlobByHash(ctx context.Context, slot *big.Int, blobHash common.Hash) ([]byte, error) { +// GetBlobs returns the sidecars for a given slot. +func (c *BeaconClient) GetBlobs(ctx context.Context, time uint64) ([]*blob.Sidecar, error) { ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, c.timeout) defer cancel() - sidecars, err := c.GetBlobs(ctxWithTimeout, slot) + slot, err := c.timeToSlot(time) if err != nil { return nil, err } - for _, sidecar := range sidecars { - commitment := kzg4844.Commitment(common.FromHex(sidecar.KzgCommitment)) - if kzg4844.CalcBlobHashV1( - sha256.New(), - &commitment, - ) == blobHash { - blob := eth.Blob(common.FromHex(sidecar.Blob)) - return blob.ToData() - } + var sidecars *blob.SidecarsResponse + resBytes, err := c.Get(ctxWithTimeout, fmt.Sprintf(sidecarsRequestURL, slot)) + if err != nil { + return nil, err } - return nil, errors.New("sidecar not found") + return sidecars.Data, json.Unmarshal(resBytes, &sidecars) +} + +// timeToSlot returns the slots of the given timestamp. +func (c *BeaconClient) timeToSlot(timestamp uint64) (uint64, error) { + if timestamp < c.genesisTime { + return 0, fmt.Errorf("provided timestamp (%v) precedes genesis time (%v)", timestamp, c.genesisTime) + } + return (timestamp - c.genesisTime) / c.secondsPerSlot, nil } diff --git a/proposer/transaction_builder/blob.go b/proposer/transaction_builder/blob.go index c073e9224..aeae2db5c 100644 --- a/proposer/transaction_builder/blob.go +++ b/proposer/transaction_builder/blob.go @@ -61,7 +61,7 @@ func (b *BlobTransactionBuilder) Build( return nil, err } - var blob *eth.Blob + var blob = ð.Blob{} if err := blob.FromData(txListBytes); err != nil { return nil, err } @@ -106,7 +106,7 @@ func (b *BlobTransactionBuilder) Build( } // Send the transaction to the L1 node. - data, err := encoding.TaikoL1ABI.Pack("proposeBlock", encodedParams, nil) + data, err := encoding.TaikoL1ABI.Pack("proposeBlock", encodedParams, []byte{}) if err != nil { return nil, encoding.TryParsingCustomError(err) }