mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
Merge branch 'master' into multicall
This commit is contained in:
commit
24151101bb
70 changed files with 1159 additions and 461 deletions
|
|
@ -34,6 +34,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
var enc ExecutableData
|
var enc ExecutableData
|
||||||
|
|
@ -59,6 +60,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||||
enc.Withdrawals = e.Withdrawals
|
enc.Withdrawals = e.Withdrawals
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||||
|
enc.Deposits = e.Deposits
|
||||||
enc.ExecutionWitness = e.ExecutionWitness
|
enc.ExecutionWitness = e.ExecutionWitness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
@ -83,6 +85,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits *types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
var dec ExecutableData
|
var dec ExecutableData
|
||||||
|
|
@ -157,6 +160,9 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ExcessBlobGas != nil {
|
if dec.ExcessBlobGas != nil {
|
||||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
|
if dec.Deposits != nil {
|
||||||
|
e.Deposits = *dec.Deposits
|
||||||
|
}
|
||||||
if dec.ExecutionWitness != nil {
|
if dec.ExecutionWitness != nil {
|
||||||
e.ExecutionWitness = dec.ExecutionWitness
|
e.ExecutionWitness = dec.ExecutionWitness
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ var (
|
||||||
PayloadV1 PayloadVersion = 0x1
|
PayloadV1 PayloadVersion = 0x1
|
||||||
PayloadV2 PayloadVersion = 0x2
|
PayloadV2 PayloadVersion = 0x2
|
||||||
PayloadV3 PayloadVersion = 0x3
|
PayloadV3 PayloadVersion = 0x3
|
||||||
|
PayloadV4 PayloadVersion = 0x4
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||||
|
|
@ -76,6 +77,7 @@ type ExecutableData struct {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,6 +233,19 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
||||||
withdrawalsRoot = &h
|
withdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
|
// Compute requestsHash if any requests are non-nil.
|
||||||
|
var (
|
||||||
|
requestsHash *common.Hash
|
||||||
|
requests types.Requests
|
||||||
|
)
|
||||||
|
if data.Deposits != nil {
|
||||||
|
requests = make(types.Requests, 0)
|
||||||
|
for _, d := range data.Deposits {
|
||||||
|
requests = append(requests, types.NewRequest(d))
|
||||||
|
}
|
||||||
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
|
requestsHash = &h
|
||||||
|
}
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: data.ParentHash,
|
ParentHash: data.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
|
@ -251,9 +266,10 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
ExcessBlobGas: data.ExcessBlobGas,
|
ExcessBlobGas: data.ExcessBlobGas,
|
||||||
BlobGasUsed: data.BlobGasUsed,
|
BlobGasUsed: data.BlobGasUsed,
|
||||||
ParentBeaconRoot: beaconRoot,
|
ParentBeaconRoot: beaconRoot,
|
||||||
|
RequestsHash: requestsHash,
|
||||||
}
|
}
|
||||||
block := types.NewBlockWithHeader(header)
|
block := types.NewBlockWithHeader(header)
|
||||||
block = block.WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals})
|
block = block.WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests})
|
||||||
block = block.WithWitness(data.ExecutionWitness)
|
block = block.WithWitness(data.ExecutionWitness)
|
||||||
if block.Hash() != data.BlockHash {
|
if block.Hash() != data.BlockHash {
|
||||||
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
||||||
|
|
@ -296,13 +312,30 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
||||||
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setRequests(block.Requests(), data)
|
||||||
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
|
// setRequests differentiates the different request types and
|
||||||
type ExecutionPayloadBodyV1 struct {
|
// assigns them to the associated fields in ExecutableData.
|
||||||
|
func setRequests(requests types.Requests, data *ExecutableData) {
|
||||||
|
if requests != nil {
|
||||||
|
// If requests is non-nil, it means deposits are available in block and we
|
||||||
|
// should return an empty slice instead of nil if there are no deposits.
|
||||||
|
data.Deposits = make(types.Deposits, 0)
|
||||||
|
}
|
||||||
|
for _, r := range requests {
|
||||||
|
if d, ok := r.Inner().(*types.Deposit); ok {
|
||||||
|
data.Deposits = append(data.Deposits, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecutionPayloadBody is used in the response to GetPayloadBodiesByHash and GetPayloadBodiesByRange
|
||||||
|
type ExecutionPayloadBody struct {
|
||||||
TransactionData []hexutil.Bytes `json:"transactions"`
|
TransactionData []hexutil.Bytes `json:"transactions"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ type ExecutionResult struct {
|
||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
|
||||||
|
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
|
|
@ -377,6 +379,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
|
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
||||||
|
// Parse the requests from the logs
|
||||||
|
var allLogs []*types.Log
|
||||||
|
for _, receipt := range receipts {
|
||||||
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
|
}
|
||||||
|
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
||||||
|
}
|
||||||
|
// Calculate the requests root
|
||||||
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
|
execRs.RequestsHash = &h
|
||||||
|
// Get the deposits from the requests
|
||||||
|
deposits := make(types.Deposits, 0)
|
||||||
|
for _, req := range requests {
|
||||||
|
if dep, ok := req.Inner().(*types.Deposit); ok {
|
||||||
|
deposits = append(deposits, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execRs.DepositRequests = &deposits
|
||||||
|
}
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
statedb, err = state.New(root, statedb.Database(), nil)
|
statedb, err = state.New(root, statedb.Database(), nil)
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,6 @@ func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, networ
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
reported = time.Now()
|
reported = time.Now()
|
||||||
imported = 0
|
imported = 0
|
||||||
forker = core.NewForkChoice(chain, nil)
|
|
||||||
h = sha256.New()
|
h = sha256.New()
|
||||||
buf = bytes.NewBuffer(nil)
|
buf = bytes.NewBuffer(nil)
|
||||||
)
|
)
|
||||||
|
|
@ -305,7 +304,7 @@ func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, networ
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
|
return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
|
||||||
}
|
}
|
||||||
if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start, forker); err != nil {
|
if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start); err != nil {
|
||||||
return fmt.Errorf("error inserting header %d: %w", it.Number(), err)
|
return fmt.Errorf("error inserting header %d: %w", it.Number(), err)
|
||||||
} else if status != core.CanonStatTy {
|
} else if status != core.CanonStatTy {
|
||||||
return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status)
|
return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status)
|
||||||
|
|
|
||||||
|
|
@ -2210,7 +2210,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disable transaction indexing/unindexing by default.
|
// Disable transaction indexing/unindexing by default.
|
||||||
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
|
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Can't create BlockChain: %v", err)
|
Fatalf("Can't create BlockChain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Initialize BlockChain.
|
// Initialize BlockChain.
|
||||||
chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to initialize chain: %v", err)
|
t.Fatalf("unable to initialize chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +171,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
|
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||||
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to initialize chain: %v", err)
|
t.Fatalf("unable to initialize chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
copy(genspec.ExtraData[extraVanity:], addr[:])
|
copy(genspec.ExtraData[extraVanity:], addr[:])
|
||||||
|
|
||||||
// Generate a batch of blocks, each properly signed
|
// Generate a batch of blocks, each properly signed
|
||||||
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil, nil)
|
chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
|
_, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) {
|
||||||
|
|
@ -87,7 +87,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Insert the first two blocks and make sure the chain is valid
|
// Insert the first two blocks and make sure the chain is valid
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
|
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
if _, err := chain.InsertChain(blocks[:2]); err != nil {
|
if _, err := chain.InsertChain(blocks[:2]); err != nil {
|
||||||
|
|
@ -100,7 +100,7 @@ func TestReimportMirroredState(t *testing.T) {
|
||||||
// Simulate a crash by creating a new chain on top of the database, without
|
// Simulate a crash by creating a new chain on top of the database, without
|
||||||
// flushing the dirty states out. Insert the last block, triggering a sidechain
|
// flushing the dirty states out. Insert the last block, triggering a sidechain
|
||||||
// reimport.
|
// reimport.
|
||||||
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
|
chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
if _, err := chain.InsertChain(blocks[2:]); err != nil {
|
if _, err := chain.InsertChain(blocks[2:]); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -458,7 +458,7 @@ func (tt *cliqueTest) run(t *testing.T) {
|
||||||
batches[len(batches)-1] = append(batches[len(batches)-1], block)
|
batches[len(batches)-1] = append(batches[len(batches)-1], block)
|
||||||
}
|
}
|
||||||
// Pass all the headers through clique and ensure tallying succeeds
|
// Pass all the headers through clique and ensure tallying succeeds
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create test chain: %v", err)
|
t.Fatalf("failed to create test chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
|
|
||||||
// Time the insertion of the new chain.
|
// Time the insertion of the new chain.
|
||||||
// State and blocks are stored in the same DB.
|
// State and blocks are stored in the same DB.
|
||||||
chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer chainman.Stop()
|
defer chainman.Stop()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -312,7 +312,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,14 +121,17 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
|
|
||||||
// ValidateState validates the various changes that happen after a state transition,
|
// ValidateState validates the various changes that happen after a state transition,
|
||||||
// such as amount of used gas, the receipt roots and the state root itself.
|
// such as amount of used gas, the receipt roots and the state root itself.
|
||||||
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, stateless bool) error {
|
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
||||||
|
if res == nil {
|
||||||
|
return fmt.Errorf("nil ProcessResult value")
|
||||||
|
}
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if block.GasUsed() != usedGas {
|
if block.GasUsed() != res.GasUsed {
|
||||||
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
|
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), res.GasUsed)
|
||||||
}
|
}
|
||||||
// Validate the received block's bloom with the one derived from the generated receipts.
|
// Validate the received block's bloom with the one derived from the generated receipts.
|
||||||
// For valid blocks this should always validate to true.
|
// For valid blocks this should always validate to true.
|
||||||
rbloom := types.CreateBloom(receipts)
|
rbloom := types.CreateBloom(res.Receipts)
|
||||||
if rbloom != header.Bloom {
|
if rbloom != header.Bloom {
|
||||||
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
|
||||||
}
|
}
|
||||||
|
|
@ -138,10 +141,17 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
// The receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
|
||||||
receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
receiptSha := types.DeriveSha(res.Receipts, trie.NewStackTrie(nil))
|
||||||
if receiptSha != header.ReceiptHash {
|
if receiptSha != header.ReceiptHash {
|
||||||
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
|
||||||
}
|
}
|
||||||
|
// Validate the parsed requests match the expected header value.
|
||||||
|
if header.RequestsHash != nil {
|
||||||
|
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
|
||||||
|
if depositSha != *header.RequestsHash {
|
||||||
|
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Validate the state root against the received state root and throw
|
// Validate the state root against the received state root and throw
|
||||||
// an error if they don't match.
|
// an error if they don't match.
|
||||||
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func testHeaderVerification(t *testing.T, scheme string) {
|
||||||
headers[i] = block.Header()
|
headers[i] = block.Header()
|
||||||
}
|
}
|
||||||
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
||||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
for i := 0; i < len(blocks); i++ {
|
for i := 0; i < len(blocks); i++ {
|
||||||
|
|
@ -160,7 +160,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
||||||
postHeaders[i] = block.Header()
|
postHeaders[i] = block.Header()
|
||||||
}
|
}
|
||||||
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
|
||||||
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
defer chain.Stop()
|
defer chain.Stop()
|
||||||
|
|
||||||
// Verify the blocks before the merging
|
// Verify the blocks before the merging
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,6 @@ type BlockChain struct {
|
||||||
validator Validator // Block and state validator interface
|
validator Validator // Block and state validator interface
|
||||||
prefetcher Prefetcher
|
prefetcher Prefetcher
|
||||||
processor Processor // Block transaction processor interface
|
processor Processor // Block transaction processor interface
|
||||||
forker *ForkChoice
|
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
logger *tracing.Hooks
|
logger *tracing.Hooks
|
||||||
}
|
}
|
||||||
|
|
@ -267,7 +266,7 @@ type BlockChain struct {
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
// available in the database. It initialises the default Ethereum Validator
|
// available in the database. It initialises the default Ethereum Validator
|
||||||
// and Processor.
|
// and Processor.
|
||||||
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) {
|
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, txLookupLimit *uint64) (*BlockChain, error) {
|
||||||
if cacheConfig == nil {
|
if cacheConfig == nil {
|
||||||
cacheConfig = defaultCacheConfig
|
cacheConfig = defaultCacheConfig
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +311,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit))
|
||||||
bc.forker = NewForkChoice(bc, shouldPreserve)
|
|
||||||
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb)
|
||||||
bc.validator = NewBlockValidator(chainConfig, bc)
|
bc.validator = NewBlockValidator(chainConfig, bc)
|
||||||
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
bc.prefetcher = newStatePrefetcher(chainConfig, bc.hc)
|
||||||
|
|
@ -1243,13 +1241,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
|
|
||||||
// Rewind may have occurred, skip in that case.
|
// Rewind may have occurred, skip in that case.
|
||||||
if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 {
|
if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 {
|
||||||
reorg, err := bc.forker.ReorgNeeded(bc.CurrentSnapBlock(), head.Header())
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Reorg failed", "err", err)
|
|
||||||
return false
|
|
||||||
} else if !reorg {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
|
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
|
||||||
bc.currentSnapBlock.Store(head.Header())
|
bc.currentSnapBlock.Store(head.Header())
|
||||||
headFastBlockGauge.Update(int64(head.NumberU64()))
|
headFastBlockGauge.Update(int64(head.NumberU64()))
|
||||||
|
|
@ -1548,42 +1539,30 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
currentBlock := bc.CurrentBlock()
|
currentBlock := bc.CurrentBlock()
|
||||||
reorg, err := bc.forker.ReorgNeeded(currentBlock, block.Header())
|
|
||||||
if err != nil {
|
// Reorganise the chain if the parent is not the head block
|
||||||
return NonStatTy, err
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
}
|
if err := bc.reorg(currentBlock, block); err != nil {
|
||||||
if reorg {
|
return NonStatTy, err
|
||||||
// Reorganise the chain if the parent is not the head block
|
|
||||||
if block.ParentHash() != currentBlock.Hash() {
|
|
||||||
if err := bc.reorg(currentBlock, block); err != nil {
|
|
||||||
return NonStatTy, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
status = CanonStatTy
|
|
||||||
} else {
|
|
||||||
status = SideStatTy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set new head.
|
// Set new head.
|
||||||
if status == CanonStatTy {
|
bc.writeHeadBlock(block)
|
||||||
bc.writeHeadBlock(block)
|
|
||||||
|
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
|
||||||
|
if len(logs) > 0 {
|
||||||
|
bc.logsFeed.Send(logs)
|
||||||
}
|
}
|
||||||
if status == CanonStatTy {
|
// In theory, we should fire a ChainHeadEvent when we inject
|
||||||
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
|
// a canonical block, but sometimes we can insert a batch of
|
||||||
if len(logs) > 0 {
|
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
||||||
bc.logsFeed.Send(logs)
|
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||||
}
|
// event here.
|
||||||
// In theory, we should fire a ChainHeadEvent when we inject
|
if emitHeadEvent {
|
||||||
// a canonical block, but sometimes we can insert a batch of
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||||
// canonical blocks. Avoid firing too many ChainHeadEvents,
|
|
||||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
|
||||||
// event here.
|
|
||||||
if emitHeadEvent {
|
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
|
|
||||||
}
|
}
|
||||||
return status, nil
|
return CanonStatTy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertChain attempts to insert the given batch of blocks in to the canonical
|
// InsertChain attempts to insert the given batch of blocks in to the canonical
|
||||||
|
|
@ -1634,7 +1613,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||||
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
|
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
|
||||||
|
|
||||||
|
|
@ -1667,24 +1645,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
// 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
|
// 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
|
||||||
// from the canonical chain, which has not been verified.
|
// from the canonical chain, which has not been verified.
|
||||||
// Skip all known blocks that are behind us.
|
// Skip all known blocks that are behind us.
|
||||||
var (
|
current := bc.CurrentBlock()
|
||||||
reorg bool
|
|
||||||
current = bc.CurrentBlock()
|
|
||||||
)
|
|
||||||
for block != nil && bc.skipBlock(err, it) {
|
for block != nil && bc.skipBlock(err, it) {
|
||||||
reorg, err = bc.forker.ReorgNeeded(current, block.Header())
|
if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() {
|
||||||
if err != nil {
|
break
|
||||||
return it.index, err
|
|
||||||
}
|
|
||||||
if reorg {
|
|
||||||
// Switch to import mode if the forker says the reorg is necessary
|
|
||||||
// and also the block is not on the canonical chain.
|
|
||||||
// In eth2 the forker always returns true for reorg decision (blindly trusting
|
|
||||||
// the external consensus engine), but in order to prevent the unnecessary
|
|
||||||
// reorgs when importing known blocks, the special case is handled here.
|
|
||||||
if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.Debug("Ignoring already known block", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Ignoring already known block", "number", block.Number(), "hash", block.Hash())
|
||||||
stats.ignored++
|
stats.ignored++
|
||||||
|
|
@ -1927,23 +1891,23 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
|
|
||||||
// Process block using the parent state as reference point
|
// Process block using the parent state as reference point
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
|
res, err := bc.processor.Process(block, statedb, bc.vmConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ptime := time.Since(pstart)
|
ptime := time.Since(pstart)
|
||||||
|
|
||||||
vstart := time.Now()
|
vstart := time.Now()
|
||||||
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
if err := bc.validator.ValidateState(block, statedb, res, false); err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
|
|
||||||
if witness := statedb.Witness(); witness != nil {
|
if witness := statedb.Witness(); witness != nil {
|
||||||
if err = bc.validator.ValidateWitness(witness, block.ReceiptHash(), block.Root()); err != nil {
|
if err = bc.validator.ValidateWitness(witness, block.ReceiptHash(), block.Root()); err != nil {
|
||||||
bc.reportBlock(block, receipts, err)
|
bc.reportBlock(block, res, err)
|
||||||
return nil, fmt.Errorf("cross verification failed: %v", err)
|
return nil, fmt.Errorf("cross verification failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1978,9 +1942,9 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
)
|
)
|
||||||
if !setHead {
|
if !setHead {
|
||||||
// Don't set the head, only insert the block
|
// Don't set the head, only insert the block
|
||||||
err = bc.writeBlockWithState(block, receipts, statedb)
|
err = bc.writeBlockWithState(block, res.Receipts, statedb)
|
||||||
} else {
|
} else {
|
||||||
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
|
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -1994,7 +1958,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits)
|
||||||
blockInsertTimer.UpdateSince(start)
|
blockInsertTimer.UpdateSince(start)
|
||||||
|
|
||||||
return &blockProcessingResult{usedGas: usedGas, procTime: proctime, status: status}, nil
|
return &blockProcessingResult{usedGas: res.GasUsed, procTime: proctime, status: status}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
||||||
|
|
@ -2006,9 +1970,8 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
||||||
// insertSideChain is only used pre-merge.
|
// insertSideChain is only used pre-merge.
|
||||||
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) {
|
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) {
|
||||||
var (
|
var (
|
||||||
externTd *big.Int
|
externTd *big.Int
|
||||||
lastBlock = block
|
current = bc.CurrentBlock()
|
||||||
current = bc.CurrentBlock()
|
|
||||||
)
|
)
|
||||||
// The first sidechain block error is already verified to be ErrPrunedAncestor.
|
// The first sidechain block error is already verified to be ErrPrunedAncestor.
|
||||||
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining
|
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining
|
||||||
|
|
@ -2059,22 +2022,6 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||||
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
|
"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
|
||||||
"root", block.Root())
|
"root", block.Root())
|
||||||
}
|
}
|
||||||
lastBlock = block
|
|
||||||
}
|
|
||||||
// At this point, we've written all sidechain blocks to database. Loop ended
|
|
||||||
// either on some other error or all were processed. If there was some other
|
|
||||||
// error, we can ignore the rest of those blocks.
|
|
||||||
//
|
|
||||||
// If the externTd was larger than our local TD, we now need to reimport the previous
|
|
||||||
// blocks to regenerate the required state
|
|
||||||
reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header())
|
|
||||||
if err != nil {
|
|
||||||
return it.index, err
|
|
||||||
}
|
|
||||||
if !reorg {
|
|
||||||
localTd := bc.GetTd(current.Hash(), current.Number.Uint64())
|
|
||||||
log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
|
|
||||||
return it.index, err
|
|
||||||
}
|
}
|
||||||
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
||||||
var (
|
var (
|
||||||
|
|
@ -2491,7 +2438,11 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reportBlock logs a bad block error.
|
// reportBlock logs a bad block error.
|
||||||
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
|
func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err error) {
|
||||||
|
var receipts types.Receipts
|
||||||
|
if res != nil {
|
||||||
|
receipts = res.Receipts
|
||||||
|
}
|
||||||
rawdb.WriteBadBlock(bc.db, block)
|
rawdb.WriteBadBlock(bc.db, block)
|
||||||
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
|
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
|
||||||
}
|
}
|
||||||
|
|
@ -2537,7 +2488,7 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
|
||||||
return 0, errChainStopped
|
return 0, errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
_, err := bc.hc.InsertHeaderChain(chain, start, bc.forker)
|
_, err := bc.hc.InsertHeaderChain(chain, start)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,11 +170,6 @@ func (it *insertIterator) current() *types.Header {
|
||||||
return it.chain[it.index].Header()
|
return it.chain[it.index].Header()
|
||||||
}
|
}
|
||||||
|
|
||||||
// first returns the first block in it.
|
|
||||||
func (it *insertIterator) first() *types.Block {
|
|
||||||
return it.chain[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// remaining returns the number of remaining blocks.
|
// remaining returns the number of remaining blocks.
|
||||||
func (it *insertIterator) remaining() int {
|
func (it *insertIterator) remaining() int {
|
||||||
return len(it.chain) - it.index
|
return len(it.chain) - it.index
|
||||||
|
|
|
||||||
|
|
@ -1794,7 +1794,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
config.SnapshotLimit = 256
|
config.SnapshotLimit = 256
|
||||||
config.SnapshotWait = true
|
config.SnapshotWait = true
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1859,7 +1859,7 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1931,7 +1931,7 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
)
|
)
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1981,7 +1981,7 @@ func testIssue23496(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1997,7 +1997,7 @@ func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme
|
||||||
config.SnapshotLimit = 256
|
config.SnapshotLimit = 256
|
||||||
config.SnapshotWait = true
|
config.SnapshotWait = true
|
||||||
}
|
}
|
||||||
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
|
||||||
}
|
}
|
||||||
engine = ethash.NewFullFaker()
|
engine = ethash.NewFullFaker()
|
||||||
)
|
)
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create chain: %v", err)
|
t.Fatalf("Failed to create chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +228,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
|
||||||
|
|
||||||
// Restart the chain normally
|
// Restart the chain normally
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -270,13 +270,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
// the crash, we do restart twice here: one after the crash and one
|
// the crash, we do restart twice here: one after the crash and one
|
||||||
// after the normal stop. It's used to ensure the broken snapshot
|
// after the normal stop. It's used to ensure the broken snapshot
|
||||||
// can be detected all the time.
|
// can be detected all the time.
|
||||||
newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
newchain.Stop()
|
newchain.Stop()
|
||||||
|
|
||||||
newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -313,7 +313,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
}
|
}
|
||||||
newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +321,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
newchain.Stop()
|
newchain.Stop()
|
||||||
|
|
||||||
// Restart the chain with enabling the snapshot
|
// Restart the chain with enabling the snapshot
|
||||||
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -349,7 +349,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
||||||
chain.SetHead(snaptest.setHead)
|
chain.SetHead(snaptest.setHead)
|
||||||
chain.Stop()
|
chain.Stop()
|
||||||
|
|
||||||
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +385,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
}
|
}
|
||||||
newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -402,7 +402,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
SnapshotWait: false, // Don't wait rebuild
|
SnapshotWait: false, // Don't wait rebuild
|
||||||
StateScheme: snaptest.scheme,
|
StateScheme: snaptest.scheme,
|
||||||
}
|
}
|
||||||
tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +411,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
tmp.triedb.Close()
|
tmp.triedb.Close()
|
||||||
tmp.stopWithoutSaving()
|
tmp.stopWithoutSaving()
|
||||||
|
|
||||||
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
|
newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to recreate chain: %v", err)
|
t.Fatalf("Failed to recreate chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -61,7 +62,7 @@ func newCanonical(engine consensus.Engine, n int, full bool, scheme string) (eth
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
|
|
||||||
// Create and inject the requested chain
|
// Create and inject the requested chain
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
|
|
@ -163,13 +164,14 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{})
|
res, err := blockchain.processor.Process(block, statedb, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
blockchain.reportBlock(block, receipts, err)
|
blockchain.reportBlock(block, res, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, false); err != nil {
|
err = blockchain.validator.ValidateState(block, statedb, res, false)
|
||||||
blockchain.reportBlock(block, receipts, err)
|
if err != nil {
|
||||||
|
blockchain.reportBlock(block, res, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,7 +764,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the chain as an archive node for the comparison baseline
|
// Import the chain as an archive node for the comparison baseline
|
||||||
archiveDb := rawdb.NewMemoryDatabase()
|
archiveDb := rawdb.NewMemoryDatabase()
|
||||||
archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer archive.Stop()
|
defer archive.Stop()
|
||||||
|
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
|
|
@ -770,7 +772,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb := rawdb.NewMemoryDatabase()
|
fastDb := rawdb.NewMemoryDatabase()
|
||||||
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
|
|
@ -790,7 +792,7 @@ func testFastVsFullChains(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
|
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
|
|
||||||
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
||||||
|
|
@ -910,7 +912,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
archiveCaching.TrieDirtyDisabled = true
|
archiveCaching.TrieDirtyDisabled = true
|
||||||
archiveCaching.StateScheme = scheme
|
archiveCaching.StateScheme = scheme
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if n, err := archive.InsertChain(blocks); err != nil {
|
if n, err := archive.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
@ -923,7 +925,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb := makeDb()
|
fastDb := makeDb()
|
||||||
defer fastDb.Close()
|
defer fastDb.Close()
|
||||||
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
|
|
@ -943,7 +945,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
// Import the chain as a ancient-first node and ensure all pointers are updated
|
// Import the chain as a ancient-first node and ensure all pointers are updated
|
||||||
ancientDb := makeDb()
|
ancientDb := makeDb()
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
|
|
||||||
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
if n, err := ancient.InsertHeaderChain(headers); err != nil {
|
||||||
|
|
@ -962,7 +964,7 @@ func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) {
|
||||||
// Import the chain as a light node and ensure all pointers are updated
|
// Import the chain as a light node and ensure all pointers are updated
|
||||||
lightDb := makeDb()
|
lightDb := makeDb()
|
||||||
defer lightDb.Close()
|
defer lightDb.Close()
|
||||||
light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if n, err := light.InsertHeaderChain(headers); err != nil {
|
if n, err := light.InsertHeaderChain(headers); err != nil {
|
||||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
@ -1035,7 +1037,7 @@ func testChainTxReorgs(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||||
}
|
}
|
||||||
|
|
@ -1109,7 +1111,7 @@ func testLogReorgs(t *testing.T, scheme string) {
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
)
|
)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
rmLogsCh := make(chan RemovedLogsEvent)
|
rmLogsCh := make(chan RemovedLogsEvent)
|
||||||
|
|
@ -1165,7 +1167,7 @@ func testLogRebirth(t *testing.T, scheme string) {
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
engine = ethash.NewFaker()
|
engine = ethash.NewFaker()
|
||||||
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
|
@ -1246,7 +1248,7 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
|
@ -1265,7 +1267,7 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
||||||
|
|
||||||
// Generate side chain with lower difficulty
|
// Generate side chain with lower difficulty, after the merge, the chain will be accepted even if it is lower difficulty
|
||||||
genDb, sideChain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) {
|
genDb, sideChain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, logCode), signer, key1)
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, logCode), signer, key1)
|
||||||
|
|
@ -1278,14 +1280,14 @@ func testSideLogRebirth(t *testing.T, scheme string) {
|
||||||
if _, err := blockchain.InsertChain(sideChain); err != nil {
|
if _, err := blockchain.InsertChain(sideChain); err != nil {
|
||||||
t.Fatalf("failed to insert forked chain: %v", err)
|
t.Fatalf("failed to insert forked chain: %v", err)
|
||||||
}
|
}
|
||||||
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
checkLogEvents(t, newLogCh, rmLogsCh, 1, 0)
|
||||||
|
|
||||||
// Generate a new block based on side chain.
|
// Generate a new block based on side chain. Should not emit any events anymore.
|
||||||
newBlocks, _ := GenerateChain(gspec.Config, sideChain[len(sideChain)-1], ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
|
newBlocks, _ := GenerateChain(gspec.Config, sideChain[len(sideChain)-1], ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
|
||||||
if _, err := blockchain.InsertChain(newBlocks); err != nil {
|
if _, err := blockchain.InsertChain(newBlocks); err != nil {
|
||||||
t.Fatalf("failed to insert forked chain: %v", err)
|
t.Fatalf("failed to insert forked chain: %v", err)
|
||||||
}
|
}
|
||||||
checkLogEvents(t, newLogCh, rmLogsCh, 1, 0)
|
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) {
|
func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) {
|
||||||
|
|
@ -1345,7 +1347,7 @@ func testReorgSideEvent(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
)
|
)
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {})
|
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {})
|
||||||
|
|
@ -1369,15 +1371,10 @@ func testReorgSideEvent(t *testing.T, scheme string) {
|
||||||
t.Fatalf("failed to insert chain: %v", err)
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// first two block of the secondary chain are for a brief moment considered
|
|
||||||
// side chains because up to that point the first one is considered the
|
|
||||||
// heavier chain.
|
|
||||||
expectedSideHashes := map[common.Hash]bool{
|
expectedSideHashes := map[common.Hash]bool{
|
||||||
replacementBlocks[0].Hash(): true,
|
chain[0].Hash(): true,
|
||||||
replacementBlocks[1].Hash(): true,
|
chain[1].Hash(): true,
|
||||||
chain[0].Hash(): true,
|
chain[2].Hash(): true,
|
||||||
chain[1].Hash(): true,
|
|
||||||
chain[2].Hash(): true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
@ -1402,7 +1399,7 @@ done:
|
||||||
timeout.Reset(timeoutDura)
|
timeout.Reset(timeoutDura)
|
||||||
|
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent")
|
t.Fatalf("Timeout. Possibly not all blocks were triggered for sideevent: %v", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1529,7 +1526,7 @@ func testEIP155Transition(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if _, err := blockchain.InsertChain(blocks); err != nil {
|
if _, err := blockchain.InsertChain(blocks); err != nil {
|
||||||
|
|
@ -1622,7 +1619,7 @@ func testEIP161AccountRemoval(t *testing.T, scheme string) {
|
||||||
block.AddTx(tx)
|
block.AddTx(tx)
|
||||||
})
|
})
|
||||||
// account must exist pre eip 161
|
// account must exist pre eip 161
|
||||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
|
if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
|
||||||
|
|
@ -1680,7 +1677,7 @@ func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
// Import the canonical and fork chain side by side, verifying the current block
|
// Import the canonical and fork chain side by side, verifying the current block
|
||||||
// and current header consistency
|
// and current header consistency
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1724,7 +1721,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||||
forks[i] = fork[0]
|
forks[i] = fork[0]
|
||||||
}
|
}
|
||||||
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
|
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1770,7 +1767,7 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
|
||||||
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1786,18 +1783,15 @@ func testLargeReorgTrieGC(t *testing.T, scheme string) {
|
||||||
if chain.HasState(shared[len(shared)-1].Root()) {
|
if chain.HasState(shared[len(shared)-1].Root()) {
|
||||||
t.Fatalf("common-but-old ancestor still cache")
|
t.Fatalf("common-but-old ancestor still cache")
|
||||||
}
|
}
|
||||||
// Import the competitor chain without exceeding the canonical's TD and ensure
|
// Import the competitor chain without exceeding the canonical's TD.
|
||||||
// we have not processed any of the blocks (protection against malicious blocks)
|
// Post-merge the side chain should be executed
|
||||||
if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil {
|
if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil {
|
||||||
t.Fatalf("failed to insert competitor chain: %v", err)
|
t.Fatalf("failed to insert competitor chain: %v", err)
|
||||||
}
|
}
|
||||||
for i, block := range competitor[:len(competitor)-2] {
|
if !chain.HasState(competitor[len(competitor)-3].Root()) {
|
||||||
if chain.HasState(block.Root()) {
|
t.Fatalf("failed to insert low-TD chain")
|
||||||
t.Fatalf("competitor %d: low TD chain became processed", i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Import the head of the competitor chain, triggering the reorg and ensure we
|
// Import the head of the competitor chain.
|
||||||
// successfully reprocess all the stashed away blocks.
|
|
||||||
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
|
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
|
||||||
t.Fatalf("failed to finalize competitor chain: %v", err)
|
t.Fatalf("failed to finalize competitor chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1841,7 +1835,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
|
||||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||||
}
|
}
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
headers := make([]*types.Header, len(blocks))
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
|
|
@ -1861,7 +1855,7 @@ func testBlockchainRecovery(t *testing.T, scheme string) {
|
||||||
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
|
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
|
||||||
|
|
||||||
// Reopen broken blockchain again
|
// Reopen broken blockchain again
|
||||||
ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer ancient.Stop()
|
defer ancient.Stop()
|
||||||
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
|
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
|
||||||
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
|
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
|
||||||
|
|
@ -1913,7 +1907,7 @@ func testInsertReceiptChainRollback(t *testing.T, scheme string) {
|
||||||
}
|
}
|
||||||
defer ancientDb.Close()
|
defer ancientDb.Close()
|
||||||
|
|
||||||
ancientChain, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
ancientChain, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer ancientChain.Stop()
|
defer ancientChain.Stop()
|
||||||
|
|
||||||
// Import the canonical header chain.
|
// Import the canonical header chain.
|
||||||
|
|
@ -1980,7 +1974,7 @@ func testLowDiffLongChain(t *testing.T, scheme string) {
|
||||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
||||||
defer diskdb.Close()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2041,7 +2035,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
mergeBlock = math.MaxInt32
|
mergeBlock = math.MaxInt32
|
||||||
)
|
)
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2195,7 +2189,7 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
|
||||||
}
|
}
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2279,10 +2273,10 @@ func testInsertKnownChainData(t *testing.T, typ string, scheme string) {
|
||||||
if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil {
|
if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil {
|
||||||
t.Fatalf("failed to insert chain data: %v", err)
|
t.Fatalf("failed to insert chain data: %v", err)
|
||||||
}
|
}
|
||||||
// The head shouldn't change.
|
// Post-merge the chain should change even if td is lower.
|
||||||
asserter(t, blocks3[len(blocks3)-1])
|
asserter(t, blocks2[len(blocks2)-1])
|
||||||
|
|
||||||
// Rollback the heavier chain and re-insert the longer chain again
|
// Rollback the heavier chain and re-insert the longer chain again.
|
||||||
chain.SetHead(rollback - 1)
|
chain.SetHead(rollback - 1)
|
||||||
if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil {
|
if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil {
|
||||||
t.Fatalf("failed to insert chain data: %v", err)
|
t.Fatalf("failed to insert chain data: %v", err)
|
||||||
|
|
@ -2366,7 +2360,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
||||||
}
|
}
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2480,7 +2474,7 @@ func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types
|
||||||
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
|
genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{1})
|
b.SetCoinbase(common.Address{1})
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2656,7 +2650,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
// Import the shared chain and the original canonical one
|
// Import the shared chain and the original canonical one
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to create tester chain: %v", err)
|
b.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2743,7 +2737,21 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
_, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*state.TriesInMemory, nil)
|
_, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*state.TriesInMemory, nil)
|
||||||
|
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil)
|
// Construct a database with freezer enabled
|
||||||
|
datadir := t.TempDir()
|
||||||
|
ancient := path.Join(datadir, "ancient")
|
||||||
|
|
||||||
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2770,7 +2778,6 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
||||||
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
||||||
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
||||||
}
|
}
|
||||||
// Now re-import some old blocks
|
|
||||||
blockToReimport := blocks[5:8]
|
blockToReimport := blocks[5:8]
|
||||||
_, err = chain.InsertChain(blockToReimport)
|
_, err = chain.InsertChain(blockToReimport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -2843,7 +2850,7 @@ func testDeleteCreateRevert(t *testing.T, scheme string) {
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -2958,7 +2965,7 @@ func testDeleteRecreateSlots(t *testing.T, scheme string) {
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3040,7 +3047,7 @@ func testDeleteRecreateAccount(t *testing.T, scheme string) {
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3216,7 +3223,7 @@ func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) {
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
//Debug: true,
|
//Debug: true,
|
||||||
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3354,7 +3361,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{
|
||||||
//Debug: true,
|
//Debug: true,
|
||||||
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
//Tracer: vm.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3441,7 +3448,7 @@ func testEIP2718Transition(t *testing.T, scheme string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3535,7 +3542,7 @@ func testEIP1559Transition(t *testing.T, scheme string) {
|
||||||
|
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3648,7 +3655,7 @@ func testSetCanonical(t *testing.T, scheme string) {
|
||||||
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
|
||||||
defer diskdb.Close()
|
defer diskdb.Close()
|
||||||
|
|
||||||
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3757,7 +3764,7 @@ func testCanonicalHashMarker(t *testing.T, scheme string) {
|
||||||
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
|
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
|
||||||
|
|
||||||
// Initialize test chain
|
// Initialize test chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -3894,7 +3901,7 @@ func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{
|
||||||
//Debug: true,
|
//Debug: true,
|
||||||
//Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
//Tracer: logger.NewJSONLogger(nil, os.Stdout),
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4006,7 +4013,7 @@ func TestDeleteThenCreate(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Import the canonical chain
|
// Import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4091,7 +4098,7 @@ func TestTransientStorageReset(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Initialize the blockchain with 1153 enabled.
|
// Initialize the blockchain with 1153 enabled.
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vmConfig, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vmConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4186,7 +4193,7 @@ func TestEIP3651(t *testing.T) {
|
||||||
|
|
||||||
b.AddTx(tx)
|
b.AddTx(tx)
|
||||||
})
|
})
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr).Hooks()}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -4220,3 +4227,90 @@ func TestEIP3651(t *testing.T) {
|
||||||
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
|
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEIP6110(t *testing.T) {
|
||||||
|
var (
|
||||||
|
engine = beacon.NewFaker()
|
||||||
|
|
||||||
|
// A sender who makes transactions, has some funds
|
||||||
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
|
||||||
|
config = *params.AllEthashProtocolChanges
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: &config,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
addr: {Balance: funds},
|
||||||
|
config.DepositContractAddress: {
|
||||||
|
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
|
||||||
|
Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
gspec.Config.BerlinBlock = common.Big0
|
||||||
|
gspec.Config.LondonBlock = common.Big0
|
||||||
|
gspec.Config.TerminalTotalDifficulty = common.Big0
|
||||||
|
gspec.Config.TerminalTotalDifficultyPassed = true
|
||||||
|
gspec.Config.ShanghaiTime = u64(0)
|
||||||
|
gspec.Config.CancunTime = u64(0)
|
||||||
|
gspec.Config.PragueTime = u64(0)
|
||||||
|
signer := types.LatestSigner(gspec.Config)
|
||||||
|
|
||||||
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
txdata := &types.DynamicFeeTx{
|
||||||
|
ChainID: gspec.Config.ChainID,
|
||||||
|
Nonce: uint64(i),
|
||||||
|
To: &config.DepositContractAddress,
|
||||||
|
Gas: 500000,
|
||||||
|
GasFeeCap: newGwei(5),
|
||||||
|
GasTipCap: big.NewInt(2),
|
||||||
|
AccessList: nil,
|
||||||
|
Data: []byte{},
|
||||||
|
}
|
||||||
|
tx := types.NewTx(txdata)
|
||||||
|
tx, _ = types.SignTx(tx, signer, key)
|
||||||
|
b.AddTx(tx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{DisableStack: true}, os.Stderr).Hooks()}, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
|
}
|
||||||
|
defer chain.Stop()
|
||||||
|
if n, err := chain.InsertChain(blocks); err != nil {
|
||||||
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
block := chain.GetBlockByNumber(1)
|
||||||
|
if len(block.Requests()) != 5 {
|
||||||
|
t.Fatalf("failed to retrieve deposits: have %d, want %d", len(block.Requests()), 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify each index is correct.
|
||||||
|
for want, req := range block.Requests() {
|
||||||
|
d, ok := req.Inner().(*types.Deposit)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("expected deposit object")
|
||||||
|
}
|
||||||
|
if got := int(d.PublicKey[0]); got != want {
|
||||||
|
t.Fatalf("invalid pubkey: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if got := int(d.WithdrawalCredentials[0]); got != want {
|
||||||
|
t.Fatalf("invalid withdrawal credentials: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if d.Amount != uint64(want) {
|
||||||
|
t.Fatalf("invalid amounbt: have %d, want %d", d.Amount, want)
|
||||||
|
}
|
||||||
|
if got := int(d.Signature[0]); got != want {
|
||||||
|
t.Fatalf("invalid signature: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if d.Index != uint64(want) {
|
||||||
|
t.Fatalf("invalid index: have %d, want %d", d.Index, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,18 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
|
var requests types.Requests
|
||||||
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
|
for _, r := range b.receipts {
|
||||||
|
d, err := ParseDepositLogs(r.Logs, config)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
||||||
|
}
|
||||||
|
requests = append(requests, d...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
|
||||||
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if i, err := blockchain.InsertChain(genchain); err != nil {
|
if i, err := blockchain.InsertChain(genchain); err != nil {
|
||||||
|
|
@ -238,7 +238,7 @@ func ExampleGenerateChain() {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Import the chain. This runs all block validation rules.
|
// Import the chain. This runs all block validation rules.
|
||||||
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &proConf,
|
Config: &proConf,
|
||||||
}
|
}
|
||||||
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer proBc.Stop()
|
defer proBc.Stop()
|
||||||
|
|
||||||
conDb := rawdb.NewMemoryDatabase()
|
conDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -62,7 +62,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Config: &conConf,
|
Config: &conConf,
|
||||||
}
|
}
|
||||||
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer conBc.Stop()
|
defer conBc.Stop()
|
||||||
|
|
||||||
if _, err := proBc.InsertChain(prefix); err != nil {
|
if _, err := proBc.InsertChain(prefix); err != nil {
|
||||||
|
|
@ -74,7 +74,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
||||||
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
||||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||||
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -97,7 +97,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
||||||
}
|
}
|
||||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||||
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
||||||
for j := 0; j < len(blocks)/2; j++ {
|
for j := 0; j < len(blocks)/2; j++ {
|
||||||
|
|
@ -121,7 +121,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||||
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
|
||||||
|
|
@ -139,7 +139,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
||||||
}
|
}
|
||||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||||
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
||||||
|
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
// Copyright 2021 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
crand "crypto/rand"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
mrand "math/rand"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ChainReader defines a small collection of methods needed to access the local
|
|
||||||
// blockchain during header verification. It's implemented by both blockchain
|
|
||||||
// and lightchain.
|
|
||||||
type ChainReader interface {
|
|
||||||
// Config retrieves the header chain's chain configuration.
|
|
||||||
Config() *params.ChainConfig
|
|
||||||
|
|
||||||
// GetTd returns the total difficulty of a local block.
|
|
||||||
GetTd(common.Hash, uint64) *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForkChoice is the fork chooser based on the highest total difficulty of the
|
|
||||||
// chain(the fork choice used in the eth1) and the external fork choice (the fork
|
|
||||||
// choice used in the eth2). This main goal of this ForkChoice is not only for
|
|
||||||
// offering fork choice during the eth1/2 merge phase, but also keep the compatibility
|
|
||||||
// for all other proof-of-work networks.
|
|
||||||
type ForkChoice struct {
|
|
||||||
chain ChainReader
|
|
||||||
rand *mrand.Rand
|
|
||||||
|
|
||||||
// preserve is a helper function used in td fork choice.
|
|
||||||
// Miners will prefer to choose the local mined block if the
|
|
||||||
// local td is equal to the extern one. It can be nil for light
|
|
||||||
// client
|
|
||||||
preserve func(header *types.Header) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header) bool) *ForkChoice {
|
|
||||||
// Seed a fast but crypto originating random generator
|
|
||||||
seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
|
|
||||||
if err != nil {
|
|
||||||
log.Crit("Failed to initialize random seed", "err", err)
|
|
||||||
}
|
|
||||||
return &ForkChoice{
|
|
||||||
chain: chainReader,
|
|
||||||
rand: mrand.New(mrand.NewSource(seed.Int64())),
|
|
||||||
preserve: preserve,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReorgNeeded returns whether the reorg should be applied
|
|
||||||
// based on the given external header and local canonical chain.
|
|
||||||
// In the td mode, the new head is chosen if the corresponding
|
|
||||||
// total difficulty is higher. In the extern mode, the trusted
|
|
||||||
// header is always selected as the head.
|
|
||||||
func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (bool, error) {
|
|
||||||
var (
|
|
||||||
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
|
|
||||||
externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64())
|
|
||||||
)
|
|
||||||
if localTD == nil || externTd == nil {
|
|
||||||
return false, errors.New("missing td")
|
|
||||||
}
|
|
||||||
// Accept the new header as the chain head if the transition
|
|
||||||
// is already triggered. We assume all the headers after the
|
|
||||||
// transition come from the trusted consensus layer.
|
|
||||||
if ttd := f.chain.Config().TerminalTotalDifficulty; ttd != nil && ttd.Cmp(externTd) <= 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the total difficulty is higher than our known, add it to the canonical chain
|
|
||||||
if diff := externTd.Cmp(localTD); diff > 0 {
|
|
||||||
return true, nil
|
|
||||||
} else if diff < 0 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
// Local and external difficulty is identical.
|
|
||||||
// Second clause in the if statement reduces the vulnerability to selfish mining.
|
|
||||||
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
|
|
||||||
reorg := false
|
|
||||||
externNum, localNum := extern.Number.Uint64(), current.Number.Uint64()
|
|
||||||
if externNum < localNum {
|
|
||||||
reorg = true
|
|
||||||
} else if externNum == localNum {
|
|
||||||
var currentPreserve, externPreserve bool
|
|
||||||
if f.preserve != nil {
|
|
||||||
currentPreserve, externPreserve = f.preserve(current), f.preserve(extern)
|
|
||||||
}
|
|
||||||
reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5)
|
|
||||||
}
|
|
||||||
return reorg, nil
|
|
||||||
}
|
|
||||||
|
|
@ -447,7 +447,10 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
|
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var withdrawals []*types.Withdrawal
|
var (
|
||||||
|
withdrawals []*types.Withdrawal
|
||||||
|
requests types.Requests
|
||||||
|
)
|
||||||
if conf := g.Config; conf != nil {
|
if conf := g.Config; conf != nil {
|
||||||
num := big.NewInt(int64(g.Number))
|
num := big.NewInt(int64(g.Number))
|
||||||
if conf.IsShanghai(num, g.Timestamp) {
|
if conf.IsShanghai(num, g.Timestamp) {
|
||||||
|
|
@ -469,8 +472,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
head.BlobGasUsed = new(uint64)
|
head.BlobGasUsed = new(uint64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if conf.IsPrague(num, g.Timestamp) {
|
||||||
|
head.RequestsHash = &types.EmptyRequestsHash
|
||||||
|
requests = make(types.Requests, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit writes the block and state of a genesis specification to the database.
|
// Commit writes the block and state of a genesis specification to the database.
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||||
oldcustomg.Commit(db, tdb)
|
oldcustomg.Commit(db, tdb)
|
||||||
|
|
||||||
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil)
|
bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil)
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
||||||
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
|
_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) {
|
||||||
// without the real blocks. Hence, writing headers directly should only be done
|
// without the real blocks. Hence, writing headers directly should only be done
|
||||||
// in two scenarios: pure-header mode of operation (light clients), or properly
|
// in two scenarios: pure-header mode of operation (light clients), or properly
|
||||||
// separated header/block phases (non-archive clients).
|
// separated header/block phases (non-archive clients).
|
||||||
func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *ForkChoice) (*headerWriteResult, error) {
|
func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header) (*headerWriteResult, error) {
|
||||||
inserted, err := hc.WriteHeaders(headers)
|
inserted, err := hc.WriteHeaders(headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -270,15 +270,6 @@ func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *F
|
||||||
lastHeader: lastHeader,
|
lastHeader: lastHeader,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Ask the fork choicer if the reorg is necessary
|
|
||||||
if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if !reorg {
|
|
||||||
if inserted != 0 {
|
|
||||||
result.status = SideStatTy
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
// Special case, all the inserted headers are already on the canonical
|
// Special case, all the inserted headers are already on the canonical
|
||||||
// header chain, skip the reorg operation.
|
// header chain, skip the reorg operation.
|
||||||
if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() {
|
if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() {
|
||||||
|
|
@ -336,11 +327,11 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header) (int, error) {
|
||||||
//
|
//
|
||||||
// The returned 'write status' says if the inserted headers are part of the canonical chain
|
// The returned 'write status' says if the inserted headers are part of the canonical chain
|
||||||
// or a side chain.
|
// or a side chain.
|
||||||
func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time, forker *ForkChoice) (WriteStatus, error) {
|
func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time) (WriteStatus, error) {
|
||||||
if hc.procInterrupt() {
|
if hc.procInterrupt() {
|
||||||
return 0, errors.New("aborted")
|
return 0, errors.New("aborted")
|
||||||
}
|
}
|
||||||
res, err := hc.writeHeadersAndSetHead(chain, forker)
|
res, err := hc.writeHeadersAndSetHead(chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,10 @@ func verifyUnbrokenCanonchain(hc *HeaderChain) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInsert(t *testing.T, hc *HeaderChain, chain []*types.Header, wantStatus WriteStatus, wantErr error, forker *ForkChoice) {
|
func testInsert(t *testing.T, hc *HeaderChain, chain []*types.Header, wantStatus WriteStatus, wantErr error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
status, err := hc.InsertHeaderChain(chain, time.Now(), forker)
|
status, err := hc.InsertHeaderChain(chain, time.Now())
|
||||||
if status != wantStatus {
|
if status != wantStatus {
|
||||||
t.Errorf("wrong write status from InsertHeaderChain: got %v, want %v", status, wantStatus)
|
t.Errorf("wrong write status from InsertHeaderChain: got %v, want %v", status, wantStatus)
|
||||||
}
|
}
|
||||||
|
|
@ -83,34 +83,33 @@ func TestHeaderInsertion(t *testing.T) {
|
||||||
// chain B: G->A1->B1...B128
|
// chain B: G->A1->B1...B128
|
||||||
chainB := makeHeaderChain(gspec.Config, chainA[0], 128, ethash.NewFaker(), genDb, 10)
|
chainB := makeHeaderChain(gspec.Config, chainA[0], 128, ethash.NewFaker(), genDb, 10)
|
||||||
|
|
||||||
forker := NewForkChoice(hc, nil)
|
|
||||||
// Inserting 64 headers on an empty chain, expecting
|
// Inserting 64 headers on an empty chain, expecting
|
||||||
// 1 callbacks, 1 canon-status, 0 sidestatus,
|
// 1 callbacks, 1 canon-status, 0 sidestatus,
|
||||||
testInsert(t, hc, chainA[:64], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainA[:64], CanonStatTy, nil)
|
||||||
|
|
||||||
// Inserting 64 identical headers, expecting
|
// Inserting 64 identical headers, expecting
|
||||||
// 0 callbacks, 0 canon-status, 0 sidestatus,
|
// 0 callbacks, 0 canon-status, 0 sidestatus,
|
||||||
testInsert(t, hc, chainA[:64], NonStatTy, nil, forker)
|
testInsert(t, hc, chainA[:64], NonStatTy, nil)
|
||||||
|
|
||||||
// Inserting the same some old, some new headers
|
// Inserting the same some old, some new headers
|
||||||
// 1 callbacks, 1 canon, 0 side
|
// 1 callbacks, 1 canon, 0 side
|
||||||
testInsert(t, hc, chainA[32:96], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainA[32:96], CanonStatTy, nil)
|
||||||
|
|
||||||
// Inserting side blocks, but not overtaking the canon chain
|
// Inserting headers from chain B, overtaking the canon chain blindly
|
||||||
testInsert(t, hc, chainB[0:32], SideStatTy, nil, forker)
|
testInsert(t, hc, chainB[0:32], CanonStatTy, nil)
|
||||||
|
|
||||||
// Inserting more side blocks, but we don't have the parent
|
// Inserting more headers on chain B, but we don't have the parent
|
||||||
testInsert(t, hc, chainB[34:36], NonStatTy, consensus.ErrUnknownAncestor, forker)
|
testInsert(t, hc, chainB[34:36], NonStatTy, consensus.ErrUnknownAncestor)
|
||||||
|
|
||||||
// Inserting more sideblocks, overtaking the canon chain
|
// Inserting more headers on chain B, extend the canon chain
|
||||||
testInsert(t, hc, chainB[32:97], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainB[32:97], CanonStatTy, nil)
|
||||||
|
|
||||||
// Inserting more A-headers, taking back the canonicality
|
// Inserting more headers on chain A, taking back the canonicality
|
||||||
testInsert(t, hc, chainA[90:100], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainA[90:100], CanonStatTy, nil)
|
||||||
|
|
||||||
// And B becomes canon again
|
// And B becomes canon again
|
||||||
testInsert(t, hc, chainB[97:107], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainB[97:107], CanonStatTy, nil)
|
||||||
|
|
||||||
// And B becomes even longer
|
// And B becomes even longer
|
||||||
testInsert(t, hc, chainB[107:128], CanonStatTy, nil, forker)
|
testInsert(t, hc, chainB[107:128], CanonStatTy, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func NewStateProcessor(config *params.ChainConfig, chain *HeaderChain) *StatePro
|
||||||
// Process returns the receipts and logs accumulated during the process and
|
// Process returns the receipts and logs accumulated during the process and
|
||||||
// returns the amount of gas that was used in the process. If any of the
|
// returns the amount of gas that was used in the process. If any of the
|
||||||
// transactions failed to execute due to insufficient gas it will return an error.
|
// transactions failed to execute due to insufficient gas it will return an error.
|
||||||
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
|
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResult, error) {
|
||||||
var (
|
var (
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
usedGas = new(uint64)
|
usedGas = new(uint64)
|
||||||
|
|
@ -71,6 +71,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
var (
|
var (
|
||||||
context vm.BlockContext
|
context vm.BlockContext
|
||||||
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
context = NewEVMBlockContext(header, p.chain, nil)
|
context = NewEVMBlockContext(header, p.chain, nil)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||||
|
|
@ -84,21 +85,35 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
receipt, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
receipt, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
receipts = append(receipts, receipt)
|
receipts = append(receipts, receipt)
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
}
|
}
|
||||||
|
// Read requests if Prague is enabled.
|
||||||
|
var requests types.Requests
|
||||||
|
if p.config.IsPrague(block.Number(), block.Time()) {
|
||||||
|
requests, err = ParseDepositLogs(allLogs, p.config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
p.chain.engine.Finalize(p.chain, header, statedb, block.Body())
|
p.chain.engine.Finalize(p.chain, header, statedb, block.Body())
|
||||||
|
|
||||||
return receipts, allLogs, *usedGas, nil
|
return &ProcessResult{
|
||||||
|
Receipts: receipts,
|
||||||
|
Requests: requests,
|
||||||
|
Logs: allLogs,
|
||||||
|
GasUsed: *usedGas,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
|
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
|
||||||
|
|
@ -244,3 +259,19 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state.
|
||||||
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseDepositLogs extracts the EIP-6110 deposit values from logs emitted by
|
||||||
|
// BeaconDepositContract.
|
||||||
|
func ParseDepositLogs(logs []*types.Log, config *params.ChainConfig) (types.Requests, error) {
|
||||||
|
deposits := make(types.Requests, 0)
|
||||||
|
for _, log := range logs {
|
||||||
|
if log.Address == config.DepositContractAddress {
|
||||||
|
d, err := types.UnpackIntoDeposit(log.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to parse deposit data: %v", err)
|
||||||
|
}
|
||||||
|
deposits = append(deposits, types.NewRequest(d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deposits, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil)
|
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
||||||
tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
|
tooBigInitCode = [params.MaxInitCodeSize + 1]byte{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -293,7 +293,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
|
|
@ -332,7 +332,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil)
|
blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
||||||
)
|
)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
for i, tt := range []struct {
|
for i, tt := range []struct {
|
||||||
|
|
@ -481,7 +481,7 @@ func TestProcessVerkle(t *testing.T) {
|
||||||
// genesis := gspec.MustCommit(bcdb, triedb)
|
// genesis := gspec.MustCommit(bcdb, triedb)
|
||||||
cacheConfig := DefaultCacheConfigWithScheme("path")
|
cacheConfig := DefaultCacheConfigWithScheme("path")
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil)
|
blockchain, _ := NewBlockChain(bcdb, cacheConfig, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
|
||||||
defer blockchain.Stop()
|
defer blockchain.Stop()
|
||||||
|
|
||||||
txCost1 := params.TxGas
|
txCost1 := params.TxGas
|
||||||
|
|
|
||||||
|
|
@ -58,15 +58,15 @@ func ExecuteStateless(config *params.ChainConfig, witness *stateless.Witness) (c
|
||||||
validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block
|
validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block
|
||||||
|
|
||||||
// Run the stateless blocks processing and self-validate certain fields
|
// Run the stateless blocks processing and self-validate certain fields
|
||||||
receipts, _, usedGas, err := processor.Process(witness.Block, db, vm.Config{})
|
res, err := processor.Process(witness.Block, db, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Hash{}, common.Hash{}, err
|
return common.Hash{}, common.Hash{}, err
|
||||||
}
|
}
|
||||||
if err = validator.ValidateState(witness.Block, db, receipts, usedGas, true); err != nil {
|
if err = validator.ValidateState(witness.Block, db, res, true); err != nil {
|
||||||
return common.Hash{}, common.Hash{}, err
|
return common.Hash{}, common.Hash{}, err
|
||||||
}
|
}
|
||||||
// Almost everything validated, but receipt and state root needs to be returned
|
// Almost everything validated, but receipt and state root needs to be returned
|
||||||
receiptRoot := types.DeriveSha(receipts, trie.NewStackTrie(nil))
|
receiptRoot := types.DeriveSha(res.Receipts, trie.NewStackTrie(nil))
|
||||||
stateRoot := db.IntermediateRoot(config.IsEIP158(witness.Block.Number()))
|
stateRoot := db.IntermediateRoot(config.IsEIP158(witness.Block.Number()))
|
||||||
|
|
||||||
return receiptRoot, stateRoot, nil
|
return receiptRoot, stateRoot, nil
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,8 @@ type Validator interface {
|
||||||
// ValidateBody validates the given block's content.
|
// ValidateBody validates the given block's content.
|
||||||
ValidateBody(block *types.Block) error
|
ValidateBody(block *types.Block) error
|
||||||
|
|
||||||
// ValidateState validates the given statedb and optionally the receipts and
|
// ValidateState validates the given statedb and optionally the process result.
|
||||||
// gas used.
|
ValidateState(block *types.Block, state *state.StateDB, res *ProcessResult, stateless bool) error
|
||||||
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64, stateless bool) error
|
|
||||||
|
|
||||||
// ValidateWitness cross validates a block execution with stateless remote clients.
|
// ValidateWitness cross validates a block execution with stateless remote clients.
|
||||||
ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error
|
ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error
|
||||||
|
|
@ -54,5 +53,13 @@ type Processor interface {
|
||||||
// Process processes the state changes according to the Ethereum rules by running
|
// Process processes the state changes according to the Ethereum rules by running
|
||||||
// the transaction messages using the statedb and applying any rewards to both
|
// the transaction messages using the statedb and applying any rewards to both
|
||||||
// the processor (coinbase) and any included uncles.
|
// the processor (coinbase) and any included uncles.
|
||||||
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error)
|
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResult, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessResult contains the values computed by Process.
|
||||||
|
type ProcessResult struct {
|
||||||
|
Receipts types.Receipts
|
||||||
|
Requests types.Requests
|
||||||
|
Logs []*types.Log
|
||||||
|
GasUsed uint64
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,9 @@ type Header struct {
|
||||||
|
|
||||||
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
|
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
|
||||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
|
||||||
|
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
|
||||||
|
RequestsHash *common.Hash `json:"requestsRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// field type overrides for gencodec
|
// field type overrides for gencodec
|
||||||
|
|
@ -163,10 +166,11 @@ func (h *Header) SanityCheck() error {
|
||||||
// EmptyBody returns true if there is no additional 'body' to complete the header
|
// EmptyBody returns true if there is no additional 'body' to complete the header
|
||||||
// that is: no transactions, no uncles and no withdrawals.
|
// that is: no transactions, no uncles and no withdrawals.
|
||||||
func (h *Header) EmptyBody() bool {
|
func (h *Header) EmptyBody() bool {
|
||||||
if h.WithdrawalsHash != nil {
|
var (
|
||||||
return h.TxHash == EmptyTxsHash && *h.WithdrawalsHash == EmptyWithdrawalsHash
|
emptyWithdrawals = h.WithdrawalsHash == nil || *h.WithdrawalsHash == EmptyWithdrawalsHash
|
||||||
}
|
emptyRequests = h.RequestsHash == nil || *h.RequestsHash == EmptyReceiptsHash
|
||||||
return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash
|
)
|
||||||
|
return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash && emptyWithdrawals && emptyRequests
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmptyReceipts returns true if there are no receipts for this header/block.
|
// EmptyReceipts returns true if there are no receipts for this header/block.
|
||||||
|
|
@ -180,6 +184,7 @@ type Body struct {
|
||||||
Transactions []*Transaction
|
Transactions []*Transaction
|
||||||
Uncles []*Header
|
Uncles []*Header
|
||||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||||
|
Requests []*Request `rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block represents an Ethereum block.
|
// Block represents an Ethereum block.
|
||||||
|
|
@ -204,6 +209,7 @@ type Block struct {
|
||||||
uncles []*Header
|
uncles []*Header
|
||||||
transactions Transactions
|
transactions Transactions
|
||||||
withdrawals Withdrawals
|
withdrawals Withdrawals
|
||||||
|
requests Requests
|
||||||
|
|
||||||
// witness is not an encoded part of the block body.
|
// witness is not an encoded part of the block body.
|
||||||
// It is held in Block in order for easy relaying to the places
|
// It is held in Block in order for easy relaying to the places
|
||||||
|
|
@ -226,6 +232,7 @@ type extblock struct {
|
||||||
Txs []*Transaction
|
Txs []*Transaction
|
||||||
Uncles []*Header
|
Uncles []*Header
|
||||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||||
|
Requests []*Request `rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlock creates a new block. The input data is copied, changes to header and to the
|
// NewBlock creates a new block. The input data is copied, changes to header and to the
|
||||||
|
|
@ -242,6 +249,7 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
|
||||||
txs = body.Transactions
|
txs = body.Transactions
|
||||||
uncles = body.Uncles
|
uncles = body.Uncles
|
||||||
withdrawals = body.Withdrawals
|
withdrawals = body.Withdrawals
|
||||||
|
requests = body.Requests
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(txs) == 0 {
|
if len(txs) == 0 {
|
||||||
|
|
@ -280,6 +288,17 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
|
||||||
b.withdrawals = slices.Clone(withdrawals)
|
b.withdrawals = slices.Clone(withdrawals)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if requests == nil {
|
||||||
|
b.header.RequestsHash = nil
|
||||||
|
} else if len(requests) == 0 {
|
||||||
|
b.header.RequestsHash = &EmptyRequestsHash
|
||||||
|
b.requests = Requests{}
|
||||||
|
} else {
|
||||||
|
h := DeriveSha(Requests(requests), hasher)
|
||||||
|
b.header.RequestsHash = &h
|
||||||
|
b.requests = slices.Clone(requests)
|
||||||
|
}
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,6 +334,10 @@ func CopyHeader(h *Header) *Header {
|
||||||
cpy.ParentBeaconRoot = new(common.Hash)
|
cpy.ParentBeaconRoot = new(common.Hash)
|
||||||
*cpy.ParentBeaconRoot = *h.ParentBeaconRoot
|
*cpy.ParentBeaconRoot = *h.ParentBeaconRoot
|
||||||
}
|
}
|
||||||
|
if h.RequestsHash != nil {
|
||||||
|
cpy.RequestsHash = new(common.Hash)
|
||||||
|
*cpy.RequestsHash = *h.RequestsHash
|
||||||
|
}
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,7 +348,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
|
||||||
if err := s.Decode(&eb); err != nil {
|
if err := s.Decode(&eb); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals
|
b.header, b.uncles, b.transactions, b.withdrawals, b.requests = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals, eb.Requests
|
||||||
b.size.Store(rlp.ListSize(size))
|
b.size.Store(rlp.ListSize(size))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -337,13 +360,14 @@ func (b *Block) EncodeRLP(w io.Writer) error {
|
||||||
Txs: b.transactions,
|
Txs: b.transactions,
|
||||||
Uncles: b.uncles,
|
Uncles: b.uncles,
|
||||||
Withdrawals: b.withdrawals,
|
Withdrawals: b.withdrawals,
|
||||||
|
Requests: b.requests,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body returns the non-header content of the block.
|
// Body returns the non-header content of the block.
|
||||||
// Note the returned data is not an independent copy.
|
// Note the returned data is not an independent copy.
|
||||||
func (b *Block) Body() *Body {
|
func (b *Block) Body() *Body {
|
||||||
return &Body{b.transactions, b.uncles, b.withdrawals}
|
return &Body{b.transactions, b.uncles, b.withdrawals, b.requests}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors for body data. These do not return a copy because the content
|
// Accessors for body data. These do not return a copy because the content
|
||||||
|
|
@ -352,6 +376,7 @@ func (b *Block) Body() *Body {
|
||||||
func (b *Block) Uncles() []*Header { return b.uncles }
|
func (b *Block) Uncles() []*Header { return b.uncles }
|
||||||
func (b *Block) Transactions() Transactions { return b.transactions }
|
func (b *Block) Transactions() Transactions { return b.transactions }
|
||||||
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
|
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
|
||||||
|
func (b *Block) Requests() Requests { return b.requests }
|
||||||
|
|
||||||
func (b *Block) Transaction(hash common.Hash) *Transaction {
|
func (b *Block) Transaction(hash common.Hash) *Transaction {
|
||||||
for _, transaction := range b.transactions {
|
for _, transaction := range b.transactions {
|
||||||
|
|
@ -476,6 +501,7 @@ func (b *Block) WithBody(body Body) *Block {
|
||||||
transactions: slices.Clone(body.Transactions),
|
transactions: slices.Clone(body.Transactions),
|
||||||
uncles: make([]*Header, len(body.Uncles)),
|
uncles: make([]*Header, len(body.Uncles)),
|
||||||
withdrawals: slices.Clone(body.Withdrawals),
|
withdrawals: slices.Clone(body.Withdrawals),
|
||||||
|
requests: slices.Clone(body.Requests),
|
||||||
witness: b.witness,
|
witness: b.witness,
|
||||||
}
|
}
|
||||||
for i := range body.Uncles {
|
for i := range body.Uncles {
|
||||||
|
|
@ -490,6 +516,7 @@ func (b *Block) WithWitness(witness *ExecutionWitness) *Block {
|
||||||
transactions: b.transactions,
|
transactions: b.transactions,
|
||||||
uncles: b.uncles,
|
uncles: b.uncles,
|
||||||
withdrawals: b.withdrawals,
|
withdrawals: b.withdrawals,
|
||||||
|
requests: b.requests,
|
||||||
witness: witness,
|
witness: witness,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
core/types/deposit.go
Normal file
103
core/types/deposit.go
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/fjl/gencodec -type Deposit -field-override depositMarshaling -out gen_deposit_json.go
|
||||||
|
|
||||||
|
// Deposit contains EIP-6110 deposit data.
|
||||||
|
type Deposit struct {
|
||||||
|
PublicKey [48]byte `json:"pubkey"` // public key of validator
|
||||||
|
WithdrawalCredentials common.Hash `json:"withdrawalCredentials"` // beneficiary of the validator funds
|
||||||
|
Amount uint64 `json:"amount"` // deposit size in Gwei
|
||||||
|
Signature [96]byte `json:"signature"` // signature over deposit msg
|
||||||
|
Index uint64 `json:"index"` // deposit count value
|
||||||
|
}
|
||||||
|
|
||||||
|
// field type overrides for gencodec
|
||||||
|
type depositMarshaling struct {
|
||||||
|
PublicKey hexutil.Bytes
|
||||||
|
WithdrawalCredentials hexutil.Bytes
|
||||||
|
Amount hexutil.Uint64
|
||||||
|
Signature hexutil.Bytes
|
||||||
|
Index hexutil.Uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deposits implements DerivableList for requests.
|
||||||
|
type Deposits []*Deposit
|
||||||
|
|
||||||
|
// Len returns the length of s.
|
||||||
|
func (s Deposits) Len() int { return len(s) }
|
||||||
|
|
||||||
|
// EncodeIndex encodes the i'th deposit to s.
|
||||||
|
func (s Deposits) EncodeIndex(i int, w *bytes.Buffer) {
|
||||||
|
rlp.Encode(w, s[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpackIntoDeposit unpacks a serialized DepositEvent.
|
||||||
|
func UnpackIntoDeposit(data []byte) (*Deposit, error) {
|
||||||
|
if len(data) != 576 {
|
||||||
|
return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data))
|
||||||
|
}
|
||||||
|
var d Deposit
|
||||||
|
// The ABI encodes the position of dynamic elements first. Since there are 5
|
||||||
|
// elements, skip over the positional data. The first 32 bytes of dynamic
|
||||||
|
// elements also encode their actual length. Skip over that value too.
|
||||||
|
b := 32*5 + 32
|
||||||
|
// PublicKey is the first element. ABI encoding pads values to 32 bytes, so
|
||||||
|
// despite BLS public keys being length 48, the value length here is 64. Then
|
||||||
|
// skip over the next length value.
|
||||||
|
copy(d.PublicKey[:], data[b:b+48])
|
||||||
|
b += 48 + 16 + 32
|
||||||
|
// WithdrawalCredentials is 32 bytes. Read that value then skip over next
|
||||||
|
// length.
|
||||||
|
copy(d.WithdrawalCredentials[:], data[b:b+32])
|
||||||
|
b += 32 + 32
|
||||||
|
// Amount is 8 bytes, but it is padded to 32. Skip over it and the next
|
||||||
|
// length.
|
||||||
|
d.Amount = binary.LittleEndian.Uint64(data[b : b+8])
|
||||||
|
b += 8 + 24 + 32
|
||||||
|
// Signature is 96 bytes. Skip over it and the next length.
|
||||||
|
copy(d.Signature[:], data[b:b+96])
|
||||||
|
b += 96 + 32
|
||||||
|
// Amount is 8 bytes.
|
||||||
|
d.Index = binary.LittleEndian.Uint64(data[b : b+8])
|
||||||
|
|
||||||
|
return &d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Deposit) requestType() byte { return DepositRequestType }
|
||||||
|
func (d *Deposit) encode(b *bytes.Buffer) error { return rlp.Encode(b, d) }
|
||||||
|
func (d *Deposit) decode(input []byte) error { return rlp.DecodeBytes(input, d) }
|
||||||
|
func (d *Deposit) copy() RequestData {
|
||||||
|
return &Deposit{
|
||||||
|
PublicKey: d.PublicKey,
|
||||||
|
WithdrawalCredentials: d.WithdrawalCredentials,
|
||||||
|
Amount: d.Amount,
|
||||||
|
Signature: d.Signature,
|
||||||
|
Index: d.Index,
|
||||||
|
}
|
||||||
|
}
|
||||||
93
core/types/deposit_test.go
Normal file
93
core/types/deposit_test.go
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
depositABI = abi.ABI{Methods: map[string]abi.Method{"DepositEvent": depositEvent}}
|
||||||
|
bytesT, _ = abi.NewType("bytes", "", nil)
|
||||||
|
depositEvent = abi.NewMethod("DepositEvent", "DepositEvent", abi.Function, "", false, false, []abi.Argument{
|
||||||
|
{Name: "pubkey", Type: bytesT, Indexed: false},
|
||||||
|
{Name: "withdrawal_credentials", Type: bytesT, Indexed: false},
|
||||||
|
{Name: "amount", Type: bytesT, Indexed: false},
|
||||||
|
{Name: "signature", Type: bytesT, Indexed: false},
|
||||||
|
{Name: "index", Type: bytesT, Indexed: false}}, nil,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// FuzzUnpackIntoDeposit tries roundtrip packing and unpacking of deposit events.
|
||||||
|
func FuzzUnpackIntoDeposit(f *testing.F) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
pubkey string
|
||||||
|
wxCred string
|
||||||
|
amount string
|
||||||
|
sig string
|
||||||
|
index string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
pubkey: "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
|
||||||
|
wxCred: "2222222222222222222222222222222222222222222222222222222222222222",
|
||||||
|
amount: "3333333333333333",
|
||||||
|
sig: "444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444",
|
||||||
|
index: "5555555555555555",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
f.Add(common.FromHex(tt.pubkey), common.FromHex(tt.wxCred), common.FromHex(tt.amount), common.FromHex(tt.sig), common.FromHex(tt.index))
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Fuzz(func(t *testing.T, p []byte, w []byte, a []byte, s []byte, i []byte) {
|
||||||
|
var (
|
||||||
|
pubkey [48]byte
|
||||||
|
wxCred [32]byte
|
||||||
|
amount [8]byte
|
||||||
|
sig [96]byte
|
||||||
|
index [8]byte
|
||||||
|
)
|
||||||
|
copy(pubkey[:], p)
|
||||||
|
copy(wxCred[:], w)
|
||||||
|
copy(amount[:], a)
|
||||||
|
copy(sig[:], s)
|
||||||
|
copy(index[:], i)
|
||||||
|
|
||||||
|
want := Deposit{
|
||||||
|
PublicKey: pubkey,
|
||||||
|
WithdrawalCredentials: wxCred,
|
||||||
|
Amount: binary.LittleEndian.Uint64(amount[:]),
|
||||||
|
Signature: sig,
|
||||||
|
Index: binary.LittleEndian.Uint64(index[:]),
|
||||||
|
}
|
||||||
|
out, err := depositABI.Pack("DepositEvent", want.PublicKey[:], want.WithdrawalCredentials[:], amount[:], want.Signature[:], index[:])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error packing deposit: %v", err)
|
||||||
|
}
|
||||||
|
got, err := UnpackIntoDeposit(out[4:])
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error unpacking deposit: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(want, *got) {
|
||||||
|
t.Errorf("roundtrip failed: want %v, got %v", want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
70
core/types/gen_deposit_json.go
Normal file
70
core/types/gen_deposit_json.go
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*depositMarshaling)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals as JSON.
|
||||||
|
func (d Deposit) MarshalJSON() ([]byte, error) {
|
||||||
|
type Deposit struct {
|
||||||
|
PublicKey hexutil.Bytes `json:"pubkey"`
|
||||||
|
WithdrawalCredentials hexutil.Bytes `json:"withdrawalCredentials"`
|
||||||
|
Amount hexutil.Uint64 `json:"amount"`
|
||||||
|
Signature hexutil.Bytes `json:"signature"`
|
||||||
|
Index hexutil.Uint64 `json:"index"`
|
||||||
|
}
|
||||||
|
var enc Deposit
|
||||||
|
enc.PublicKey = d.PublicKey[:]
|
||||||
|
enc.WithdrawalCredentials = d.WithdrawalCredentials[:]
|
||||||
|
enc.Amount = hexutil.Uint64(d.Amount)
|
||||||
|
enc.Signature = d.Signature[:]
|
||||||
|
enc.Index = hexutil.Uint64(d.Index)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
|
func (d *Deposit) UnmarshalJSON(input []byte) error {
|
||||||
|
type Deposit struct {
|
||||||
|
PublicKey *hexutil.Bytes `json:"pubkey"`
|
||||||
|
WithdrawalCredentials *hexutil.Bytes `json:"withdrawalCredentials"`
|
||||||
|
Amount *hexutil.Uint64 `json:"amount"`
|
||||||
|
Signature *hexutil.Bytes `json:"signature"`
|
||||||
|
Index *hexutil.Uint64 `json:"index"`
|
||||||
|
}
|
||||||
|
var dec Deposit
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.PublicKey != nil {
|
||||||
|
if len(*dec.PublicKey) != len(d.PublicKey) {
|
||||||
|
return errors.New("field 'pubkey' has wrong length, need 48 items")
|
||||||
|
}
|
||||||
|
copy(d.PublicKey[:], *dec.PublicKey)
|
||||||
|
}
|
||||||
|
if dec.WithdrawalCredentials != nil {
|
||||||
|
if len(*dec.WithdrawalCredentials) != len(d.WithdrawalCredentials) {
|
||||||
|
return errors.New("field 'withdrawalCredentials' has wrong length, need 32 items")
|
||||||
|
}
|
||||||
|
copy(d.WithdrawalCredentials[:], *dec.WithdrawalCredentials)
|
||||||
|
}
|
||||||
|
if dec.Amount != nil {
|
||||||
|
d.Amount = uint64(*dec.Amount)
|
||||||
|
}
|
||||||
|
if dec.Signature != nil {
|
||||||
|
if len(*dec.Signature) != len(d.Signature) {
|
||||||
|
return errors.New("field 'signature' has wrong length, need 96 items")
|
||||||
|
}
|
||||||
|
copy(d.Signature[:], *dec.Signature)
|
||||||
|
}
|
||||||
|
if dec.Index != nil {
|
||||||
|
d.Index = uint64(*dec.Index)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsRoot" rlp:"optional"`
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
}
|
}
|
||||||
var enc Header
|
var enc Header
|
||||||
|
|
@ -59,6 +60,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||||
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
||||||
|
enc.RequestsHash = h.RequestsHash
|
||||||
enc.Hash = h.Hash()
|
enc.Hash = h.Hash()
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
@ -86,6 +88,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
RequestsHash *common.Hash `json:"requestsRoot" rlp:"optional"`
|
||||||
}
|
}
|
||||||
var dec Header
|
var dec Header
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -163,5 +166,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ParentBeaconRoot != nil {
|
if dec.ParentBeaconRoot != nil {
|
||||||
h.ParentBeaconRoot = dec.ParentBeaconRoot
|
h.ParentBeaconRoot = dec.ParentBeaconRoot
|
||||||
}
|
}
|
||||||
|
if dec.RequestsHash != nil {
|
||||||
|
h.RequestsHash = dec.RequestsHash
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||||
_tmp3 := obj.BlobGasUsed != nil
|
_tmp3 := obj.BlobGasUsed != nil
|
||||||
_tmp4 := obj.ExcessBlobGas != nil
|
_tmp4 := obj.ExcessBlobGas != nil
|
||||||
_tmp5 := obj.ParentBeaconRoot != nil
|
_tmp5 := obj.ParentBeaconRoot != nil
|
||||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
_tmp6 := obj.RequestsHash != nil
|
||||||
|
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||||
if obj.BaseFee == nil {
|
if obj.BaseFee == nil {
|
||||||
w.Write(rlp.EmptyString)
|
w.Write(rlp.EmptyString)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -52,34 +53,41 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||||
w.WriteBigInt(obj.BaseFee)
|
w.WriteBigInt(obj.BaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 {
|
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||||
if obj.WithdrawalsHash == nil {
|
if obj.WithdrawalsHash == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp3 || _tmp4 || _tmp5 {
|
if _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
||||||
if obj.BlobGasUsed == nil {
|
if obj.BlobGasUsed == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.BlobGasUsed))
|
w.WriteUint64((*obj.BlobGasUsed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp4 || _tmp5 {
|
if _tmp4 || _tmp5 || _tmp6 {
|
||||||
if obj.ExcessBlobGas == nil {
|
if obj.ExcessBlobGas == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.ExcessBlobGas))
|
w.WriteUint64((*obj.ExcessBlobGas))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp5 {
|
if _tmp5 || _tmp6 {
|
||||||
if obj.ParentBeaconRoot == nil {
|
if obj.ParentBeaconRoot == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.ParentBeaconRoot[:])
|
w.WriteBytes(obj.ParentBeaconRoot[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if _tmp6 {
|
||||||
|
if obj.RequestsHash == nil {
|
||||||
|
w.Write([]byte{0x80})
|
||||||
|
} else {
|
||||||
|
w.WriteBytes(obj.RequestsHash[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
w.ListEnd(_tmp0)
|
w.ListEnd(_tmp0)
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ var (
|
||||||
// EmptyWithdrawalsHash is the known hash of the empty withdrawal set.
|
// EmptyWithdrawalsHash is the known hash of the empty withdrawal set.
|
||||||
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||||
|
|
||||||
|
// EmptyRequestsHash is the known hash of the empty requests set.
|
||||||
|
EmptyRequestsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||||
|
|
||||||
// EmptyVerkleHash is the known hash of an empty verkle trie.
|
// EmptyVerkleHash is the known hash of an empty verkle trie.
|
||||||
EmptyVerkleHash = common.Hash{}
|
EmptyVerkleHash = common.Hash{}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
157
core/types/request.go
Normal file
157
core/types/request.go
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrRequestTypeNotSupported = errors.New("request type not supported")
|
||||||
|
errShortTypedRequest = errors.New("typed request too short")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request types.
|
||||||
|
const (
|
||||||
|
DepositRequestType = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request is an EIP-7685 request object. It represents execution layer
|
||||||
|
// triggered messages bound for the consensus layer.
|
||||||
|
type Request struct {
|
||||||
|
inner RequestData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns the EIP-7685 type of the request.
|
||||||
|
func (r *Request) Type() byte {
|
||||||
|
return r.inner.requestType()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner returns the inner request data.
|
||||||
|
func (r *Request) Inner() RequestData {
|
||||||
|
return r.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest creates a new request.
|
||||||
|
func NewRequest(inner RequestData) *Request {
|
||||||
|
req := new(Request)
|
||||||
|
req.inner = inner.copy()
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requests implements DerivableList for requests.
|
||||||
|
type Requests []*Request
|
||||||
|
|
||||||
|
// Len returns the length of s.
|
||||||
|
func (s Requests) Len() int { return len(s) }
|
||||||
|
|
||||||
|
// EncodeIndex encodes the i'th request to s.
|
||||||
|
func (s Requests) EncodeIndex(i int, w *bytes.Buffer) {
|
||||||
|
s[i].encode(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestData is the underlying data of a request.
|
||||||
|
type RequestData interface {
|
||||||
|
requestType() byte
|
||||||
|
encode(*bytes.Buffer) error
|
||||||
|
decode([]byte) error
|
||||||
|
copy() RequestData // creates a deep copy and initializes all fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeRLP implements rlp.Encoder
|
||||||
|
func (r *Request) EncodeRLP(w io.Writer) error {
|
||||||
|
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
||||||
|
defer encodeBufferPool.Put(buf)
|
||||||
|
buf.Reset()
|
||||||
|
if err := r.encode(buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rlp.Encode(w, buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode writes the canonical encoding of a request to w.
|
||||||
|
func (r *Request) encode(w *bytes.Buffer) error {
|
||||||
|
w.WriteByte(r.Type())
|
||||||
|
return r.inner.encode(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalBinary returns the canonical encoding of the request.
|
||||||
|
func (r *Request) MarshalBinary() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := r.encode(&buf)
|
||||||
|
return buf.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeRLP implements rlp.Decoder
|
||||||
|
func (r *Request) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
kind, size, err := s.Kind()
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
return err
|
||||||
|
case kind == rlp.List:
|
||||||
|
return fmt.Errorf("untyped request")
|
||||||
|
case kind == rlp.Byte:
|
||||||
|
return errShortTypedRequest
|
||||||
|
default:
|
||||||
|
// First read the request payload bytes into a temporary buffer.
|
||||||
|
b, buf, err := getPooledBuffer(size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer encodeBufferPool.Put(buf)
|
||||||
|
if err := s.ReadBytes(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Now decode the inner request.
|
||||||
|
inner, err := r.decode(b)
|
||||||
|
if err == nil {
|
||||||
|
r.inner = inner
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary decodes the canonical encoding of requests.
|
||||||
|
func (r *Request) UnmarshalBinary(b []byte) error {
|
||||||
|
inner, err := r.decode(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.inner = inner
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode decodes a request from the canonical format.
|
||||||
|
func (r *Request) decode(b []byte) (RequestData, error) {
|
||||||
|
if len(b) <= 1 {
|
||||||
|
return nil, errShortTypedRequest
|
||||||
|
}
|
||||||
|
var inner RequestData
|
||||||
|
switch b[0] {
|
||||||
|
case DepositRequestType:
|
||||||
|
inner = new(Deposit)
|
||||||
|
default:
|
||||||
|
return nil, ErrRequestTypeNotSupported
|
||||||
|
}
|
||||||
|
err := inner.decode(b[1:])
|
||||||
|
return inner, err
|
||||||
|
}
|
||||||
|
|
@ -216,11 +216,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
if config.OverrideVerkle != nil {
|
if config.OverrideVerkle != nil {
|
||||||
overrides.OverrideVerkle = config.OverrideVerkle
|
overrides.OverrideVerkle = config.OverrideVerkle
|
||||||
}
|
}
|
||||||
// TODO (MariusVanDerWijden) get rid of shouldPreserve in a follow-up PR
|
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, &config.TransactionHistory)
|
||||||
shouldPreserve := func(header *types.Header) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, shouldPreserve, &config.TransactionHistory)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,15 @@ var caps = []string{
|
||||||
"engine_getPayloadV1",
|
"engine_getPayloadV1",
|
||||||
"engine_getPayloadV2",
|
"engine_getPayloadV2",
|
||||||
"engine_getPayloadV3",
|
"engine_getPayloadV3",
|
||||||
|
"engine_getPayloadV4",
|
||||||
"engine_newPayloadV1",
|
"engine_newPayloadV1",
|
||||||
"engine_newPayloadV2",
|
"engine_newPayloadV2",
|
||||||
"engine_newPayloadV3",
|
"engine_newPayloadV3",
|
||||||
|
"engine_newPayloadV4",
|
||||||
"engine_getPayloadBodiesByHashV1",
|
"engine_getPayloadBodiesByHashV1",
|
||||||
|
"engine_getPayloadBodiesByHashV2",
|
||||||
"engine_getPayloadBodiesByRangeV1",
|
"engine_getPayloadBodiesByRangeV1",
|
||||||
|
"engine_getPayloadBodiesByRangeV2",
|
||||||
"engine_getClientVersionV1",
|
"engine_getClientVersionV1",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +224,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
|
||||||
if params.BeaconRoot == nil {
|
if params.BeaconRoot == nil {
|
||||||
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
|
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
|
||||||
}
|
}
|
||||||
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
|
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
|
||||||
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
|
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -443,6 +447,14 @@ func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.Execu
|
||||||
return api.getPayload(payloadID, false)
|
return api.getPayload(payloadID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPayloadV4 returns a cached payload by id.
|
||||||
|
func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
||||||
|
if !payloadID.Is(engine.PayloadV4) {
|
||||||
|
return nil, engine.UnsupportedFork
|
||||||
|
}
|
||||||
|
return api.getPayload(payloadID, false)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) {
|
func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) {
|
||||||
log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID)
|
log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID)
|
||||||
data := api.localBlocks.get(payloadID, full)
|
data := api.localBlocks.get(payloadID, full)
|
||||||
|
|
@ -508,6 +520,34 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
|
||||||
return api.newPayload(params, versionedHashes, beaconRoot)
|
return api.newPayload(params, versionedHashes, beaconRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPayloadV4 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
|
||||||
|
func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
|
||||||
|
if params.Withdrawals == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
|
||||||
|
}
|
||||||
|
if params.ExcessBlobGas == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
|
||||||
|
}
|
||||||
|
if params.BlobGasUsed == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
|
||||||
|
}
|
||||||
|
if params.Deposits == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil deposits post-prague"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if versionedHashes == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
|
||||||
|
}
|
||||||
|
if beaconRoot == nil {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
|
||||||
|
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads"))
|
||||||
|
}
|
||||||
|
return api.newPayload(params, versionedHashes, beaconRoot)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
|
func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
|
||||||
// The locking here is, strictly, not required. Without these locks, this can happen:
|
// The locking here is, strictly, not required. Without these locks, this can happen:
|
||||||
//
|
//
|
||||||
|
|
@ -553,6 +593,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
|
||||||
"params.ExcessBlobGas", ebg,
|
"params.ExcessBlobGas", ebg,
|
||||||
"len(params.Transactions)", len(params.Transactions),
|
"len(params.Transactions)", len(params.Transactions),
|
||||||
"len(params.Withdrawals)", len(params.Withdrawals),
|
"len(params.Withdrawals)", len(params.Withdrawals),
|
||||||
|
"len(params.Deposits)", len(params.Deposits),
|
||||||
"beaconRoot", beaconRoot,
|
"beaconRoot", beaconRoot,
|
||||||
"error", err)
|
"error", err)
|
||||||
return api.invalid(err, nil), nil
|
return api.invalid(err, nil), nil
|
||||||
|
|
@ -826,8 +867,25 @@ func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engin
|
||||||
|
|
||||||
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
||||||
// of block bodies by the engine api.
|
// of block bodies by the engine api.
|
||||||
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
|
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBody {
|
||||||
bodies := make([]*engine.ExecutionPayloadBodyV1, len(hashes))
|
bodies := make([]*engine.ExecutionPayloadBody, len(hashes))
|
||||||
|
for i, hash := range hashes {
|
||||||
|
block := api.eth.BlockChain().GetBlockByHash(hash)
|
||||||
|
body := getBody(block)
|
||||||
|
if body != nil {
|
||||||
|
// Nil out the V2 values, clients should know to not request V1 objects
|
||||||
|
// after Prague.
|
||||||
|
body.Deposits = nil
|
||||||
|
}
|
||||||
|
bodies[i] = body
|
||||||
|
}
|
||||||
|
return bodies
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayloadBodiesByHashV2 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
||||||
|
// of block bodies by the engine api.
|
||||||
|
func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engine.ExecutionPayloadBody {
|
||||||
|
bodies := make([]*engine.ExecutionPayloadBody, len(hashes))
|
||||||
for i, hash := range hashes {
|
for i, hash := range hashes {
|
||||||
block := api.eth.BlockChain().GetBlockByHash(hash)
|
block := api.eth.BlockChain().GetBlockByHash(hash)
|
||||||
bodies[i] = getBody(block)
|
bodies[i] = getBody(block)
|
||||||
|
|
@ -837,7 +895,28 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
|
||||||
|
|
||||||
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
||||||
// of block bodies by the engine api.
|
// of block bodies by the engine api.
|
||||||
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) {
|
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
||||||
|
bodies, err := api.getBodiesByRange(start, count)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Nil out the V2 values, clients should know to not request V1 objects
|
||||||
|
// after Prague.
|
||||||
|
for i := range bodies {
|
||||||
|
if bodies[i] != nil {
|
||||||
|
bodies[i].Deposits = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bodies, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPayloadBodiesByRangeV2 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
||||||
|
// of block bodies by the engine api.
|
||||||
|
func (api *ConsensusAPI) GetPayloadBodiesByRangeV2(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
||||||
|
return api.getBodiesByRange(start, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *ConsensusAPI) getBodiesByRange(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
||||||
if start == 0 || count == 0 {
|
if start == 0 || count == 0 {
|
||||||
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
|
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
|
||||||
}
|
}
|
||||||
|
|
@ -850,7 +929,7 @@ func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64)
|
||||||
if last > current {
|
if last > current {
|
||||||
last = current
|
last = current
|
||||||
}
|
}
|
||||||
bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count))
|
bodies := make([]*engine.ExecutionPayloadBody, 0, uint64(count))
|
||||||
for i := uint64(start); i <= last; i++ {
|
for i := uint64(start); i <= last; i++ {
|
||||||
block := api.eth.BlockChain().GetBlockByNumber(i)
|
block := api.eth.BlockChain().GetBlockByNumber(i)
|
||||||
bodies = append(bodies, getBody(block))
|
bodies = append(bodies, getBody(block))
|
||||||
|
|
@ -858,15 +937,16 @@ func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64)
|
||||||
return bodies, nil
|
return bodies, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
|
func getBody(block *types.Block) *engine.ExecutionPayloadBody {
|
||||||
if block == nil {
|
if block == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
body = block.Body()
|
body = block.Body()
|
||||||
txs = make([]hexutil.Bytes, len(body.Transactions))
|
txs = make([]hexutil.Bytes, len(body.Transactions))
|
||||||
withdrawals = body.Withdrawals
|
withdrawals = body.Withdrawals
|
||||||
|
depositRequests types.Deposits
|
||||||
)
|
)
|
||||||
|
|
||||||
for j, tx := range body.Transactions {
|
for j, tx := range body.Transactions {
|
||||||
|
|
@ -878,8 +958,20 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
|
||||||
withdrawals = make([]*types.Withdrawal, 0)
|
withdrawals = make([]*types.Withdrawal, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &engine.ExecutionPayloadBodyV1{
|
if block.Header().RequestsHash != nil {
|
||||||
|
// TODO: this isn't future proof because we can't determine if a request
|
||||||
|
// type has activated yet or if there are just no requests of that type from
|
||||||
|
// only the block.
|
||||||
|
for _, req := range block.Requests() {
|
||||||
|
if d, ok := req.Inner().(*types.Deposit); ok {
|
||||||
|
depositRequests = append(depositRequests, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &engine.ExecutionPayloadBody{
|
||||||
TransactionData: txs,
|
TransactionData: txs,
|
||||||
Withdrawals: withdrawals,
|
Withdrawals: withdrawals,
|
||||||
|
Deposits: depositRequests,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
||||||
Alloc: types.GenesisAlloc{
|
Alloc: types.GenesisAlloc{
|
||||||
testAddr: {Balance: testBalance},
|
testAddr: {Balance: testBalance},
|
||||||
params.BeaconRootsAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")},
|
params.BeaconRootsAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")},
|
||||||
|
config.DepositContractAddress: {
|
||||||
|
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
|
||||||
|
Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ExtraData: []byte("test genesis"),
|
ExtraData: []byte("test genesis"),
|
||||||
Timestamp: 9000,
|
Timestamp: 9000,
|
||||||
|
|
@ -483,10 +489,10 @@ func TestFullAPI(t *testing.T) {
|
||||||
ethservice.TxPool().Add([]*types.Transaction{tx}, true, false)
|
ethservice.TxPool().Add([]*types.Transaction{tx}, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
setupBlocks(t, ethservice, 10, parent, callback, nil)
|
setupBlocks(t, ethservice, 10, parent, callback, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal) []*types.Header {
|
func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal, beaconRoots []common.Hash) []*types.Header {
|
||||||
api := NewConsensusAPI(ethservice)
|
api := NewConsensusAPI(ethservice)
|
||||||
var blocks []*types.Header
|
var blocks []*types.Header
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
|
|
@ -495,14 +501,18 @@ func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.He
|
||||||
if withdrawals != nil {
|
if withdrawals != nil {
|
||||||
w = withdrawals[i]
|
w = withdrawals[i]
|
||||||
}
|
}
|
||||||
|
var h *common.Hash
|
||||||
|
if beaconRoots != nil {
|
||||||
|
h = &beaconRoots[i]
|
||||||
|
}
|
||||||
|
|
||||||
payload := getNewPayload(t, api, parent, w)
|
payload := getNewPayload(t, api, parent, w, h)
|
||||||
execResp, err := api.NewPayloadV2(*payload)
|
execResp, err := api.newPayload(*payload, []common.Hash{}, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't execute payload: %v", err)
|
t.Fatalf("can't execute payload: %v", err)
|
||||||
}
|
}
|
||||||
if execResp.Status != engine.VALID {
|
if execResp.Status != engine.VALID {
|
||||||
t.Fatalf("invalid status: %v", execResp.Status)
|
t.Fatalf("invalid status: %v %s", execResp.Status, *execResp.ValidationError)
|
||||||
}
|
}
|
||||||
fcState := engine.ForkchoiceStateV1{
|
fcState := engine.ForkchoiceStateV1{
|
||||||
HeadBlockHash: payload.BlockHash,
|
HeadBlockHash: payload.BlockHash,
|
||||||
|
|
@ -690,10 +700,10 @@ func TestEmptyBlocks(t *testing.T) {
|
||||||
api := NewConsensusAPI(ethservice)
|
api := NewConsensusAPI(ethservice)
|
||||||
|
|
||||||
// Setup 10 blocks on the canonical chain
|
// Setup 10 blocks on the canonical chain
|
||||||
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil)
|
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil, nil)
|
||||||
|
|
||||||
// (1) check LatestValidHash by sending a normal payload (P1'')
|
// (1) check LatestValidHash by sending a normal payload (P1'')
|
||||||
payload := getNewPayload(t, api, commonAncestor, nil)
|
payload := getNewPayload(t, api, commonAncestor, nil, nil)
|
||||||
|
|
||||||
status, err := api.NewPayloadV1(*payload)
|
status, err := api.NewPayloadV1(*payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -707,7 +717,7 @@ func TestEmptyBlocks(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (2) Now send P1' which is invalid
|
// (2) Now send P1' which is invalid
|
||||||
payload = getNewPayload(t, api, commonAncestor, nil)
|
payload = getNewPayload(t, api, commonAncestor, nil, nil)
|
||||||
payload.GasUsed += 1
|
payload.GasUsed += 1
|
||||||
payload = setBlockhash(payload)
|
payload = setBlockhash(payload)
|
||||||
// Now latestValidHash should be the common ancestor
|
// Now latestValidHash should be the common ancestor
|
||||||
|
|
@ -725,7 +735,7 @@ func TestEmptyBlocks(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (3) Now send a payload with unknown parent
|
// (3) Now send a payload with unknown parent
|
||||||
payload = getNewPayload(t, api, commonAncestor, nil)
|
payload = getNewPayload(t, api, commonAncestor, nil, nil)
|
||||||
payload.ParentHash = common.Hash{1}
|
payload.ParentHash = common.Hash{1}
|
||||||
payload = setBlockhash(payload)
|
payload = setBlockhash(payload)
|
||||||
// Now latestValidHash should be the common ancestor
|
// Now latestValidHash should be the common ancestor
|
||||||
|
|
@ -741,12 +751,13 @@ func TestEmptyBlocks(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Header, withdrawals []*types.Withdrawal) *engine.ExecutableData {
|
func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Header, withdrawals []*types.Withdrawal, beaconRoot *common.Hash) *engine.ExecutableData {
|
||||||
params := engine.PayloadAttributes{
|
params := engine.PayloadAttributes{
|
||||||
Timestamp: parent.Time + 1,
|
Timestamp: parent.Time + 1,
|
||||||
Random: crypto.Keccak256Hash([]byte{byte(1)}),
|
Random: crypto.Keccak256Hash([]byte{byte(1)}),
|
||||||
SuggestedFeeRecipient: parent.Coinbase,
|
SuggestedFeeRecipient: parent.Coinbase,
|
||||||
Withdrawals: withdrawals,
|
Withdrawals: withdrawals,
|
||||||
|
BeaconRoot: beaconRoot,
|
||||||
}
|
}
|
||||||
|
|
||||||
payload, err := assembleBlock(api, parent.Hash(), ¶ms)
|
payload, err := assembleBlock(api, parent.Hash(), ¶ms)
|
||||||
|
|
@ -814,7 +825,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
||||||
commonAncestor := ethserviceA.BlockChain().CurrentBlock()
|
commonAncestor := ethserviceA.BlockChain().CurrentBlock()
|
||||||
|
|
||||||
// Setup 10 blocks on the canonical chain
|
// Setup 10 blocks on the canonical chain
|
||||||
setupBlocks(t, ethserviceA, 10, commonAncestor, func(parent *types.Header) {}, nil)
|
setupBlocks(t, ethserviceA, 10, commonAncestor, func(parent *types.Header) {}, nil, nil)
|
||||||
commonAncestor = ethserviceA.BlockChain().CurrentBlock()
|
commonAncestor = ethserviceA.BlockChain().CurrentBlock()
|
||||||
|
|
||||||
var invalidChain []*engine.ExecutableData
|
var invalidChain []*engine.ExecutableData
|
||||||
|
|
@ -823,7 +834,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
||||||
//invalidChain = append(invalidChain, payload1)
|
//invalidChain = append(invalidChain, payload1)
|
||||||
|
|
||||||
// create an invalid payload2 (P2)
|
// create an invalid payload2 (P2)
|
||||||
payload2 := getNewPayload(t, apiA, commonAncestor, nil)
|
payload2 := getNewPayload(t, apiA, commonAncestor, nil, nil)
|
||||||
//payload2.ParentHash = payload1.BlockHash
|
//payload2.ParentHash = payload1.BlockHash
|
||||||
payload2.GasUsed += 1
|
payload2.GasUsed += 1
|
||||||
payload2 = setBlockhash(payload2)
|
payload2 = setBlockhash(payload2)
|
||||||
|
|
@ -832,7 +843,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
||||||
head := payload2
|
head := payload2
|
||||||
// create some valid payloads on top
|
// create some valid payloads on top
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
payload := getNewPayload(t, apiA, commonAncestor, nil)
|
payload := getNewPayload(t, apiA, commonAncestor, nil, nil)
|
||||||
payload.ParentHash = head.BlockHash
|
payload.ParentHash = head.BlockHash
|
||||||
payload = setBlockhash(payload)
|
payload = setBlockhash(payload)
|
||||||
invalidChain = append(invalidChain, payload)
|
invalidChain = append(invalidChain, payload)
|
||||||
|
|
@ -869,10 +880,10 @@ func TestInvalidBloom(t *testing.T) {
|
||||||
api := NewConsensusAPI(ethservice)
|
api := NewConsensusAPI(ethservice)
|
||||||
|
|
||||||
// Setup 10 blocks on the canonical chain
|
// Setup 10 blocks on the canonical chain
|
||||||
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil)
|
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil, nil)
|
||||||
|
|
||||||
// (1) check LatestValidHash by sending a normal payload (P1'')
|
// (1) check LatestValidHash by sending a normal payload (P1'')
|
||||||
payload := getNewPayload(t, api, commonAncestor, nil)
|
payload := getNewPayload(t, api, commonAncestor, nil, nil)
|
||||||
payload.LogsBloom = append(payload.LogsBloom, byte(1))
|
payload.LogsBloom = append(payload.LogsBloom, byte(1))
|
||||||
status, err := api.NewPayloadV1(*payload)
|
status, err := api.NewPayloadV1(*payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1285,24 +1296,35 @@ func TestNilWithdrawals(t *testing.T) {
|
||||||
|
|
||||||
func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
|
func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
|
||||||
genesis, blocks := generateMergeChain(10, true)
|
genesis, blocks := generateMergeChain(10, true)
|
||||||
// enable shanghai on the last block
|
|
||||||
|
// Enable next forks on the last block.
|
||||||
time := blocks[len(blocks)-1].Header().Time + 1
|
time := blocks[len(blocks)-1].Header().Time + 1
|
||||||
genesis.Config.ShanghaiTime = &time
|
genesis.Config.ShanghaiTime = &time
|
||||||
|
genesis.Config.CancunTime = &time
|
||||||
|
genesis.Config.PragueTime = &time
|
||||||
|
|
||||||
n, ethservice := startEthService(t, genesis, blocks)
|
n, ethservice := startEthService(t, genesis, blocks)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
parent = ethservice.BlockChain().CurrentBlock()
|
|
||||||
// This EVM code generates a log when the contract is created.
|
// This EVM code generates a log when the contract is created.
|
||||||
logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
||||||
|
parent = ethservice.BlockChain().CurrentBlock()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Each block, this callback will include two txs that generate body values like logs and requests.
|
||||||
callback := func(parent *types.Header) {
|
callback := func(parent *types.Header) {
|
||||||
statedb, _ := ethservice.BlockChain().StateAt(parent.Root)
|
var (
|
||||||
nonce := statedb.GetNonce(testAddr)
|
statedb, _ = ethservice.BlockChain().StateAt(parent.Root)
|
||||||
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
|
// Create tx to trigger log generator.
|
||||||
ethservice.TxPool().Add([]*types.Transaction{tx}, false, false)
|
tx1, _ = types.SignTx(types.NewContractCreation(statedb.GetNonce(testAddr), new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
|
||||||
|
// Create tx to trigger deposit generator.
|
||||||
|
tx2, _ = types.SignTx(types.NewTransaction(statedb.GetNonce(testAddr)+1, ethservice.APIBackend.ChainConfig().DepositContractAddress, new(big.Int), 500000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
|
||||||
|
)
|
||||||
|
ethservice.TxPool().Add([]*types.Transaction{tx1}, false, false)
|
||||||
|
ethservice.TxPool().Add([]*types.Transaction{tx2}, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make some withdrawals to include.
|
||||||
withdrawals := make([][]*types.Withdrawal, 10)
|
withdrawals := make([][]*types.Withdrawal, 10)
|
||||||
withdrawals[0] = nil // should be filtered out by miner
|
withdrawals[0] = nil // should be filtered out by miner
|
||||||
withdrawals[1] = make([]*types.Withdrawal, 0)
|
withdrawals[1] = make([]*types.Withdrawal, 0)
|
||||||
|
|
@ -1314,12 +1336,20 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
postShanghaiHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals)
|
// Make beacon root update for each block.
|
||||||
postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders))
|
beaconRoots := make([]common.Hash, 10)
|
||||||
for i, header := range postShanghaiHeaders {
|
for i := 0; i < 10; i++ {
|
||||||
postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64())
|
beaconRoots[i] = common.Hash{byte(i)}
|
||||||
}
|
}
|
||||||
return n, ethservice, append(blocks, postShanghaiBlocks...)
|
|
||||||
|
// Create the blocks.
|
||||||
|
newHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals, beaconRoots)
|
||||||
|
newBlocks := make([]*types.Block, len(newHeaders))
|
||||||
|
for i, header := range newHeaders {
|
||||||
|
newBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64())
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, ethservice, append(blocks, newBlocks...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func allHashes(blocks []*types.Block) []common.Hash {
|
func allHashes(blocks []*types.Block) []common.Hash {
|
||||||
|
|
@ -1384,7 +1414,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, test := range tests {
|
for k, test := range tests {
|
||||||
result := api.GetPayloadBodiesByHashV1(test.hashes)
|
result := api.GetPayloadBodiesByHashV2(test.hashes)
|
||||||
for i, r := range result {
|
for i, r := range result {
|
||||||
if !equalBody(test.results[i], r) {
|
if !equalBody(test.results[i], r) {
|
||||||
t.Fatalf("test %v: invalid response: expected %+v got %+v", k, test.results[i], r)
|
t.Fatalf("test %v: invalid response: expected %+v got %+v", k, test.results[i], r)
|
||||||
|
|
@ -1458,7 +1488,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, test := range tests {
|
for k, test := range tests {
|
||||||
result, err := api.GetPayloadBodiesByRangeV1(test.start, test.count)
|
result, err := api.GetPayloadBodiesByRangeV2(test.start, test.count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1509,7 +1539,7 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count)
|
result, err := api.GetPayloadBodiesByRangeV2(tc.start, tc.count)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("test %d: expected error, got %v", i, result)
|
t.Fatalf("test %d: expected error, got %v", i, result)
|
||||||
}
|
}
|
||||||
|
|
@ -1519,7 +1549,7 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool {
|
func equalBody(a *types.Body, b *engine.ExecutionPayloadBody) bool {
|
||||||
if a == nil && b == nil {
|
if a == nil && b == nil {
|
||||||
return true
|
return true
|
||||||
} else if a == nil || b == nil {
|
} else if a == nil || b == nil {
|
||||||
|
|
@ -1534,7 +1564,23 @@ func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reflect.DeepEqual(a.Withdrawals, b.Withdrawals)
|
|
||||||
|
if !reflect.DeepEqual(a.Withdrawals, b.Withdrawals) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var deposits types.Deposits
|
||||||
|
if a.Requests != nil {
|
||||||
|
// If requests is non-nil, it means deposits are available in block and we
|
||||||
|
// should return an empty slice instead of nil if there are no deposits.
|
||||||
|
deposits = make(types.Deposits, 0)
|
||||||
|
}
|
||||||
|
for _, r := range a.Requests {
|
||||||
|
if d, ok := r.Inner().(*types.Deposit); ok {
|
||||||
|
deposits = append(deposits, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reflect.DeepEqual(deposits, b.Deposits)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockToPayloadWithBlobs(t *testing.T) {
|
func TestBlockToPayloadWithBlobs(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, err
|
||||||
|
|
||||||
// if genesis block, send forkchoiceUpdated to trigger transition to PoS
|
// if genesis block, send forkchoiceUpdated to trigger transition to PoS
|
||||||
if block.Number.Sign() == 0 {
|
if block.Number.Sign() == 0 {
|
||||||
if _, err := engineAPI.ForkchoiceUpdatedV2(current, nil); err != nil {
|
if _, err := engineAPI.ForkchoiceUpdatedV3(current, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +226,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
|
||||||
c.setCurrentState(payload.BlockHash, finalizedHash)
|
c.setCurrentState(payload.BlockHash, finalizedHash)
|
||||||
|
|
||||||
// Mark the block containing the payload as canonical
|
// Mark the block containing the payload as canonical
|
||||||
if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
|
if _, err = c.engineAPI.ForkchoiceUpdatedV3(c.curForkchoiceState, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.lastBlockTime = payload.Timestamp
|
c.lastBlockTime = payload.Timestamp
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
||||||
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
|
Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -230,6 +230,7 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et
|
||||||
txsHashes = make([]common.Hash, len(bodies))
|
txsHashes = make([]common.Hash, len(bodies))
|
||||||
uncleHashes = make([]common.Hash, len(bodies))
|
uncleHashes = make([]common.Hash, len(bodies))
|
||||||
withdrawalHashes = make([]common.Hash, len(bodies))
|
withdrawalHashes = make([]common.Hash, len(bodies))
|
||||||
|
requestsHashes = make([]common.Hash, len(bodies))
|
||||||
)
|
)
|
||||||
hasher := trie.NewStackTrie(nil)
|
hasher := trie.NewStackTrie(nil)
|
||||||
for i, body := range bodies {
|
for i, body := range bodies {
|
||||||
|
|
@ -248,7 +249,7 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et
|
||||||
res := ð.Response{
|
res := ð.Response{
|
||||||
Req: req,
|
Req: req,
|
||||||
Res: (*eth.BlockBodiesResponse)(&bodies),
|
Res: (*eth.BlockBodiesResponse)(&bodies),
|
||||||
Meta: [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes},
|
Meta: [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes, requestsHashes},
|
||||||
Time: 1,
|
Time: 1,
|
||||||
Done: make(chan error, 1), // Ignore the returned status
|
Done: make(chan error, 1), // Ignore the returned status
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,10 @@ func (q *bodyQueue) request(peer *peerConnection, req *fetchRequest, resCh chan
|
||||||
// deliver is responsible for taking a generic response packet from the concurrent
|
// deliver is responsible for taking a generic response packet from the concurrent
|
||||||
// fetcher, unpacking the body data and delivering it to the downloader's queue.
|
// fetcher, unpacking the body data and delivering it to the downloader's queue.
|
||||||
func (q *bodyQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) {
|
func (q *bodyQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) {
|
||||||
txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesResponse).Unpack()
|
txs, uncles, withdrawals, requests := packet.Res.(*eth.BlockBodiesResponse).Unpack()
|
||||||
hashsets := packet.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes}
|
hashsets := packet.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes, requests hashes}
|
||||||
|
|
||||||
accepted, err := q.queue.DeliverBodies(peer.id, txs, hashsets[0], uncles, hashsets[1], withdrawals, hashsets[2])
|
accepted, err := q.queue.DeliverBodies(peer.id, txs, hashsets[0], uncles, hashsets[1], withdrawals, hashsets[2], requests, hashsets[3])
|
||||||
switch {
|
switch {
|
||||||
case err == nil && len(txs) == 0:
|
case err == nil && len(txs) == 0:
|
||||||
peer.log.Trace("Requested bodies delivered")
|
peer.log.Trace("Requested bodies delivered")
|
||||||
|
|
|
||||||
|
|
@ -784,7 +784,8 @@ func (q *queue) DeliverHeaders(id string, headers []*types.Header, hashes []comm
|
||||||
// also wakes any threads waiting for data delivery.
|
// also wakes any threads waiting for data delivery.
|
||||||
func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListHashes []common.Hash,
|
func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListHashes []common.Hash,
|
||||||
uncleLists [][]*types.Header, uncleListHashes []common.Hash,
|
uncleLists [][]*types.Header, uncleListHashes []common.Hash,
|
||||||
withdrawalLists [][]*types.Withdrawal, withdrawalListHashes []common.Hash) (int, error) {
|
withdrawalLists [][]*types.Withdrawal, withdrawalListHashes []common.Hash,
|
||||||
|
requestsLists [][]*types.Request, requestsListHashes []common.Hash) (int, error) {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
defer q.lock.Unlock()
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -808,6 +809,19 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
|
||||||
return errInvalidBody
|
return errInvalidBody
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if header.RequestsHash == nil {
|
||||||
|
// nil hash means that requests should not be present in body
|
||||||
|
if requestsLists[index] != nil {
|
||||||
|
return errInvalidBody
|
||||||
|
}
|
||||||
|
} else { // non-nil hash: body must have requests
|
||||||
|
if requestsLists[index] == nil {
|
||||||
|
return errInvalidBody
|
||||||
|
}
|
||||||
|
if requestsListHashes[index] != *header.RequestsHash {
|
||||||
|
return errInvalidBody
|
||||||
|
}
|
||||||
|
}
|
||||||
// Blocks must have a number of blobs corresponding to the header gas usage,
|
// Blocks must have a number of blobs corresponding to the header gas usage,
|
||||||
// and zero before the Cancun hardfork.
|
// and zero before the Cancun hardfork.
|
||||||
var blobs int
|
var blobs int
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,7 @@ func XTestDelivery(t *testing.T) {
|
||||||
uncleHashes[i] = types.CalcUncleHash(uncles)
|
uncleHashes[i] = types.CalcUncleHash(uncles)
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
_, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil)
|
_, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("delivered %d bodies %v\n", len(txset), err)
|
fmt.Printf("delivered %d bodies %v\n", len(txset), err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ func newTestBlockchain(blocks []*types.Block) *core.BlockChain {
|
||||||
if pregenerated {
|
if pregenerated {
|
||||||
panic("Requested chain generation outside of init")
|
panic("Requested chain generation outside of init")
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, testGspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, testGspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ func TestFilters(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var l uint64
|
var l uint64
|
||||||
bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
|
bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, &l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pe
|
||||||
})
|
})
|
||||||
// Construct testing chain
|
// Construct testing chain
|
||||||
gspec.Config.TerminalTotalDifficulty = new(big.Int).SetUint64(td)
|
gspec.Config.TerminalTotalDifficulty = new(big.Int).SetUint64(td)
|
||||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create local chain, %v", err)
|
t.Fatalf("Failed to create local chain, %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@ func testForkIDSplit(t *testing.T, protocol uint) {
|
||||||
gspecNoFork = &core.Genesis{Config: configNoFork}
|
gspecNoFork = &core.Genesis{Config: configNoFork}
|
||||||
gspecProFork = &core.Genesis{Config: configProFork}
|
gspecProFork = &core.Genesis{Config: configProFork}
|
||||||
|
|
||||||
chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, gspecNoFork, nil, engine, vm.Config{}, nil, nil)
|
chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, gspecNoFork, nil, engine, vm.Config{}, nil)
|
||||||
chainProFork, _ = core.NewBlockChain(dbProFork, nil, gspecProFork, nil, engine, vm.Config{}, nil, nil)
|
chainProFork, _ = core.NewBlockChain(dbProFork, nil, gspecProFork, nil, engine, vm.Config{}, nil)
|
||||||
|
|
||||||
_, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil)
|
_, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil)
|
||||||
_, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil)
|
_, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil)
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
|
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
|
||||||
}
|
}
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
|
||||||
_, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil)
|
_, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil)
|
||||||
if _, err := chain.InsertChain(bs); err != nil {
|
if _, err := chain.InsertChain(bs); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
|
||||||
Config: config,
|
Config: config,
|
||||||
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
|
Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
|
||||||
}
|
}
|
||||||
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
|
|
||||||
_, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator)
|
_, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator)
|
||||||
if _, err := chain.InsertChain(bs); err != nil {
|
if _, err := chain.InsertChain(bs); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
txsHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
txsHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
||||||
uncleHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
uncleHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
||||||
withdrawalHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
withdrawalHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
||||||
|
requestsHashes = make([]common.Hash, len(res.BlockBodiesResponse))
|
||||||
)
|
)
|
||||||
hasher := trie.NewStackTrie(nil)
|
hasher := trie.NewStackTrie(nil)
|
||||||
for i, body := range res.BlockBodiesResponse {
|
for i, body := range res.BlockBodiesResponse {
|
||||||
|
|
@ -324,8 +325,11 @@ func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
if body.Withdrawals != nil {
|
if body.Withdrawals != nil {
|
||||||
withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher)
|
withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher)
|
||||||
}
|
}
|
||||||
|
if body.Requests != nil {
|
||||||
|
requestsHashes[i] = types.DeriveSha(types.Requests(body.Requests), hasher)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes}
|
return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes, requestsHashes}
|
||||||
}
|
}
|
||||||
return peer.dispatchResponse(&Response{
|
return peer.dispatchResponse(&Response{
|
||||||
id: res.RequestId,
|
id: res.RequestId,
|
||||||
|
|
|
||||||
|
|
@ -224,21 +224,22 @@ type BlockBody struct {
|
||||||
Transactions []*types.Transaction // Transactions contained within a block
|
Transactions []*types.Transaction // Transactions contained within a block
|
||||||
Uncles []*types.Header // Uncles contained within a block
|
Uncles []*types.Header // Uncles contained within a block
|
||||||
Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block
|
Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block
|
||||||
|
Requests []*types.Request `rlp:"optional"` // Requests contained within a block
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack retrieves the transactions and uncles from the range packet and returns
|
// Unpack retrieves the transactions and uncles from the range packet and returns
|
||||||
// them in a split flat format that's more consistent with the internal data structures.
|
// them in a split flat format that's more consistent with the internal data structures.
|
||||||
func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) {
|
func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal, [][]*types.Request) {
|
||||||
// TODO(matt): add support for withdrawals to fetchers
|
|
||||||
var (
|
var (
|
||||||
txset = make([][]*types.Transaction, len(*p))
|
txset = make([][]*types.Transaction, len(*p))
|
||||||
uncleset = make([][]*types.Header, len(*p))
|
uncleset = make([][]*types.Header, len(*p))
|
||||||
withdrawalset = make([][]*types.Withdrawal, len(*p))
|
withdrawalset = make([][]*types.Withdrawal, len(*p))
|
||||||
|
requestset = make([][]*types.Request, len(*p))
|
||||||
)
|
)
|
||||||
for i, body := range *p {
|
for i, body := range *p {
|
||||||
txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals
|
txset[i], uncleset[i], withdrawalset[i], requestset[i] = body.Transactions, body.Uncles, body.Withdrawals, body.Requests
|
||||||
}
|
}
|
||||||
return txset, uncleset, withdrawalset
|
return txset, uncleset, withdrawalset, requestset
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReceiptsRequest represents a block receipts query.
|
// GetReceiptsRequest represents a block receipts query.
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func getChain() *core.BlockChain {
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
}
|
}
|
||||||
trieRoot = blocks[len(blocks)-1].Root()
|
trieRoot = blocks[len(blocks)-1].Root()
|
||||||
bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if _, err := bc.InsertChain(blocks); err != nil {
|
if _, err := bc.InsertChain(blocks); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
||||||
if current = eth.blockchain.GetBlockByNumber(next); current == nil {
|
if current = eth.blockchain.GetBlockByNumber(next); current == nil {
|
||||||
return nil, nil, fmt.Errorf("block #%d not found", next)
|
return nil, nil, fmt.Errorf("block #%d not found", next)
|
||||||
}
|
}
|
||||||
_, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{})
|
_, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
|
return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i i
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
TrieDirtyDisabled: true, // Archive mode
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1014,7 +1014,7 @@ func newTestMergedBackend(t *testing.T, n int, gspec *core.Genesis, generator fu
|
||||||
SnapshotLimit: 0,
|
SnapshotLimit: 0,
|
||||||
TrieDirtyDisabled: true, // Archive mode
|
TrieDirtyDisabled: true, // Archive mode
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,7 @@ func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockG
|
||||||
return nil, nil, fmt.Errorf("failed to create call tracer: %v", err)
|
return nil, nil, fmt.Errorf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), core.DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, engine, vm.Config{Tracer: tracer}, nil, nil)
|
chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), core.DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, engine, vm.Config{Tracer: tracer}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
return nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ func (t *mdLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, r
|
||||||
// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
|
// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
|
||||||
func (t *mdLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
func (t *mdLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||||
stack := scope.StackData()
|
stack := scope.StackData()
|
||||||
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
|
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, vm.OpCode(op).String(), cost)
|
||||||
|
|
||||||
if !t.cfg.DisableStack {
|
if !t.cfg.DisableStack {
|
||||||
// format stack
|
// format stack
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ type rpcBlock struct {
|
||||||
Transactions []rpcTransaction `json:"transactions"`
|
Transactions []rpcTransaction `json:"transactions"`
|
||||||
UncleHashes []common.Hash `json:"uncles"`
|
UncleHashes []common.Hash `json:"uncles"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||||
|
Requests []*types.Request `json:"requests,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
|
func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
|
||||||
|
|
@ -196,6 +197,7 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
||||||
Transactions: txs,
|
Transactions: txs,
|
||||||
Uncles: uncles,
|
Uncles: uncles,
|
||||||
Withdrawals: body.Withdrawals,
|
Withdrawals: body.Withdrawals,
|
||||||
|
Requests: body.Requests,
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"opRetro": {
|
|
||||||
"projectId": "0x79c2ae8858a5a3bd7f2e0da9509d727833ffa01f358b5969355f38ff32b20122"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1388,6 +1388,9 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
||||||
if head.ParentBeaconRoot != nil {
|
if head.ParentBeaconRoot != nil {
|
||||||
result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
|
result["parentBeaconBlockRoot"] = head.ParentBeaconRoot
|
||||||
}
|
}
|
||||||
|
if head.RequestsHash != nil {
|
||||||
|
result["requestsRoot"] = head.RequestsHash
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1423,6 +1426,9 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
|
||||||
if block.Header().WithdrawalsHash != nil {
|
if block.Header().WithdrawalsHash != nil {
|
||||||
fields["withdrawals"] = block.Withdrawals()
|
fields["withdrawals"] = block.Withdrawals()
|
||||||
}
|
}
|
||||||
|
if block.Header().RequestsHash != nil {
|
||||||
|
fields["requests"] = block.Requests()
|
||||||
|
}
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -451,7 +451,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
|
||||||
// Generate blocks for testing
|
// Generate blocks for testing
|
||||||
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
|
||||||
txlookupLimit := uint64(0)
|
txlookupLimit := uint64(0)
|
||||||
chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, &txlookupLimit)
|
chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, &txlookupLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ func createMiner(t *testing.T) *Miner {
|
||||||
// Create consensus engine
|
// Create consensus engine
|
||||||
engine := clique.New(chainConfig.Clique, chainDB)
|
engine := clique.New(chainConfig.Clique, chainDB)
|
||||||
// Create Ethereum backend
|
// Create Ethereum backend
|
||||||
bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil, nil)
|
bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create new chain %v", err)
|
t.Fatalf("can't create new chain %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
||||||
default:
|
default:
|
||||||
t.Fatalf("unexpected consensus engine type: %T", engine)
|
t.Fatalf("unexpected consensus engine type: %T", engine)
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("core.NewBlockChain failed: %v", err)
|
t.Fatalf("core.NewBlockChain failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,20 @@ func (miner *Miner) generateWork(params *generateParams) *newPayloadResult {
|
||||||
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit))
|
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(miner.config.Recommit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals}
|
body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals}
|
||||||
|
allLogs := make([]*types.Log, 0)
|
||||||
|
for _, r := range work.receipts {
|
||||||
|
allLogs = append(allLogs, r.Logs...)
|
||||||
|
}
|
||||||
|
// Read requests if Prague is enabled.
|
||||||
|
if miner.chainConfig.IsPrague(work.header.Number, work.header.Time) {
|
||||||
|
requests, err := core.ParseDepositLogs(allLogs, miner.chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return &newPayloadResult{err: err}
|
||||||
|
}
|
||||||
|
body.Requests = requests
|
||||||
|
}
|
||||||
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts)
|
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ func TestJWT(t *testing.T) {
|
||||||
expFail := []func() string{
|
expFail := []func() string{
|
||||||
// future
|
// future
|
||||||
func() string {
|
func() string {
|
||||||
return fmt.Sprintf("Bearer %v", issueToken(secret, nil, testClaim{"iat": time.Now().Unix() + int64(jwtExpiryTimeout.Seconds()) + 1}))
|
return fmt.Sprintf("Bearer %v", issueToken(secret, nil, testClaim{"iat": time.Now().Unix() + int64(jwtExpiryTimeout.Seconds()) + 60}))
|
||||||
},
|
},
|
||||||
// stale
|
// stale
|
||||||
func() string {
|
func() string {
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ var (
|
||||||
TerminalTotalDifficultyPassed: true,
|
TerminalTotalDifficultyPassed: true,
|
||||||
ShanghaiTime: newUint64(1681338455),
|
ShanghaiTime: newUint64(1681338455),
|
||||||
CancunTime: newUint64(1710338135),
|
CancunTime: newUint64(1710338135),
|
||||||
|
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
|
||||||
Ethash: new(EthashConfig),
|
Ethash: new(EthashConfig),
|
||||||
}
|
}
|
||||||
// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
|
// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
|
||||||
|
|
@ -337,6 +338,8 @@ type ChainConfig struct {
|
||||||
// TODO(karalabe): Drop this field eventually (always assuming PoS mode)
|
// TODO(karalabe): Drop this field eventually (always assuming PoS mode)
|
||||||
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
|
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
|
||||||
|
|
||||||
|
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
|
||||||
|
|
||||||
// Various consensus engines
|
// Various consensus engines
|
||||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,17 @@ func TestBlockchain(t *testing.T) {
|
||||||
// using 4.6 TGas
|
// using 4.6 TGas
|
||||||
bt.skipLoad(`.*randomStatetest94.json.*`)
|
bt.skipLoad(`.*randomStatetest94.json.*`)
|
||||||
|
|
||||||
|
// After the merge we would accept side chains as canonical even if they have lower td
|
||||||
|
bt.skipLoad(`.*bcMultiChainTest/ChainAtoChainB_difficultyB.json`)
|
||||||
|
bt.skipLoad(`.*bcMultiChainTest/CallContractFromNotBestBlock.json`)
|
||||||
|
bt.skipLoad(`.*bcTotalDifficultyTest/uncleBlockAtBlock3afterBlock4.json`)
|
||||||
|
bt.skipLoad(`.*bcTotalDifficultyTest/lotsOfBranchesOverrideAtTheMiddle.json`)
|
||||||
|
bt.skipLoad(`.*bcTotalDifficultyTest/sideChainWithMoreTransactions.json`)
|
||||||
|
bt.skipLoad(`.*bcForkStressTest/ForkStressTest.json`)
|
||||||
|
bt.skipLoad(`.*bcMultiChainTest/lotsOfLeafs.json`)
|
||||||
|
bt.skipLoad(`.*bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain.json`)
|
||||||
|
bt.skipLoad(`.*bcFrontierToHomestead/blockChainFrontierWithLargerTDvsHomesteadBlockchain2.json`)
|
||||||
|
|
||||||
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
|
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
|
||||||
execBlockTest(t, bt, test)
|
execBlockTest(t, bt, test)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
|
||||||
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
|
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
|
||||||
Tracer: tracer,
|
Tracer: tracer,
|
||||||
EnableWitnessCollection: witness,
|
EnableWitnessCollection: witness,
|
||||||
}, nil, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
ShanghaiTime: u64(0),
|
ShanghaiTime: u64(0),
|
||||||
CancunTime: u64(0),
|
CancunTime: u64(0),
|
||||||
PragueTime: u64(0),
|
PragueTime: u64(0),
|
||||||
|
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
||||||
},
|
},
|
||||||
"CancunToPragueAtTime15k": {
|
"CancunToPragueAtTime15k": {
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
|
|
@ -393,6 +394,7 @@ var Forks = map[string]*params.ChainConfig{
|
||||||
ShanghaiTime: u64(0),
|
ShanghaiTime: u64(0),
|
||||||
CancunTime: u64(0),
|
CancunTime: u64(0),
|
||||||
PragueTime: u64(15_000),
|
PragueTime: u64(15_000),
|
||||||
|
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue