core: add basic chain history support in GenerateChain (#28428)
This change improves GenerateChain to support internal chain history access (ChainReader) for the consensus engine and EVM. GenerateChain takes a `parent` block and the number of blocks to create. With my changes, the consensus engine and EVM can now access blocks from `parent` up to the block currently being generated. This is required to make the BLOCKHASH instruction work, and also needed to create real clique chains. Clique uses chain history to figure out if the current signer is in-turn, for example. I've also added some more accessors to BlockGen. These are helpful when creating transactions: - g.Signer returns a signer instance for the current block - g.Difficulty returns the current block difficulty - g.Gas returns the remaining gas amount Another fix in this commit concerns the receipts returned by GenerateChain. The receipts now have properly derived fields (BlockHash, etc.) and should generally match what would be returned by the RPC API.
This commit is contained in:
parent
447945e438
commit
bc42e88415
@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
|
||||
toaddr := common.Address{}
|
||||
data := make([]byte, nbytes)
|
||||
gas, _ := IntrinsicGas(data, nil, false, false, false, false)
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
||||
signer := gen.Signer()
|
||||
gasPrice := big.NewInt(0)
|
||||
if gen.header.BaseFee != nil {
|
||||
gasPrice = gen.header.BaseFee
|
||||
@ -128,7 +128,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
||||
if gen.header.BaseFee != nil {
|
||||
gasPrice = gen.header.BaseFee
|
||||
}
|
||||
signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), gen.header.Time)
|
||||
signer := gen.Signer()
|
||||
for {
|
||||
gas -= params.TxGas
|
||||
if gas < params.TxGas {
|
||||
|
@ -38,8 +38,8 @@ import (
|
||||
// See GenerateChain for a detailed explanation.
|
||||
type BlockGen struct {
|
||||
i int
|
||||
cm *chainMaker
|
||||
parent *types.Block
|
||||
chain []*types.Block
|
||||
header *types.Header
|
||||
statedb *state.StateDB
|
||||
|
||||
@ -49,7 +49,6 @@ type BlockGen struct {
|
||||
uncles []*types.Header
|
||||
withdrawals []*types.Withdrawal
|
||||
|
||||
config *params.ChainConfig
|
||||
engine consensus.Engine
|
||||
}
|
||||
|
||||
@ -88,13 +87,18 @@ func (b *BlockGen) SetPoS() {
|
||||
b.header.Difficulty = new(big.Int)
|
||||
}
|
||||
|
||||
// Difficulty returns the currently calculated difficulty of the block.
|
||||
func (b *BlockGen) Difficulty() *big.Int {
|
||||
return new(big.Int).Set(b.header.Difficulty)
|
||||
}
|
||||
|
||||
// SetParentBeaconRoot sets the parent beacon root field of the generated
|
||||
// block.
|
||||
func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
|
||||
b.header.ParentBeaconRoot = &root
|
||||
var (
|
||||
blockContext = NewEVMBlockContext(b.header, nil, &b.header.Coinbase)
|
||||
vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.config, vm.Config{})
|
||||
blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
||||
vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{})
|
||||
)
|
||||
ProcessBeaconBlockRoot(root, vmenv, b.statedb)
|
||||
}
|
||||
@ -111,7 +115,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||
b.SetCoinbase(common.Address{})
|
||||
}
|
||||
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
||||
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig)
|
||||
receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -125,11 +129,11 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||
// AddTx adds a transaction to the generated block. If no coinbase has
|
||||
// been set, the block's coinbase is set to the zero address.
|
||||
//
|
||||
// AddTx panics if the transaction cannot be executed. In addition to
|
||||
// the protocol-imposed limitations (gas limit, etc.), there are some
|
||||
// further limitations on the content of transactions that can be
|
||||
// added. Notably, contract code relying on the BLOCKHASH instruction
|
||||
// will panic during execution.
|
||||
// AddTx panics if the transaction cannot be executed. In addition to the protocol-imposed
|
||||
// limitations (gas limit, etc.), there are some further limitations on the content of
|
||||
// transactions that can be added. Notably, contract code relying on the BLOCKHASH
|
||||
// instruction will panic during execution if it attempts to access a block number outside
|
||||
// of the range created by GenerateChain.
|
||||
func (b *BlockGen) AddTx(tx *types.Transaction) {
|
||||
b.addTx(nil, vm.Config{}, tx)
|
||||
}
|
||||
@ -137,11 +141,10 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
|
||||
// AddTxWithChain adds a transaction to the generated block. If no coinbase has
|
||||
// been set, the block's coinbase is set to the zero address.
|
||||
//
|
||||
// AddTxWithChain panics if the transaction cannot be executed. In addition to
|
||||
// the protocol-imposed limitations (gas limit, etc.), there are some
|
||||
// further limitations on the content of transactions that can be
|
||||
// added. If contract code relies on the BLOCKHASH instruction,
|
||||
// the block in chain will be returned.
|
||||
// AddTxWithChain panics if the transaction cannot be executed. In addition to the
|
||||
// protocol-imposed limitations (gas limit, etc.), there are some further limitations on
|
||||
// the content of transactions that can be added. If contract code relies on the BLOCKHASH
|
||||
// instruction, the block in chain will be returned.
|
||||
func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
|
||||
b.addTx(bc, vm.Config{}, tx)
|
||||
}
|
||||
@ -158,8 +161,7 @@ func (b *BlockGen) GetBalance(addr common.Address) *big.Int {
|
||||
return b.statedb.GetBalance(addr)
|
||||
}
|
||||
|
||||
// AddUncheckedTx forcefully adds a transaction to the block without any
|
||||
// validation.
|
||||
// AddUncheckedTx forcefully adds a transaction to the block without any validation.
|
||||
//
|
||||
// AddUncheckedTx will cause consensus failures when used during real
|
||||
// chain processing. This is best used in conjunction with raw block insertion.
|
||||
@ -182,6 +184,16 @@ func (b *BlockGen) BaseFee() *big.Int {
|
||||
return new(big.Int).Set(b.header.BaseFee)
|
||||
}
|
||||
|
||||
// Gas returns the amount of gas left in the current block.
|
||||
func (b *BlockGen) Gas() uint64 {
|
||||
return b.header.GasLimit - b.header.GasUsed
|
||||
}
|
||||
|
||||
// Signer returns a valid signer instance for the current block.
|
||||
func (b *BlockGen) Signer() types.Signer {
|
||||
return types.MakeSigner(b.cm.config, b.header.Number, b.header.Time)
|
||||
}
|
||||
|
||||
// AddUncheckedReceipt forcefully adds a receipts to the block without a
|
||||
// backing transaction.
|
||||
//
|
||||
@ -207,20 +219,19 @@ func (b *BlockGen) AddUncle(h *types.Header) {
|
||||
|
||||
var parent *types.Header
|
||||
for i := b.i - 1; i >= 0; i-- {
|
||||
if b.chain[i].Hash() == h.ParentHash {
|
||||
parent = b.chain[i].Header()
|
||||
if b.cm.chain[i].Hash() == h.ParentHash {
|
||||
parent = b.cm.chain[i].Header()
|
||||
break
|
||||
}
|
||||
}
|
||||
chainreader := &fakeChainReader{config: b.config}
|
||||
h.Difficulty = b.engine.CalcDifficulty(chainreader, b.header.Time, parent)
|
||||
h.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, parent)
|
||||
|
||||
// The gas limit and price should be derived from the parent
|
||||
h.GasLimit = parent.GasLimit
|
||||
if b.config.IsLondon(h.Number) {
|
||||
h.BaseFee = eip1559.CalcBaseFee(b.config, parent)
|
||||
if !b.config.IsLondon(parent.Number) {
|
||||
parentGasLimit := parent.GasLimit * b.config.ElasticityMultiplier()
|
||||
if b.cm.config.IsLondon(h.Number) {
|
||||
h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent)
|
||||
if !b.cm.config.IsLondon(parent.Number) {
|
||||
parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier()
|
||||
h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
|
||||
}
|
||||
}
|
||||
@ -242,12 +253,12 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
|
||||
return b.withdrawals[len(b.withdrawals)-1].Index + 1
|
||||
}
|
||||
for i := b.i - 1; i >= 0; i-- {
|
||||
if wd := b.chain[i].Withdrawals(); len(wd) != 0 {
|
||||
if wd := b.cm.chain[i].Withdrawals(); len(wd) != 0 {
|
||||
return wd[len(wd)-1].Index + 1
|
||||
}
|
||||
if i == 0 {
|
||||
// Correctly set the index if no parent had withdrawals.
|
||||
if wd := b.parent.Withdrawals(); len(wd) != 0 {
|
||||
if wd := b.cm.bottom.Withdrawals(); len(wd) != 0 {
|
||||
return wd[len(wd)-1].Index + 1
|
||||
}
|
||||
}
|
||||
@ -263,9 +274,9 @@ func (b *BlockGen) PrevBlock(index int) *types.Block {
|
||||
panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i))
|
||||
}
|
||||
if index == -1 {
|
||||
return b.parent
|
||||
return b.cm.bottom
|
||||
}
|
||||
return b.chain[index]
|
||||
return b.cm.chain[index]
|
||||
}
|
||||
|
||||
// OffsetTime modifies the time instance of a block, implicitly changing its
|
||||
@ -273,11 +284,10 @@ func (b *BlockGen) PrevBlock(index int) *types.Block {
|
||||
// tied to chain length directly.
|
||||
func (b *BlockGen) OffsetTime(seconds int64) {
|
||||
b.header.Time += uint64(seconds)
|
||||
if b.header.Time <= b.parent.Header().Time {
|
||||
if b.header.Time <= b.cm.bottom.Header().Time {
|
||||
panic("block time out of range")
|
||||
}
|
||||
chainreader := &fakeChainReader{config: b.config}
|
||||
b.header.Difficulty = b.engine.CalcDifficulty(chainreader, b.header.Time, b.parent.Header())
|
||||
b.header.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, b.parent.Header())
|
||||
}
|
||||
|
||||
// GenerateChain creates a chain of n blocks. The first block's
|
||||
@ -296,11 +306,14 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
if config == nil {
|
||||
config = params.TestChainConfig
|
||||
}
|
||||
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
|
||||
chainreader := &fakeChainReader{config: config}
|
||||
if engine == nil {
|
||||
panic("nil consensus engine")
|
||||
}
|
||||
cm := newChainMaker(parent, config, engine)
|
||||
|
||||
genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
||||
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
|
||||
b.header = makeHeader(chainreader, parent, statedb, b.engine)
|
||||
b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
|
||||
b.header = cm.makeHeader(parent, statedb, b.engine)
|
||||
|
||||
// Set the difficulty for clique block. The chain maker doesn't have access
|
||||
// to a chain, so the difficulty will be left unset (nil). Set it here to the
|
||||
@ -330,8 +343,8 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
if gen != nil {
|
||||
gen(i, b)
|
||||
}
|
||||
if b.engine != nil {
|
||||
block, err := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals)
|
||||
|
||||
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -346,8 +359,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
}
|
||||
return block, b.receipts
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Forcibly use hash-based state scheme for retaining all nodes in disk.
|
||||
triedb := trie.NewDatabase(db, trie.HashDefaults)
|
||||
defer triedb.Close()
|
||||
@ -357,12 +369,36 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
block, receipt := genblock(i, parent, triedb, statedb)
|
||||
blocks[i] = block
|
||||
receipts[i] = receipt
|
||||
block, receipts := genblock(i, parent, triedb, statedb)
|
||||
|
||||
// Post-process the receipts.
|
||||
// Here we assign the final block hash and other info into the receipt.
|
||||
// In order for DeriveFields to work, the transaction and receipt lists need to be
|
||||
// of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be
|
||||
// extra ones, so we just trim the lists here.
|
||||
receiptsCount := len(receipts)
|
||||
txs := block.Transactions()
|
||||
if len(receipts) > len(txs) {
|
||||
receipts = receipts[:len(txs)]
|
||||
} else if len(receipts) < len(txs) {
|
||||
txs = txs[:len(receipts)]
|
||||
}
|
||||
var blobGasPrice *big.Int
|
||||
if block.ExcessBlobGas() != nil {
|
||||
blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas())
|
||||
}
|
||||
if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Re-expand to ensure all receipts are returned.
|
||||
receipts = receipts[:receiptsCount]
|
||||
|
||||
// Advance the chain.
|
||||
cm.add(block, receipts)
|
||||
parent = block
|
||||
}
|
||||
return blocks, receipts
|
||||
return cm.chain, cm.receipts
|
||||
}
|
||||
|
||||
// GenerateChainWithGenesis is a wrapper of GenerateChain which will initialize
|
||||
@ -380,35 +416,26 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int,
|
||||
return db, blocks, receipts
|
||||
}
|
||||
|
||||
func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
|
||||
var time uint64
|
||||
if parent.Time() == 0 {
|
||||
time = 10
|
||||
} else {
|
||||
time = parent.Time() + 10 // block time is fixed at 10 seconds
|
||||
}
|
||||
func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
|
||||
time := parent.Time() + 10 // block time is fixed at 10 seconds
|
||||
header := &types.Header{
|
||||
Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
|
||||
Root: state.IntermediateRoot(cm.config.IsEIP158(parent.Number())),
|
||||
ParentHash: parent.Hash(),
|
||||
Coinbase: parent.Coinbase(),
|
||||
Difficulty: engine.CalcDifficulty(chain, time, &types.Header{
|
||||
Number: parent.Number(),
|
||||
Time: time - 10,
|
||||
Difficulty: parent.Difficulty(),
|
||||
UncleHash: parent.UncleHash(),
|
||||
}),
|
||||
Difficulty: engine.CalcDifficulty(cm, time, parent.Header()),
|
||||
GasLimit: parent.GasLimit(),
|
||||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||
Time: time,
|
||||
}
|
||||
if chain.Config().IsLondon(header.Number) {
|
||||
header.BaseFee = eip1559.CalcBaseFee(chain.Config(), parent.Header())
|
||||
if !chain.Config().IsLondon(parent.Number()) {
|
||||
parentGasLimit := parent.GasLimit() * chain.Config().ElasticityMultiplier()
|
||||
|
||||
if cm.config.IsLondon(header.Number) {
|
||||
header.BaseFee = eip1559.CalcBaseFee(cm.config, parent.Header())
|
||||
if !cm.config.IsLondon(parent.Number()) {
|
||||
parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier()
|
||||
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
|
||||
}
|
||||
}
|
||||
if chain.Config().IsCancun(header.Number, header.Time) {
|
||||
if cm.config.IsCancun(header.Number, header.Time) {
|
||||
var (
|
||||
parentExcessBlobGas uint64
|
||||
parentBlobGasUsed uint64
|
||||
@ -461,18 +488,86 @@ func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine,
|
||||
return db, blocks
|
||||
}
|
||||
|
||||
type fakeChainReader struct {
|
||||
// chainMaker contains the state of chain generation.
|
||||
type chainMaker struct {
|
||||
bottom *types.Block
|
||||
engine consensus.Engine
|
||||
config *params.ChainConfig
|
||||
chain []*types.Block
|
||||
chainByHash map[common.Hash]*types.Block
|
||||
receipts []types.Receipts
|
||||
}
|
||||
|
||||
// Config returns the chain configuration.
|
||||
func (cr *fakeChainReader) Config() *params.ChainConfig {
|
||||
return cr.config
|
||||
func newChainMaker(bottom *types.Block, config *params.ChainConfig, engine consensus.Engine) *chainMaker {
|
||||
return &chainMaker{
|
||||
bottom: bottom,
|
||||
config: config,
|
||||
engine: engine,
|
||||
chainByHash: make(map[common.Hash]*types.Block),
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *fakeChainReader) CurrentHeader() *types.Header { return nil }
|
||||
func (cr *fakeChainReader) GetHeaderByNumber(number uint64) *types.Header { return nil }
|
||||
func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header { return nil }
|
||||
func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil }
|
||||
func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil }
|
||||
func (cr *fakeChainReader) GetTd(hash common.Hash, number uint64) *big.Int { return nil }
|
||||
func (cm *chainMaker) add(b *types.Block, r []*types.Receipt) {
|
||||
cm.chain = append(cm.chain, b)
|
||||
cm.chainByHash[b.Hash()] = b
|
||||
cm.receipts = append(cm.receipts, r)
|
||||
}
|
||||
|
||||
func (cm *chainMaker) blockByNumber(number uint64) *types.Block {
|
||||
if number == cm.bottom.NumberU64() {
|
||||
return cm.bottom
|
||||
}
|
||||
cur := cm.CurrentHeader().Number.Uint64()
|
||||
lowest := cm.bottom.NumberU64() + 1
|
||||
if number < lowest || number > cur {
|
||||
return nil
|
||||
}
|
||||
return cm.chain[number-lowest]
|
||||
}
|
||||
|
||||
// ChainReader/ChainContext implementation
|
||||
|
||||
// Config returns the chain configuration (for consensus.ChainReader).
|
||||
func (cm *chainMaker) Config() *params.ChainConfig {
|
||||
return cm.config
|
||||
}
|
||||
|
||||
// Engine returns the consensus engine (for ChainContext).
|
||||
func (cm *chainMaker) Engine() consensus.Engine {
|
||||
return cm.engine
|
||||
}
|
||||
|
||||
func (cm *chainMaker) CurrentHeader() *types.Header {
|
||||
if len(cm.chain) == 0 {
|
||||
return cm.bottom.Header()
|
||||
}
|
||||
return cm.chain[len(cm.chain)-1].Header()
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetHeaderByNumber(number uint64) *types.Header {
|
||||
b := cm.blockByNumber(number)
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
return b.Header()
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetHeaderByHash(hash common.Hash) *types.Header {
|
||||
b := cm.chainByHash[hash]
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
return b.Header()
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header {
|
||||
return cm.GetHeaderByNumber(number)
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||
return cm.blockByNumber(number)
|
||||
}
|
||||
|
||||
func (cm *chainMaker) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||
return nil // not supported
|
||||
}
|
||||
|
@ -19,8 +19,10 @@ package core
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
@ -53,7 +55,6 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||
GasLimit: 5_000_000,
|
||||
}
|
||||
gendb = rawdb.NewMemoryDatabase()
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
)
|
||||
|
||||
@ -82,10 +83,20 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||
}
|
||||
genesis := gspec.MustCommit(gendb, trie.NewDatabase(gendb, trie.HashDefaults))
|
||||
|
||||
chain, _ := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
|
||||
genchain, genreceipts := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) {
|
||||
gen.SetParentBeaconRoot(common.Hash{byte(i + 1)})
|
||||
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(address), address, big.NewInt(1000), params.TxGas, new(big.Int).Add(gen.BaseFee(), common.Big1), nil), signer, key)
|
||||
|
||||
// Add value transfer tx.
|
||||
tx := types.MustSignNewTx(key, gen.Signer(), &types.LegacyTx{
|
||||
Nonce: gen.TxNonce(address),
|
||||
To: &address,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: new(big.Int).Add(gen.BaseFee(), common.Big1),
|
||||
})
|
||||
gen.AddTx(tx)
|
||||
|
||||
// Add withdrawals.
|
||||
if i == 1 {
|
||||
gen.AddWithdrawal(&types.Withdrawal{
|
||||
Validator: 42,
|
||||
@ -116,20 +127,39 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||
blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil, nil)
|
||||
defer blockchain.Stop()
|
||||
|
||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
||||
return
|
||||
if i, err := blockchain.InsertChain(genchain); err != nil {
|
||||
t.Fatalf("insert error (block %d): %v\n", genchain[i].NumberU64(), err)
|
||||
}
|
||||
|
||||
// enforce that withdrawal indexes are monotonically increasing from 0
|
||||
var (
|
||||
withdrawalIndex uint64
|
||||
head = blockchain.CurrentBlock().Number.Uint64()
|
||||
)
|
||||
for i := 0; i < int(head); i++ {
|
||||
block := blockchain.GetBlockByNumber(uint64(i))
|
||||
for i := range genchain {
|
||||
blocknum := genchain[i].NumberU64()
|
||||
block := blockchain.GetBlockByNumber(blocknum)
|
||||
if block == nil {
|
||||
t.Fatalf("block %d not found", i)
|
||||
t.Fatalf("block %d not found", blocknum)
|
||||
}
|
||||
|
||||
// Verify receipts.
|
||||
genBlockReceipts := genreceipts[i]
|
||||
for _, r := range genBlockReceipts {
|
||||
if r.BlockNumber.Cmp(block.Number()) != 0 {
|
||||
t.Errorf("receipt has wrong block number %d, want %d", r.BlockNumber, block.Number())
|
||||
}
|
||||
if r.BlockHash != block.Hash() {
|
||||
t.Errorf("receipt has wrong block hash %v, want %v", r.BlockHash, block.Hash())
|
||||
}
|
||||
|
||||
// patch up empty logs list to make DeepEqual below work
|
||||
if r.Logs == nil {
|
||||
r.Logs = []*types.Log{}
|
||||
}
|
||||
}
|
||||
blockchainReceipts := blockchain.GetReceiptsByHash(block.Hash())
|
||||
if !reflect.DeepEqual(genBlockReceipts, blockchainReceipts) {
|
||||
t.Fatalf("receipts mismatch\ngenerated: %s\nblockchain: %s", spew.Sdump(genBlockReceipts), spew.Sdump(blockchainReceipts))
|
||||
}
|
||||
|
||||
// Verify withdrawals.
|
||||
@ -144,7 +174,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify parent beacon root.
|
||||
want := common.Hash{byte(i)}
|
||||
want := common.Hash{byte(blocknum)}
|
||||
if got := block.BeaconRoot(); *got != want {
|
||||
t.Fatalf("block %d, wrong parent beacon root: got %s, want %s", i, got, want)
|
||||
}
|
||||
|
@ -165,7 +165,8 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
|
||||
}
|
||||
// Create a new context to be used in the EVM environment
|
||||
blockContext := NewEVMBlockContext(header, bc, author)
|
||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.BlobHashes()}, statedb, config, cfg)
|
||||
txContext := NewEVMTxContext(msg)
|
||||
vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
|
||||
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,8 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block {
|
||||
difficulty := big.NewInt(0)
|
||||
if !config.TerminalTotalDifficultyPassed {
|
||||
difficulty = engine.CalcDifficulty(&fakeChainReader{config}, parent.Time()+10, &types.Header{
|
||||
fakeChainReader := newChainMaker(nil, config, engine)
|
||||
difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{
|
||||
Number: parent.Number(),
|
||||
Time: parent.Time(),
|
||||
Difficulty: parent.Difficulty(),
|
||||
|
@ -287,53 +287,71 @@ func TestFilters(t *testing.T) {
|
||||
{
|
||||
f: sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}),
|
||||
want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
|
||||
want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
|
||||
want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
|
||||
err: "safe header not found",
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
|
||||
err: "safe header not found",
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil),
|
||||
err: "safe header not found",
|
||||
}, {
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`,
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xc7245899e5817f16fa99cf5ad2d9c1e4b98443a565a673ec9c764640443ef037","logIndex":"0x0","removed":false}]`,
|
||||
}, {
|
||||
want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`,
|
||||
},
|
||||
{
|
||||
f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
|
||||
err: "invalid block range",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user