Reduce amount of changes to Geth Live Tracer to keep Firehose backward compatibility

We removed the `precompile` check on `OnNewAccount` and moved it to the Firehose tracer directly. This way, we can remove our custom logic that toggle the check at the tracing code level and we can instead move the logic of backward compatibility back `FirehoseTracer`.

Refactored a bit also how precompiles are check. We moved the precompiles checker up to the block level now that `chainConfig` is available on `OnBlockStart` meaning we can extract the list of active precompiles. However, to make it work, we had to modify `OnGenesisBlock` to also receive `chainConfig` parameter, I've ask to add it to the geth codebase directly.
This commit is contained in:
Matthieu Vachon 2024-02-05 12:01:21 -05:00
parent 8767058368
commit a46903cf0c
19 changed files with 95 additions and 88 deletions

View file

@ -318,15 +318,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
reward.Mul(reward, blockReward)
reward.Div(reward, big.NewInt(8))
statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward), false, state.BalanceIncreaseRewardMineUncle)
statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward), state.BalanceIncreaseRewardMineUncle)
}
statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward), false, state.BalanceIncreaseRewardMineBlock)
statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward), state.BalanceIncreaseRewardMineBlock)
}
// Apply withdrawals
for _, w := range pre.Env.Withdrawals {
// Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), false, state.BalanceIncreaseWithdrawal)
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), state.BalanceIncreaseWithdrawal)
}
// Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))

View file

@ -358,7 +358,7 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// Convert amount from gwei to wei.
amount := new(uint256.Int).SetUint64(w.Amount)
amount = amount.Mul(amount, uint256.NewInt(params.GWei))
stateDB.AddBalance(w.Address, amount, false, state.BalanceIncreaseWithdrawal)
stateDB.AddBalance(w.Address, amount, state.BalanceIncreaseWithdrawal)
}
// No block reward which is issued by consensus layer instead.
}

View file

@ -589,10 +589,10 @@ func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, heade
r.Sub(r, hNum)
r.Mul(r, blockReward)
r.Div(r, u256_8)
stateDB.AddBalance(uncle.Coinbase, r, false, state.BalanceIncreaseRewardMineUncle)
stateDB.AddBalance(uncle.Coinbase, r, state.BalanceIncreaseRewardMineUncle)
r.Div(blockReward, u256_32)
reward.Add(reward, r)
}
stateDB.AddBalance(header.Coinbase, reward, false, state.BalanceIncreaseRewardMineBlock)
stateDB.AddBalance(header.Coinbase, reward, state.BalanceIncreaseRewardMineBlock)
}

View file

@ -81,7 +81,7 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), false, state.BalanceIncreaseDaoContract)
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), state.BalanceIncreaseDaoContract)
statedb.SetBalance(addr, new(uint256.Int), state.BalanceDecreaseDaoAccount)
}
}

View file

@ -194,7 +194,7 @@ type BlockchainLogger interface {
// `td` is the total difficulty prior to `block`.
OnBlockStart(block *types.Block, td *big.Int, finalized *types.Header, safe *types.Header, chainConfig *params.ChainConfig)
OnBlockEnd(err error)
OnGenesisBlock(genesis *types.Block, alloc GenesisAlloc)
OnGenesisBlock(genesis *types.Block, alloc GenesisAlloc, chainConfig *params.ChainConfig)
OnBeaconBlockRootStart(root common.Hash)
OnBeaconBlockRootEnd()
}
@ -462,7 +462,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
return nil, fmt.Errorf("live blockchain tracer requires genesis alloc to be set")
}
bc.logger.OnGenesisBlock(bc.genesisBlock, alloc)
bc.logger.OnGenesisBlock(bc.genesisBlock, alloc, bc.chainConfig)
}
}

View file

@ -138,5 +138,5 @@ func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
db.SubBalance(sender, amount, state.BalanceChangeTransfer)
db.AddBalance(recipient, amount, false, state.BalanceChangeTransfer)
db.AddBalance(recipient, amount, state.BalanceChangeTransfer)
}

View file

@ -143,7 +143,7 @@ func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
}
for addr, account := range *ga {
if account.Balance != nil {
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), false, state.BalanceIncreaseGenesisBalance)
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), state.BalanceIncreaseGenesisBalance)
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
@ -166,7 +166,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
if account.Balance != nil {
// This is not actually logged via tracer because OnGenesisBlock
// already captures the allocations.
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), false, state.BalanceIncreaseGenesisBalance)
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), state.BalanceIncreaseGenesisBalance)
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)

