Skip to content

Commit

Permalink
4844: derivate blobs from bsc rather than beacon chain
Browse files Browse the repository at this point in the history
  • Loading branch information
bnoieh committed Apr 25, 2024
1 parent 053083f commit 954d6dc
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
5 changes: 4 additions & 1 deletion op-node/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error {
}

func (n *OpNode) initL1BeaconAPI(ctx context.Context, cfg *Config) error {
// BSC use L1 client to fetch blobs
return nil

// If Ecotone upgrade is not scheduled yet, then there is no need for a Beacon API.
if cfg.Rollup.EcotoneTime == nil {
return nil
Expand Down Expand Up @@ -409,7 +412,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger
} else {
n.safeDB = safedb.Disabled
}
n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.beacon, n, n, n.log, snapshotLog, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, plasmaDA)
n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.l1Source, n, n, n.log, snapshotLog, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, plasmaDA)
return nil
}

Expand Down
22 changes: 22 additions & 0 deletions op-service/eth/blobs_api.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package eth

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
)

type BlobSidecar struct {
Blob Blob `json:"blob"`
Index Uint64String `json:"index"`
Expand Down Expand Up @@ -66,3 +72,19 @@ type APIVersionResponse struct {
type VersionInformation struct {
Version string `json:"version"`
}

type BSCBlobTxSidecar struct {
Blobs []Blob `json:"blobs"` // Blobs needed by the blob pool
Commitments []Bytes48 `json:"commitments"` // Commitments needed by the blob pool
Proofs []Bytes48 `json:"proofs"` // Proofs needed by the blob pool
}

type BSCBlobSidecar struct {
BSCBlobTxSidecar
BlockNumber *big.Int `json:"blockNumber"`
BlockHash common.Hash `json:"blockHash"`
TxIndex uint64 `json:"transactionIndex"`
TxHash common.Hash `json:"transactionHash"`
}

type BSCBlobSidecars []*BSCBlobSidecar
72 changes: 72 additions & 0 deletions op-service/sources/l1_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package sources
import (
"context"
"fmt"
"math/big"
"strings"
"sync"
"time"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"

"github.com/ethereum-optimism/optimism/op-node/rollup"
Expand Down Expand Up @@ -255,6 +257,76 @@ func (s *L1Client) ClearReceiptsCacheBefore(blockNumber uint64) {
s.recProvider.GetReceiptsCache().RemoveLessThan(blockNumber)
}

func (s *L1Client) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) {
if len(hashes) == 0 {
return []*eth.Blob{}, nil
}

blobSidecars, err := s.getBlobSidecars(ctx, ref)
if err != nil {
return nil, fmt.Errorf("failed to get blob sidecars for L1BlockRef %s: %w", ref, err)
}

validatedBlobs, err := validateBlobSidecars(blobSidecars, ref)
if err != nil {
return nil, fmt.Errorf("failed to validate blob sidecars for L1BlockRef %s: %w", ref, err)
}

blobs := make([]*eth.Blob, len(hashes))
for i, indexedBlobHash := range hashes {
blob, ok := validatedBlobs[indexedBlobHash.Hash]
if !ok {
return nil, fmt.Errorf("blob sidecars fetched from rpc mismatched with expected hash %s for L1BlockRef %s", indexedBlobHash.Hash, ref)
}
blobs[i] = blob
}
return blobs, nil
}

func (s *L1Client) getBlobSidecars(ctx context.Context, ref eth.L1BlockRef) (eth.BSCBlobSidecars, error) {
var blobSidecars eth.BSCBlobSidecars
err := s.client.CallContext(ctx, &blobSidecars, "eth_getBlobSidecars", numberID(ref.Number).Arg())
if err != nil {
return nil, err
}
if blobSidecars == nil {
return nil, ethereum.NotFound
}
return blobSidecars, nil
}

func validateBlobSidecars (blobSidecars eth.BSCBlobSidecars, ref eth.L1BlockRef) (map[common.Hash]*eth.Blob, error) {
if len(blobSidecars) == 0 {
return nil, fmt.Errorf("invalidate api response, blob sidecars of block %s are empty", ref.Hash)
}
blobsMap := make(map[common.Hash]*eth.Blob)
for _, blobSidecar := range blobSidecars {
if blobSidecar.BlockNumber.Cmp(big.NewInt(0).SetUint64(ref.Number)) != 0 {
return nil, fmt.Errorf("invalidate api response of tx %s, expect block number %d, got %d", blobSidecar.TxHash, ref.Number, blobSidecar.BlockNumber.Uint64())
}
if blobSidecar.BlockHash.Cmp(ref.Hash) != 0 {
return nil, fmt.Errorf("invalidate api response of tx %s, expect block hash %s, got %s", blobSidecar.TxHash, ref.Hash, blobSidecar.BlockHash)
}
if len(blobSidecar.Blobs) == 0 || len(blobSidecar.Blobs) != len(blobSidecar.Commitments) || len(blobSidecar.Blobs) != len(blobSidecar.Proofs) {
return nil, fmt.Errorf("invalidate api response of tx %s, len of blobs/commitments/proofs is not equal or is 0", blobSidecar.TxHash)
}

for i:=0; i<len(blobSidecar.Blobs); i++ {
// confirm blob data is valid by verifying its proof against the commitment
if err := eth.VerifyBlobProof(&blobSidecar.Blobs[i], kzg4844.Commitment(blobSidecar.Commitments[i]), kzg4844.Proof(blobSidecar.Proofs[i])); err != nil {
return nil, fmt.Errorf("blob of tx %s at index %d failed verification: %w", blobSidecar.TxHash, i, err)
}
// the blob's kzg commitment hashes
hash := eth.KZGToVersionedHash(kzg4844.Commitment(blobSidecar.Commitments[i]))
blobsMap[hash] = &blobSidecar.Blobs[i]
}
}
return blobsMap, nil
}




func (s *L1Client) Close() {
close(s.done)
s.EthClient.Close()
Expand Down

0 comments on commit 954d6dc

Please sign in to comment.