Skip to content

Commit fd1af89

Browse files
authored
Merge pull request #198 from covalenthq/develop
Complete EIP-4844 blob export support (Ethereum Migration v1.5)
2 parents 82b1d1f + b720ac5 commit fd1af89

File tree

11 files changed

+172
-75
lines changed

11 files changed

+172
-75
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,4 @@ logs/
5656
coverage.out
5757
coverage.txt
5858
tests/spec-tests/
59+
bin/

cmd/geth/chaincmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
104104
utils.BlockReplicationTargetsFlag,
105105
utils.ReplicaEnableSpecimenFlag,
106106
utils.ReplicaEnableResultFlag,
107+
utils.ReplicaEnableBlobFlag,
107108
}, utils.DatabaseFlags),
108109
Description: `
109110
The import command imports blocks from an RLP-encoded form. The form can be one file

cmd/geth/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ var (
149149
utils.BlockReplicationTargetsFlag,
150150
utils.ReplicaEnableResultFlag,
151151
utils.ReplicaEnableSpecimenFlag,
152+
utils.ReplicaEnableBlobFlag,
152153
}, utils.NetworkFlags, utils.DatabaseFlags)
153154

154155
rpcFlags = []cli.Flag{

cmd/utils/flags.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,10 @@ var (
694694
Name: "replica.result",
695695
Usage: "Enables export of fields that comprise a block-result",
696696
}
697+
ReplicaEnableBlobFlag = &cli.BoolFlag{
698+
Name: "replica.blob",
699+
Usage: "Enables export of fields that comprise a block-blob",
700+
}
697701
BatchRequestLimit = &cli.IntFlag{
698702
Name: "rpc.batch-request-limit",
699703
Usage: "Maximum number of requests in a batch",
@@ -2188,8 +2192,11 @@ func setBlockReplicationTargets(ctx *cli.Context, cfg *eth.Config) {
21882192
if ctx.Bool(ReplicaEnableResultFlag.Name) {
21892193
cfg.ReplicaEnableResult = true
21902194
}
2195+
if ctx.Bool(ReplicaEnableBlobFlag.Name) {
2196+
cfg.ReplicaEnableBlob = true
2197+
}
21912198
} else {
2192-
Fatalf("--replication.targets flag is invalid without --replica.specimen and/or --replica.result")
2199+
Fatalf("--replication.targets flag is invalid without --replica.specimen and/or --replica.result, ONLY ADD --replica.blob with both replica.specimen AND replica.result flags for complete unified state capture)")
21932200
}
21942201
}
21952202

core/block_replica.go

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,23 @@ type BlockReplicationEvent struct {
2121
}
2222

2323
func (bc *BlockChain) createBlockReplica(block *types.Block, replicaConfig *ReplicaConfig, chainConfig *params.ChainConfig, stateSpecimen *types.StateSpecimen) error {
24-
//block replica
25-
exportBlockReplica, err := bc.createReplica(block, replicaConfig, chainConfig, stateSpecimen)
24+
25+
// blobs
26+
var blobTxSidecars []*types.BlobTxSidecar
27+
if replicaConfig.EnableBlob {
28+
for sidecarData := range types.BlobTxSidecarChan {
29+
if sidecarData.BlockNumber.Uint64() == block.NumberU64() {
30+
log.Info("Consuming BlobTxSidecar Match From Chain Sync Channel", "Block Number:", sidecarData.BlockNumber.Uint64())
31+
blobTxSidecars = append(blobTxSidecars, sidecarData.Blobs)
32+
} else {
33+
log.Info("Failing BlobTxSidecar Match from Chain Sync Channel", "Block Number:", sidecarData.BlockNumber.Uint64())
34+
}
35+
log.Info("BlobTxSidecar Header", "Block Number:", sidecarData.BlockNumber.Uint64())
36+
log.Info("Chain Sync Sidecar Channel", "Length:", len(types.BlobTxSidecarChan))
37+
}
38+
}
39+
//block replica with blobs
40+
exportBlockReplica, err := bc.createReplica(block, replicaConfig, chainConfig, stateSpecimen, blobTxSidecars)
2641
if err != nil {
2742
return err
2843
}
@@ -50,7 +65,7 @@ func (bc *BlockChain) createBlockReplica(block *types.Block, replicaConfig *Repl
5065
}
5166
}
5267

53-
func (bc *BlockChain) createReplica(block *types.Block, replicaConfig *ReplicaConfig, chainConfig *params.ChainConfig, stateSpecimen *types.StateSpecimen) (*types.ExportBlockReplica, error) {
68+
func (bc *BlockChain) createReplica(block *types.Block, replicaConfig *ReplicaConfig, chainConfig *params.ChainConfig, stateSpecimen *types.StateSpecimen, blobSpecimen []*types.BlobTxSidecar) (*types.ExportBlockReplica, error) {
5469
bHash := block.Hash()
5570
bNum := block.NumberU64()
5671

@@ -117,55 +132,58 @@ func (bc *BlockChain) createReplica(block *types.Block, replicaConfig *ReplicaCo
117132
uncles := block.Uncles()
118133

119134
//block replica export
120-
if replicaConfig.EnableSpecimen && replicaConfig.EnableResult {
135+
if replicaConfig.EnableSpecimen && replicaConfig.EnableResult && replicaConfig.EnableBlob {
121136
exportBlockReplica := &types.ExportBlockReplica{
122-
Type: "block-replica",
123-
NetworkId: chainConfig.ChainID.Uint64(),
124-
Hash: bHash,
125-
TotalDiff: td,
126-
Header: header,
127-
Transactions: txsRlp,
128-
Uncles: uncles,
129-
Receipts: receiptsRlp,
130-
Senders: senders,
131-
State: stateSpecimen,
132-
Withdrawals: withdrawalsRlp,
137+
Type: "block-replica",
138+
NetworkId: chainConfig.ChainID.Uint64(),
139+
Hash: bHash,
140+
TotalDiff: td,
141+
Header: header,
142+
Transactions: txsRlp,
143+
Uncles: uncles,
144+
Receipts: receiptsRlp,
145+
Senders: senders,
146+
State: stateSpecimen,
147+
Withdrawals: withdrawalsRlp,
148+
BlobTxSidecars: blobSpecimen,
133149
}
134-
log.Debug("Exporting full block-replica")
150+
log.Debug("Exporting full block-replica with blob-specimen")
135151
return exportBlockReplica, nil
136152
} else if replicaConfig.EnableSpecimen && !replicaConfig.EnableResult {
137153
exportBlockReplica := &types.ExportBlockReplica{
138-
Type: "block-specimen",
139-
NetworkId: chainConfig.ChainID.Uint64(),
140-
Hash: bHash,
141-
TotalDiff: td,
142-
Header: header,
143-
Transactions: txsRlp,
144-
Uncles: uncles,
145-
Receipts: []*types.ReceiptExportRLP{},
146-
Senders: senders,
147-
State: stateSpecimen,
148-
Withdrawals: withdrawalsRlp,
154+
Type: "block-specimen",
155+
NetworkId: chainConfig.ChainID.Uint64(),
156+
Hash: bHash,
157+
TotalDiff: td,
158+
Header: header,
159+
Transactions: txsRlp,
160+
Uncles: uncles,
161+
Receipts: []*types.ReceiptExportRLP{},
162+
Senders: senders,
163+
State: stateSpecimen,
164+
Withdrawals: withdrawalsRlp,
165+
BlobTxSidecars: []*types.BlobTxSidecar{},
149166
}
150-
log.Debug("Exporting block-specimen only")
167+
log.Debug("Exporting block-specimen only (no blob specimens)")
151168
return exportBlockReplica, nil
152169
} else if !replicaConfig.EnableSpecimen && replicaConfig.EnableResult {
153170
exportBlockReplica := &types.ExportBlockReplica{
154-
Type: "block-result",
155-
NetworkId: chainConfig.ChainID.Uint64(),
156-
Hash: bHash,
157-
TotalDiff: td,
158-
Header: header,
159-
Transactions: txsRlp,
160-
Uncles: uncles,
161-
Receipts: receiptsRlp,
162-
Senders: senders,
163-
State: &types.StateSpecimen{},
171+
Type: "block-result",
172+
NetworkId: chainConfig.ChainID.Uint64(),
173+
Hash: bHash,
174+
TotalDiff: td,
175+
Header: header,
176+
Transactions: txsRlp,
177+
Uncles: uncles,
178+
Receipts: receiptsRlp,
179+
Senders: senders,
180+
State: &types.StateSpecimen{},
181+
BlobTxSidecars: []*types.BlobTxSidecar{},
164182
}
165-
log.Debug("Exporting block-result only")
183+
log.Debug("Exporting block-result only (no blob specimens)")
166184
return exportBlockReplica, nil
167185
} else {
168-
return nil, fmt.Errorf("--replication.targets flag is invalid without --replica.specimen and/or --replica.result")
186+
return nil, fmt.Errorf("--replication.targets flag is invalid without --replica.specimen and/or --replica.result, ADD --replica.blob with both replica.specimen AND replica.result flags for complete unified state capture aka block-replica)")
169187
}
170188
}
171189

@@ -181,5 +199,8 @@ func (bc *BlockChain) SetBlockReplicaExports(replicaConfig *ReplicaConfig) bool
181199
if replicaConfig.EnableSpecimen {
182200
bc.ReplicaConfig.EnableSpecimen = true
183201
}
202+
if replicaConfig.EnableBlob {
203+
bc.ReplicaConfig.EnableBlob = true
204+
}
184205
return true
185206
}

core/blockchain.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ type BlockChain struct {
267267
type ReplicaConfig struct {
268268
EnableSpecimen bool
269269
EnableResult bool
270+
EnableBlob bool
270271
HistoricalBlocksSynced *uint32
271272
}
272273

@@ -315,6 +316,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
315316
ReplicaConfig: &ReplicaConfig{
316317
EnableSpecimen: false,
317318
EnableResult: false,
319+
EnableBlob: false,
318320
HistoricalBlocksSynced: new(uint32), // Always set 0 for historical mode at start
319321
},
320322
}
@@ -1851,7 +1853,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
18511853

18521854
if !setHead {
18531855
// Export Block Specimen
1854-
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1856+
if bc.ReplicaConfig.EnableSpecimen || bc.ReplicaConfig.EnableResult {
1857+
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1858+
}
18551859
// After merge we expect few side chains. Simply count
18561860
// all blocks the CL gives us for GC processing time
18571861
bc.gcproc += proctime
@@ -1865,7 +1869,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
18651869
"elapsed", common.PrettyDuration(time.Since(start)),
18661870
"root", block.Root())
18671871
// Handle creation of block specimen for canonical blocks
1868-
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1872+
if bc.ReplicaConfig.EnableSpecimen || bc.ReplicaConfig.EnableResult {
1873+
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1874+
}
18691875
lastCanon = block
18701876

18711877
// Only count canonical blocks for GC processing time
@@ -1887,7 +1893,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
18871893
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
18881894
"root", block.Root())
18891895
// Is impossible but keeping in line to be nice to our future selves we add this for now
1890-
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1896+
if bc.ReplicaConfig.EnableSpecimen || bc.ReplicaConfig.EnableResult {
1897+
bc.createBlockReplica(block, bc.ReplicaConfig, bc.chainConfig, statedb.TakeStateSpecimen())
1898+
}
18911899
}
18921900
}
18931901

core/types/block_export.go

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ import (
88
)
99

1010
type ExportBlockReplica struct {
11-
Type string
12-
NetworkId uint64
13-
Hash common.Hash
14-
TotalDiff *big.Int
15-
Header *Header
16-
Transactions []*TransactionExportRLP
17-
Uncles []*Header
18-
Receipts []*ReceiptExportRLP
19-
Senders []common.Address
20-
State *StateSpecimen
21-
Withdrawals []*WithdrawalExportRLP
11+
Type string
12+
NetworkId uint64
13+
Hash common.Hash
14+
TotalDiff *big.Int
15+
Header *Header
16+
Transactions []*TransactionExportRLP
17+
Uncles []*Header
18+
Receipts []*ReceiptExportRLP
19+
Senders []common.Address
20+
State *StateSpecimen
21+
Withdrawals []*WithdrawalExportRLP
22+
BlobTxSidecars []*BlobTxSidecar
2223
}
2324

2425
type LogsExportRLP struct {
@@ -71,8 +72,18 @@ type TransactionExportRLP struct {
7172
V *big.Int `json:"v" rlp:"nil"`
7273
R *big.Int `json:"r" rlp:"nil"`
7374
S *big.Int `json:"s" rlp:"nil"`
75+
BlobFeeCap *big.Int `json:"blobFeeCap" rlp:"optional"`
76+
BlobHashes []common.Hash `json:"blobHashes" rlp:"optional"`
77+
BlobGas uint64 `json:"blobGas" rlp:"optional"`
7478
}
7579

80+
type BlobTxSidecarData struct {
81+
Blobs *BlobTxSidecar
82+
BlockNumber *big.Int
83+
}
84+
85+
var BlobTxSidecarChan = make(chan *BlobTxSidecarData, 100)
86+
7687
func (r *ReceiptForExport) ExportReceipt() *ReceiptExportRLP {
7788
enc := &ReceiptExportRLP{
7889
PostStateOrStatus: (*Receipt)(r).statusEncoding(),
@@ -105,21 +116,47 @@ func (tx *TransactionForExport) ExportTx(chainConfig *params.ChainConfig, blockN
105116

106117
txData := tx.inner
107118

108-
return &TransactionExportRLP{
109-
AccountNonce: txData.nonce(),
110-
Price: txData.effectiveGasPrice(&big.Int{}, baseFee),
111-
GasLimit: txData.gas(),
112-
Sender: &from,
113-
Recipient: txData.to(),
114-
Amount: txData.value(),
115-
Payload: txData.data(),
116-
Type: txData.txType(),
117-
ChainId: txData.chainID(),
118-
AccessList: txData.accessList(),
119-
GasTipCap: txData.gasTipCap(),
120-
GasFeeCap: txData.gasFeeCap(),
121-
V: v,
122-
R: r,
123-
S: s,
119+
if inner_tx.Type() == BlobTxType {
120+
return &TransactionExportRLP{
121+
AccountNonce: txData.nonce(),
122+
Price: txData.effectiveGasPrice(&big.Int{}, baseFee),
123+
GasLimit: txData.gas(),
124+
Sender: &from,
125+
Recipient: txData.to(),
126+
Amount: txData.value(),
127+
Payload: txData.data(),
128+
Type: txData.txType(),
129+
ChainId: txData.chainID(),
130+
AccessList: txData.accessList(),
131+
GasTipCap: txData.gasTipCap(),
132+
GasFeeCap: txData.gasFeeCap(),
133+
V: v,
134+
R: r,
135+
S: s,
136+
BlobFeeCap: inner_tx.BlobGasFeeCap(),
137+
BlobHashes: inner_tx.BlobHashes(),
138+
BlobGas: inner_tx.BlobGas(),
139+
}
140+
} else {
141+
return &TransactionExportRLP{
142+
AccountNonce: txData.nonce(),
143+
Price: txData.effectiveGasPrice(&big.Int{}, baseFee),
144+
GasLimit: txData.gas(),
145+
Sender: &from,
146+
Recipient: txData.to(),
147+
Amount: txData.value(),
148+
Payload: txData.data(),
149+
Type: txData.txType(),
150+
ChainId: txData.chainID(),
151+
AccessList: txData.accessList(),
152+
GasTipCap: txData.gasTipCap(),
153+
GasFeeCap: txData.gasFeeCap(),
154+
V: v,
155+
R: r,
156+
S: s,
157+
BlobFeeCap: &big.Int{},
158+
BlobHashes: make([]common.Hash, 0),
159+
BlobGas: 0,
160+
}
124161
}
125162
}

eth/backend.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
177177
ReplicaConfig: &core.ReplicaConfig{
178178
EnableSpecimen: config.ReplicaEnableSpecimen,
179179
EnableResult: config.ReplicaEnableResult,
180+
EnableBlob: config.ReplicaEnableBlob,
180181
HistoricalBlocksSynced: new(uint32), // Always set 0 for historical mode at start
181182
},
182183
}
@@ -186,7 +187,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
186187
if err != nil {
187188
return nil, err
188189
}
189-
log.Info("Block replication started", "targets", targets, "network ID", config.NetworkId, "export block-specimen", eth.ReplicaConfig.EnableSpecimen, "export block-result", eth.ReplicaConfig.EnableResult)
190+
log.Info("Block replication started", "targets", targets, "network ID", config.NetworkId, "export block-specimen", eth.ReplicaConfig.EnableSpecimen, "export block-result", eth.ReplicaConfig.EnableResult, "export blob-specimen", eth.ReplicaConfig.EnableBlob)
190191
eth.blockReplicators = append(eth.blockReplicators, replicator)
191192
}
192193
bcVersion := rawdb.ReadDatabaseVersion(chainDb)

eth/ethconfig/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ type Config struct {
160160
// Bools that make explicit types being exported
161161
ReplicaEnableResult bool
162162
ReplicaEnableSpecimen bool
163+
ReplicaEnableBlob bool
163164

164165
// OverrideCancun (TODO: remove after the fork)
165166
OverrideCancun *uint64 `toml:",omitempty"`

0 commit comments

Comments
 (0)