diff --git a/go/ethadapter/blob_beacon_client.go b/go/ethadapter/blob_beacon_client.go index 4be97a7f81..9165b3ec7b 100644 --- a/go/ethadapter/blob_beacon_client.go +++ b/go/ethadapter/blob_beacon_client.go @@ -97,6 +97,9 @@ func (bc *BeaconHTTPClient) BeaconBlobSidecars(ctx context.Context, slot uint64, if err != nil { return APIGetBlobSidecarsResponse{}, err } + if len(resp.Data) == 0 { + return APIGetBlobSidecarsResponse{}, fmt.Errorf("no blob sidecars found for blob at slot %d", slot) + } return resp, nil } @@ -198,11 +201,9 @@ func (cl *L1BeaconClient) fetchSidecars(ctx context.Context, slot uint64, hashes } // GetBlobSidecars fetches blob sidecars that were confirmed in the specified -// L1 block with the given hashes. +// L1 block. If hashes are provided, only returns sidecars matching those hashes. +// If no hashes are provided, returns all sidecars for the block. func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, b *types.Header, hashes []gethcommon.Hash) ([]*BlobSidecar, error) { - if len(hashes) == 0 { - return []*BlobSidecar{}, nil - } slotFn, err := cl.GetTimeToSlot(ctx) if err != nil { return nil, fmt.Errorf("failed to get time to slot function: %w", err) @@ -217,6 +218,12 @@ func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, b *types.Header, return nil, fmt.Errorf("failed to fetch blob sidecars for slot %v block %v: %w", slot, b, err) } + // return all sidecars for block if no hashes provided + if len(hashes) == 0 { + return resp.Data, nil + } + + // match sidecars with provided hashes sidecars, err := MatchSidecarsWithHashes(resp.Data, hashes) if err != nil { return nil, err @@ -233,6 +240,15 @@ func (cl *L1BeaconClient) FetchBlobs(ctx context.Context, b *types.Header, hashe if err != nil { return nil, fmt.Errorf("failed to get blob sidecars for Block Header %s: %w", b.Hash().Hex(), err) } + + // no hashes were provided, create slice of all hashes from sidecars + if len(hashes) == 0 { + hashes = make([]gethcommon.Hash, len(blobSidecars)) + for i, sidecar := range blobSidecars { + hashes[i] = KZGToVersionedHash(kzg4844.Commitment(sidecar.KZGCommitment)) + } + } + return BlobsFromSidecars(blobSidecars, hashes) } diff --git a/go/host/container/host_container.go b/go/host/container/host_container.go index 8759602eb7..d65bd6c098 100644 --- a/go/host/container/host_container.go +++ b/go/host/container/host_container.go @@ -153,9 +153,9 @@ func NewHostContainerFromConfig(parsedConfig *config.HostInputConfig, logger get obscuroRelevantContracts := []gethcommon.Address{cfg.ManagementContractAddress, cfg.MessageBusAddress} l1Repo := l1.NewL1Repository(l1Client, obscuroRelevantContracts, logger) beaconClient := ethadapter.NewBeaconHTTPClient(new(http.Client), cfg.L1BeaconUrl) + beaconFallback := ethadapter.NewBeaconHTTPClient(new(http.Client), cfg.L1BlobArchiveUrl) // we can add more fallback clients as they become available - fallback := ethadapter.NewArchivalHTTPClient(new(http.Client), cfg.L1BlobArchiveUrl) - blobResolver := l1.NewBlobResolver(ethadapter.NewL1BeaconClient(beaconClient, fallback)) + blobResolver := l1.NewBlobResolver(ethadapter.NewL1BeaconClient(beaconClient, beaconFallback)) return NewHostContainer(cfg, services, aggP2P, l1Client, l1Repo, enclaveClients, mgmtContractLib, ethWallet, rpcServer, logger, metricsService, blobResolver) } diff --git a/go/host/l1/blobresolver_test.go b/go/host/l1/blobresolver_test.go index 141f7716a7..b73db3ea40 100644 --- a/go/host/l1/blobresolver_test.go +++ b/go/host/l1/blobresolver_test.go @@ -4,6 +4,7 @@ import ( "context" "net/http" "testing" + "time" gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -30,3 +31,22 @@ func TestBlobResolver(t *testing.T) { require.NoError(t, err) require.Len(t, blobs, 2) } + +// TestSepoliaBlobResolver checks the public node sepolia beacon APIs work as expected +func TestSepoliaBlobResolver(t *testing.T) { + t.Skipf("Test will occasionally fail due to the time wi ad ndow landing on a block with no blobs") + // l1_beacon_url for sepolia + beaconClient := ethadapter.NewBeaconHTTPClient(new(http.Client), "https://ethereum-sepolia-beacon-api.publicnode.com") + // l1_blob_archive_url for sepolia + fallback := ethadapter.NewBeaconHTTPClient(new(http.Client), "https://eth-beacon-chain-sepolia.drpc.org/rest/") + blobResolver := NewBlobResolver(ethadapter.NewL1BeaconClient(beaconClient, fallback)) + + // this is a moving point in time so we can't compare hashes or be certain there will be blobs in the block + // create block with timestamp 30 days ago relative to current time + historicalBlock := &types.Header{ + Time: uint64(time.Now().Unix()) - (30 * 24 * 60 * 60), // 30 days in seconds + } + + _, err := blobResolver.FetchBlobs(context.Background(), historicalBlock, []gethcommon.Hash{}) + require.NoError(t, err) +} diff --git a/integration/simulation/utils.go b/integration/simulation/utils.go index 7fe5ed6400..9445b9c7be 100644 --- a/integration/simulation/utils.go +++ b/integration/simulation/utils.go @@ -103,8 +103,8 @@ func findHashDups(list []gethcommon.Hash) map[gethcommon.Hash]int { } // FindRollupDups - returns a map of all L2 root hashes that appear multiple times, and how many times -func findRollupDups(list []*common.ExtRollup) map[common.L2BatchHash]int { - elementCount := make(map[common.L2BatchHash]int) +func findRollupDups(list []*common.ExtRollup) map[common.L2RollupHash]int { + elementCount := make(map[common.L2RollupHash]int) for _, item := range list { // check if the item/element exist in the duplicate_frequency map @@ -115,7 +115,7 @@ func findRollupDups(list []*common.ExtRollup) map[common.L2BatchHash]int { elementCount[item.Hash()] = 1 // else start counting from 1 } } - dups := make(map[common.L2BatchHash]int) + dups := make(map[common.L2RollupHash]int) for u, i := range elementCount { if i > 1 { dups[u] = i diff --git a/integration/simulation/validate_chain.go b/integration/simulation/validate_chain.go index aa7932b73f..1fded15ca0 100644 --- a/integration/simulation/validate_chain.go +++ b/integration/simulation/validate_chain.go @@ -189,15 +189,16 @@ func checkBlockchainOfEthereumNode(t *testing.T, node ethadapter.EthClient, minH checkCollectedL1Fees(t, node, s, nodeIdx, rollupReceipts) - if len(findHashDups(deposits)) > 0 { - dups := findHashDups(deposits) - t.Errorf("Node %d: Found Deposit duplicates: %v", nodeIdx, dups) + hashDups := findHashDups(deposits) + if len(hashDups) > 0 { + t.Errorf("Node %d: Found Deposit duplicates: %v", nodeIdx, hashDups) } - if len(findRollupDups(rollups)) > 0 { - dups := findRollupDups(rollups) + + rollupDups := findRollupDups(rollups) + if len(rollupDups) > 0 { // todo @siliev - fix in memory rollups, lack of real client breaks the normal ask smart contract flow. if !s.Params.IsInMem { - t.Errorf("Node %d: Found Rollup duplicates: %v", nodeIdx, dups) + t.Errorf("Node %d: Found Rollup duplicates: %v", nodeIdx, rollupDups) } }