Skip to content

Commit 993e4c5

Browse files
Modify simulated beacon to service blobs in nitro system_tests
1 parent a087bcc commit 993e4c5

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

eth/catalyst/simulated_beacon.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ type SimulatedBeacon struct {
9696
engineAPI *ConsensusAPI
9797
curForkchoiceState engine.ForkchoiceStateV1
9898
lastBlockTime uint64
99+
100+
blobsBundleProvider map[common.Hash]*engine.BlobsBundleV1
99101
}
100102

101103
func payloadVersion(config *params.ChainConfig, time uint64, header *types.Header) engine.PayloadVersion {
@@ -264,6 +266,10 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
264266
return err
265267
}
266268
c.lastBlockTime = payload.Timestamp
269+
270+
if c.blobsBundleProvider != nil && envelope.BlobsBundle != nil {
271+
c.blobsBundleProvider[payload.BlockHash] = envelope.BlobsBundle
272+
}
267273
return nil
268274
}
269275

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package catalyst
2+
3+
import (
4+
"context"
5+
"crypto/sha256"
6+
"errors"
7+
"fmt"
8+
9+
"github.com/ethereum/go-ethereum/beacon/engine"
10+
"github.com/ethereum/go-ethereum/common"
11+
"github.com/ethereum/go-ethereum/crypto/kzg4844"
12+
)
13+
14+
// GetBlobs is a mimic of blobSidecars function (https://github.com/OffchainLabs/nitro/blob/a4b72abd63df46de920580685842491d550dfc20/util/headerreader/blob_client.go#L199)
15+
// in nitro, a mel related system test uses simulated beacon as blob reader, if that were to fail we need to update this function to be similar to the above referenced function
16+
func (c *SimulatedBeacon) GetBlobs(ctx context.Context, batchBlockHash common.Hash, versionedHashes []common.Hash) ([]kzg4844.Blob, error) {
17+
bundle, ok := c.blobsBundleProvider[batchBlockHash]
18+
if !ok {
19+
return nil, errors.New("blobs not found")
20+
}
21+
22+
if len(bundle.Blobs) < len(versionedHashes) {
23+
return nil, fmt.Errorf("expected at least %d blobs but only got %d", len(versionedHashes), len(bundle.Blobs))
24+
}
25+
26+
output := make([]kzg4844.Blob, len(versionedHashes))
27+
outputsFound := make([]bool, len(versionedHashes))
28+
29+
for i := 0; i < len(bundle.Blobs); i++ {
30+
var commitment kzg4844.Commitment
31+
copy(commitment[:], bundle.Commitments[i])
32+
versionedHash := commitmentToVersionedHash(commitment)
33+
34+
// The versioned hashes of the blob commitments are produced in the by HASH_OPCODE_BYTE,
35+
// presumably in the order they were added to the tx. The spec is unclear if the blobs
36+
// need to be returned in any particular order from the beacon API, so we put them back in
37+
// the order from the tx.
38+
var outputIdx int
39+
var found bool
40+
for outputIdx = range versionedHashes {
41+
if versionedHashes[outputIdx] == versionedHash {
42+
if outputsFound[outputIdx] {
43+
// Duplicate, skip this one
44+
break
45+
}
46+
found = true
47+
outputsFound[outputIdx] = true
48+
break
49+
}
50+
}
51+
if !found {
52+
continue
53+
}
54+
55+
copy(output[outputIdx][:], bundle.Blobs[i])
56+
57+
var proof kzg4844.Proof
58+
copy(proof[:], bundle.Proofs[i])
59+
60+
if err := kzg4844.VerifyBlobProof(&output[outputIdx], commitment, proof); err != nil {
61+
return nil, fmt.Errorf("failed to verify blob proof for blob index(%d), blob(%s)", i, firstFewChars(bundle.Blobs[i].String()))
62+
}
63+
}
64+
65+
for i, found := range outputsFound {
66+
if !found {
67+
return nil, fmt.Errorf("missing blob %v, can't reconstruct batch payload", versionedHashes[i])
68+
}
69+
}
70+
71+
return output, nil
72+
}
73+
74+
func (c *SimulatedBeacon) Initialize(ctx context.Context) error {
75+
c.blobsBundleProvider = make(map[common.Hash]*engine.BlobsBundleV1)
76+
return nil
77+
}
78+
79+
func commitmentToVersionedHash(commitment kzg4844.Commitment) common.Hash {
80+
// As per the EIP-4844 spec, the versioned hash is the SHA-256 hash of the commitment with the first byte set to 1.
81+
hash := sha256.Sum256(commitment[:])
82+
hash[0] = 1
83+
return hash
84+
}
85+
86+
func firstFewChars(s string) string {
87+
if len(s) < 9 {
88+
return fmt.Sprintf("\"%s\"", s)
89+
} else {
90+
return fmt.Sprintf("\"%s...\"", s[:8])
91+
}
92+
}

0 commit comments

Comments
 (0)