View file

@ -405,8 +405,8 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
*/
// AddBalance adds amount to the account associated with addr.
func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, checkPrecompile bool, reason BalanceChangeReason) {
stateObject := s.getOrNewStateObjectWithCheckPrecompiles(addr, checkPrecompile)
func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason BalanceChangeReason) {
stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
stateObject.AddBalance(amount, reason)
}
@ -655,32 +655,20 @@ func (s *StateDB) setStateObject(object *stateObject) {
// getOrNewStateObject retrieves a state object or create a new state object if nil.
func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
return s.getOrNewStateObjectWithCheckPrecompiles(addr, false)
}
func (s *StateDB) getOrNewStateObjectWithCheckPrecompiles(addr common.Address, checkPrecompile bool) *stateObject {
stateObject := s.getStateObject(addr)
if stateObject == nil {
stateObject, _ = s.createObject(addr, checkPrecompile)
stateObject, _ = s.createObject(addr)
}
return stateObject
}
// createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value.
func (s *StateDB) createObject(addr common.Address, checkPrecompile bool) (newobj, prev *stateObject) {
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
newobj = newObject(s, addr, nil)
if s.logger != nil {
if checkPrecompile {
// Precompiled contracts are touched during a call.
// Make sure we avoid emitting a new account event for them.
if _, ok := s.precompiles[addr]; !ok {
s.logger.OnNewAccount(addr, prev != nil)
}
} else {
s.logger.OnNewAccount(addr, prev != nil)
}
s.logger.OnNewAccount(addr, prev != nil)
}
if prev == nil {
s.journal.append(createObjectChange{account: &addr})
@ -731,7 +719,7 @@ func (s *StateDB) createObject(addr common.Address, checkPrecompile bool) (newob
//
// Carrying over the balance ensures that Ether doesn't disappear.
func (s *StateDB) CreateAccount(addr common.Address) {
newObj, prev := s.createObject(addr, false)
newObj, prev := s.createObject(addr)
if prev != nil {
newObj.setBalance(prev.data.Balance)
}

View file

@ -55,7 +55,7 @@ func TestUpdateLeaks(t *testing.T) {
// Update it with some accounts
for i := byte(0); i < 255; i++ {
addr := common.BytesToAddress([]byte{i})
state.AddBalance(addr, uint256.NewInt(uint64(11*i)), false, BalanceChangeUnspecified)
state.AddBalance(addr, uint256.NewInt(uint64(11*i)), BalanceChangeUnspecified)
state.SetNonce(addr, uint64(42*i))
if i%2 == 0 {
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
@ -272,7 +272,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
{
name: "AddBalance",
fn: func(a testAction, s *StateDB) {
s.AddBalance(addr, uint256.NewInt(uint64(a.args[0])), false, BalanceChangeUnspecified)
s.AddBalance(addr, uint256.NewInt(uint64(a.args[0])), BalanceChangeUnspecified)
},
args: make([]int64, 1),
},
@ -535,7 +535,7 @@ func TestTouchDelete(t *testing.T) {
s.state, _ = New(root, s.state.db, s.state.snaps)
snapshot := s.state.Snapshot()
s.state.AddBalance(common.Address{}, new(uint256.Int), false, BalanceChangeUnspecified)
s.state.AddBalance(common.Address{}, new(uint256.Int), BalanceChangeUnspecified)
if len(s.state.journal.dirties) != 1 {
t.Fatal("expected one dirty state object")

View file

@ -461,7 +461,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
} else {
fee := new(uint256.Int).SetUint64(st.gasUsed())
fee.Mul(fee, effectiveTipU256)
st.state.AddBalance(st.evm.Context.Coinbase, fee, false, state.BalanceIncreaseRewardTransactionFee)
st.state.AddBalance(st.evm.Context.Coinbase, fee, state.BalanceIncreaseRewardTransactionFee)
}
return &ExecutionResult{
@ -488,7 +488,7 @@ func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
// Return ETH for remaining gas, exchanged at the original rate.
remaining := uint256.NewInt(st.gasRemaining)
remaining = remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice))
st.state.AddBalance(st.msg.From, remaining, false, state.BalanceIncreaseGasReturn)
st.state.AddBalance(st.msg.From, remaining, state.BalanceIncreaseGasReturn)
if st.evm.Config.Tracer != nil && st.gasRemaining > 0 {
st.evm.Config.Tracer.OnGasChange(st.gasRemaining, 0, vm.GasChangeTxLeftOverReturned)

View file

@ -500,17 +500,17 @@ func TestOpenDrops(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3)
statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2)
statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), uint256.NewInt(10000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), uint256.NewInt(1000000), state.BalanceChangeUnspecified)
statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), uint256.NewInt(10000000), state.BalanceChangeUnspecified)
statedb.Commit(0, true)
chain := &testBlockChain{
@ -625,7 +625,7 @@ func TestOpenIndex(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.Commit(0, true)
chain := &testBlockChain{
@ -725,9 +725,9 @@ func TestOpenHeap(t *testing.T) {
// Create a blob pool out of the pre-seeded data
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.Commit(0, true)
chain := &testBlockChain{
@ -805,9 +805,9 @@ func TestOpenCap(t *testing.T) {
for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} {
// Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000), state.BalanceChangeUnspecified)
statedb.Commit(0, true)
chain := &testBlockChain{
@ -1198,7 +1198,7 @@ func TestAdd(t *testing.T) {
addrs[acc] = crypto.PubkeyToAddress(keys[acc].PublicKey)
// Seed the state database with this acocunt
statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance), state.BalanceChangeUnspecified)
statedb.SetNonce(addrs[acc], seed.nonce)
// Sign the seed transactions and store them in the data store

View file

@ -50,7 +50,7 @@ func fillPool(t testing.TB, pool *LegacyPool) {
nonExecutableTxs := types.Transactions{}
for i := 0; i < 384; i++ {
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(10000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(10000000000), state.BalanceChangeUnspecified)
// Add executable ones
for j := 0; j < int(pool.config.AccountSlots); j++ {
executableTxs = append(executableTxs, pricedTransaction(uint64(j), 100000, big.NewInt(300), key))
@ -92,7 +92,7 @@ func TestTransactionFutureAttack(t *testing.T) {
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), state.BalanceChangeUnspecified)
futureTxs := types.Transactions{}
for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ {
futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 100000, big.NewInt(500), key))
@ -129,7 +129,7 @@ func TestTransactionFuture1559(t *testing.T) {
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), state.BalanceChangeUnspecified)
futureTxs := types.Transactions{}
for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ {
futureTxs = append(futureTxs, dynamicFeeTx(1000+uint64(j), 100000, big.NewInt(200), big.NewInt(101), key))
@ -183,7 +183,7 @@ func TestTransactionZAttack(t *testing.T) {
for j := 0; j < int(pool.config.GlobalQueue); j++ {
futureTxs := types.Transactions{}
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), state.BalanceChangeUnspecified)
futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 21000, big.NewInt(500), key))
pool.addRemotesSync(futureTxs)
}
@ -191,7 +191,7 @@ func TestTransactionZAttack(t *testing.T) {
overDraftTxs := types.Transactions{}
{
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), state.BalanceChangeUnspecified)
for j := 0; j < int(pool.config.GlobalSlots); j++ {
overDraftTxs = append(overDraftTxs, pricedValuedTransaction(uint64(j), 600000000000, 21000, big.NewInt(500), key))
}
@ -228,7 +228,7 @@ func BenchmarkFutureAttack(b *testing.B) {
fillPool(b, pool)
key, _ := crypto.GenerateKey()
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000), state.BalanceChangeUnspecified)
futureTxs := types.Transactions{}
for n := 0; n < b.N; n++ {

View file

@ -310,7 +310,7 @@ func TestStateChangeDuringReset(t *testing.T) {
func testAddBalance(pool *LegacyPool, addr common.Address, amount *big.Int) {
pool.mu.Lock()
pool.currentState.AddBalance(addr, uint256.MustFromBig(amount), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(addr, uint256.MustFromBig(amount), state.BalanceChangeUnspecified)
pool.mu.Unlock()
}
@ -471,7 +471,7 @@ func TestChainFork(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
statedb.AddBalance(addr, uint256.NewInt(100000000000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr, uint256.NewInt(100000000000000), state.BalanceChangeUnspecified)
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
<-pool.requestReset(nil, nil)
@ -500,7 +500,7 @@ func TestDoubleNonce(t *testing.T) {
addr := crypto.PubkeyToAddress(key.PublicKey)
resetState := func() {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
statedb.AddBalance(addr, uint256.NewInt(100000000000000), false, state.BalanceChangeUnspecified)
statedb.AddBalance(addr, uint256.NewInt(100000000000000), state.BalanceChangeUnspecified)
pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed))
<-pool.requestReset(nil, nil)
@ -2663,7 +2663,7 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) {
for i := 0; i < b.N; i++ {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
pool.currentState.AddBalance(account, uint256.NewInt(1000000), false, state.BalanceChangeUnspecified)
pool.currentState.AddBalance(account, uint256.NewInt(1000000), state.BalanceChangeUnspecified)
tx := transaction(uint64(0), 100000, key)
batches[i] = tx
}

View file

@ -374,7 +374,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
// but is the correct thing to do and matters on other networks, in tests, and potential
// future scenarios
evm.StateDB.AddBalance(addr, new(uint256.Int), true, state.BalanceChangeTouchAccount)
evm.StateDB.AddBalance(addr, new(uint256.Int), state.BalanceChangeTouchAccount)
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)

View file

@ -835,7 +835,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
}
beneficiary := scope.Stack.pop()
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, false, state.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, state.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
@ -851,7 +851,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
beneficiary := scope.Stack.pop()
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, state.BalanceDecreaseSelfdestruct)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, false, state.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, state.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil {
tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())

View file

@ -31,7 +31,7 @@ type StateDB interface {
CreateAccount(common.Address)
SubBalance(common.Address, *uint256.Int, state.BalanceChangeReason)
AddBalance(common.Address, *uint256.Int, bool, state.BalanceChangeReason)
AddBalance(common.Address, *uint256.Int, state.BalanceChangeReason)
GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64

View file

@ -64,13 +64,14 @@ type Firehose struct {
blockBaseFee *big.Int
blockOrdinal *Ordinal
blockFinality *FinalityStatus
blockRules params.Rules
// Transaction state
evm *vm.EVM
transaction *pbeth.TransactionTrace
transactionLogIndex uint32
inSystemCall bool
isPrecompiledAddr func(addr common.Address) bool
evm *vm.EVM
transaction *pbeth.TransactionTrace
transactionLogIndex uint32
inSystemCall bool
blockIsPrecompiledAddr func(addr common.Address) bool
// Call state
callStack *CallStack
@ -106,6 +107,8 @@ func (f *Firehose) resetBlock() {
f.blockBaseFee = nil
f.blockOrdinal.Reset()
f.blockFinality.Reset()
f.blockIsPrecompiledAddr = nil
f.blockRules = params.Rules{}
}
// resetTransaction resets the transaction state and the call state in one shot
@ -114,7 +117,6 @@ func (f *Firehose) resetTransaction() {
f.evm = nil
f.transactionLogIndex = 0
f.inSystemCall = false
f.isPrecompiledAddr = nil
f.callStack.Reset()
f.latestCallStartSuicided = false
@ -124,7 +126,8 @@ func (f *Firehose) resetTransaction() {
func (f *Firehose) OnBlockStart(b *types.Block, td *big.Int, finalized *types.Header, safe *types.Header, chainConfig *params.ChainConfig) {
firehoseDebug("block start number=%d hash=%s", b.NumberU64(), b.Hash())
f.ensureNotInBlock()
f.blockRules = chainConfig.Rules(b.Number(), chainConfig.TerminalTotalDifficultyPassed, b.Time())
f.blockIsPrecompiledAddr = getActivePrecompilesChecker(f.blockRules)
f.block = &pbeth.Block{
Hash: b.Hash().Bytes(),
@ -147,6 +150,20 @@ func (f *Firehose) OnBlockStart(b *types.Block, td *big.Int, finalized *types.He
f.blockFinality.populateFromChain(finalized)
}
func getActivePrecompilesChecker(rules params.Rules) func(addr common.Address) bool {
activePrecompiles := vm.ActivePrecompiles(rules)
activePrecompilesMap := make(map[common.Address]bool, len(activePrecompiles))
for _, addr := range activePrecompiles {
activePrecompilesMap[addr] = true
}
return func(addr common.Address) bool {
_, found := activePrecompilesMap[addr]
return found
}
}
func (f *Firehose) OnBlockEnd(err error) {
firehoseDebug("block ending err=%s", errorView(err))
@ -194,17 +211,13 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction, from commo
to = *tx.To()
}
isBeforeHomestead := !evm.ChainConfig().IsHomestead(big.NewInt(int64(f.block.Number)))
f.captureTxStart(tx, tx.Hash(), from, to, evm.IsPrecompileAddr, isBeforeHomestead)
f.captureTxStart(tx, tx.Hash(), from, to)
}
// captureTxStart is used internally a two places, in the normal "tracer" and in the "OnGenesisBlock",
// we manually pass some override to the `tx` because genesis block has a different way of creating
// the transaction that wraps the genesis block.
func (f *Firehose) captureTxStart(tx *types.Transaction, hash common.Hash, from, to common.Address, isPrecompiledAddr func(common.Address) bool, isBeforeHomestead bool) {
f.isPrecompiledAddr = isPrecompiledAddr
func (f *Firehose) captureTxStart(tx *types.Transaction, hash common.Hash, from, to common.Address) {
v, r, s := tx.RawSignatureValues()
var blobGas *uint64
@ -492,8 +505,7 @@ func (f *Firehose) callStart(source string, callType pbeth.CallType, from common
GasLimit: gas,
}
precompile := f.isPrecompiledAddr(common.BytesToAddress(call.Address))
call.ExecutedCode = getExecutedCode(f.evm, precompile, call)
call.ExecutedCode = f.getExecutedCode(f.evm, call)
// Known Firehose issue: The BeginOrdinal of the genesis block root call is never actually
// incremented and it's always 0.
@ -521,10 +533,12 @@ func (f *Firehose) callStart(source string, callType pbeth.CallType, from common
f.callStack.Push(call)
}
func getExecutedCode(evm *vm.EVM, precompile bool, call *pbeth.Call) bool {
func (f *Firehose) getExecutedCode(evm *vm.EVM, call *pbeth.Call) bool {
precompile := f.blockIsPrecompiledAddr(common.BytesToAddress(call.Address))
if evm != nil && call.CallType == pbeth.CallType_CALL {
if !evm.StateDB.Exist(common.BytesToAddress(call.Address)) &&
!precompile && evm.ChainConfig().Rules(evm.Context.BlockNumber, evm.Context.Random != nil, evm.Context.Time).IsEIP158 &&
!precompile && f.blockRules.IsEIP158 &&
(call.Value == nil || call.Value.Native().Sign() == 0) {
firehoseDebug("executed code IsSpuriousDragon callTyp=%s inputLength=%d", call.CallType.String(), len(call.Input) > 0)
return call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0
@ -660,9 +674,9 @@ func (f *Firehose) CaptureKeccakPreimage(hash common.Hash, data []byte) {
activeCall.KeccakPreimages[hex.EncodeToString(hash.Bytes())] = encodedData
}
func (f *Firehose) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc) {
f.OnBlockStart(b, big.NewInt(0), nil, nil, nil)
f.captureTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress, func(common.Address) bool { return false }, false)
func (f *Firehose) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc, chainConfig *params.ChainConfig) {
f.OnBlockStart(b, big.NewInt(0), nil, nil, chainConfig)
f.captureTxStart(types.NewTx(&types.LegacyTx{}), emptyCommonHash, emptyCommonAddress, emptyCommonAddress)
f.CaptureStart(emptyCommonAddress, emptyCommonAddress, false, nil, 0, nil)
for _, addr := range sortedKeys(alloc) {
@ -860,6 +874,11 @@ func (f *Firehose) OnNewAccount(a common.Address, previousDataExists bool) {
// exists in the past. For now, do nothing and keep the legacy behavior.
_ = previousDataExists
if call := f.callStack.Peek(); call != nil && call.CallType == pbeth.CallType_STATIC && f.blockIsPrecompiledAddr(common.Address(call.Address)) {
// Old Firehose ignore those, we do the same
return
}
accountCreation := &pbeth.AccountCreation{
Account: a.Bytes(),
Ordinal: f.blockOrdinal.Next(),

View file

@ -96,7 +96,7 @@ func (p *Printer) OnBlockEnd(err error) {
fmt.Printf("OnBlockEnd: err=%v\n", err)
}
func (p *Printer) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc) {
func (p *Printer) OnGenesisBlock(b *types.Block, alloc core.GenesisAlloc, chainConfig *params.ChainConfig) {
fmt.Printf("OnGenesisBlock: b=%v, allocLength=%d\n", b.NumberU64(), len(alloc))
}

View file

@ -316,7 +316,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
// - the coinbase self-destructed, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
statedb.AddBalance(block.Coinbase(), new(uint256.Int), false, state.BalanceChangeUnspecified)
statedb.AddBalance(block.Coinbase(), new(uint256.Int), state.BalanceChangeUnspecified)
// Commit state mutations into database.
root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))