mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-09 22:44:27 +00:00
This commit is contained in:
parent
d9867ea87d
commit
ebbbdf2bff
30 changed files with 674 additions and 179 deletions
|
|
@ -43,7 +43,6 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
|
|
@ -738,7 +737,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||||
|
|
||||||
// Set infinite balance to the fake caller account.
|
// Set infinite balance to the fake caller account.
|
||||||
from := stateDB.GetOrNewStateObject(call.From)
|
from := stateDB.GetOrNewStateObject(call.From)
|
||||||
from.SetBalance(math.MaxBig256, tracing.BalanceChangeUnspecified)
|
from.SetBalance(math.MaxBig256)
|
||||||
|
|
||||||
// Execute the call.
|
// Execute the call.
|
||||||
msg := &core.Message{
|
msg := &core.Message{
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/event"
|
"github.com/XinFinOrg/XDPoSChain/event"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
|
|
@ -276,7 +277,7 @@ func (x *XDPoS) Prepare(chain consensus.ChainReader, header *types.Header) error
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||||
// rewards given, and returns the final block.
|
// rewards given, and returns the final block.
|
||||||
func (x *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (x *XDPoS) Finalize(chain consensus.ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
switch x.config.BlockConsensusVersion(header.Number) {
|
switch x.config.BlockConsensusVersion(header.Number) {
|
||||||
case params.ConsensusEngineVersion2:
|
case params.ConsensusEngineVersion2:
|
||||||
return x.EngineV2.Finalize(chain, header, state, parentState, txs, uncles, receipts)
|
return x.EngineV2.Finalize(chain, header, state, parentState, txs, uncles, receipts)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc/eip1559"
|
"github.com/XinFinOrg/XDPoSChain/consensus/misc/eip1559"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
|
|
@ -53,7 +54,7 @@ type XDPoS_v1 struct {
|
||||||
signFn clique.SignerFn // Signer function to authorize hashes with
|
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||||
lock sync.RWMutex // Protects the signer fields
|
lock sync.RWMutex // Protects the signer fields
|
||||||
|
|
||||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error)
|
HookReward func(chain consensus.ChainReader, state vm.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error)
|
||||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||||
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
|
||||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||||
|
|
@ -823,7 +824,7 @@ func (x *XDPoS_v1) UpdateMasternodes(chain consensus.ChainReader, header *types.
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||||
// rewards given, and returns the final block.
|
// rewards given, and returns the final block.
|
||||||
func (x *XDPoS_v1) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (x *XDPoS_v1) Finalize(chain consensus.ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
// set block reward
|
// set block reward
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
|
@ -74,7 +75,7 @@ type XDPoS_v2 struct {
|
||||||
latestReward map[string]interface{}
|
latestReward map[string]interface{}
|
||||||
latestRewardBlocknum uint64
|
latestRewardBlocknum uint64
|
||||||
|
|
||||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error)
|
HookReward func(chain consensus.ChainReader, state vm.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error)
|
||||||
HookPenalty func(chain consensus.ChainReader, number *big.Int, parentHash common.Hash, candidates []common.Address) ([]common.Address, error)
|
HookPenalty func(chain consensus.ChainReader, number *big.Int, parentHash common.Hash, candidates []common.Address) ([]common.Address, error)
|
||||||
|
|
||||||
ForensicsProcessor *Forensics
|
ForensicsProcessor *Forensics
|
||||||
|
|
@ -410,7 +411,7 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||||
// rewards given, and returns the final block.
|
// rewards given, and returns the final block.
|
||||||
func (x *XDPoS_v2) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (x *XDPoS_v2) Finalize(chain consensus.ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
// set block reward
|
// set block reward
|
||||||
|
|
||||||
isEpochSwitch, _, err := x.IsEpochSwitch(header)
|
isEpochSwitch, _, err := x.IsEpochSwitch(header)
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
|
|
@ -584,7 +585,7 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
|
||||||
// rewards given, and returns the final block.
|
// rewards given, and returns the final block.
|
||||||
func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (c *Clique) Finalize(chain consensus.ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
// No block rewards in PoA, so the state remains as is and uncles are dropped
|
||||||
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
||||||
header.UncleHash = types.CalcUncleHash(nil)
|
header.UncleHash = types.CalcUncleHash(nil)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -83,7 +84,7 @@ type Engine interface {
|
||||||
// and assembles the final block.
|
// and assembles the final block.
|
||||||
// Note: The block header and state database might be updated to reflect any
|
// Note: The block header and state database might be updated to reflect any
|
||||||
// consensus rules that happen at finalization (e.g. block rewards).
|
// consensus rules that happen at finalization (e.g. block rewards).
|
||||||
Finalize(chain ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction,
|
Finalize(chain ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction,
|
||||||
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)
|
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)
|
||||||
|
|
||||||
// Seal generates a new block for the given input block with the local miner's
|
// Seal generates a new block for the given input block with the local miner's
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
|
|
@ -433,7 +434,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header)
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
|
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
|
||||||
// setting the final state and assembling the block.
|
// setting the final state and assembling the block.
|
||||||
func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state vm.StateDB, parentState *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
|
||||||
// Accumulate any block and uncle rewards and commit the final state root
|
// Accumulate any block and uncle rewards and commit the final state root
|
||||||
accumulateRewards(chain.Config(), state, header, uncles)
|
accumulateRewards(chain.Config(), state, header, uncles)
|
||||||
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
||||||
|
|
@ -451,7 +452,7 @@ var (
|
||||||
// AccumulateRewards credits the coinbase of the given block with the mining
|
// AccumulateRewards credits the coinbase of the given block with the mining
|
||||||
// reward. The total reward consists of the static block reward and rewards for
|
// reward. The total reward consists of the static block reward and rewards for
|
||||||
// included uncles. The coinbase of each uncle block is also rewarded.
|
// included uncles. The coinbase of each uncle block is also rewarded.
|
||||||
func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) {
|
func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) {
|
||||||
// Select the correct block reward based on chain progression
|
// Select the correct block reward based on chain progression
|
||||||
blockReward := FrontierBlockReward
|
blockReward := FrontierBlockReward
|
||||||
if config.IsByzantium(header.Number) {
|
if config.IsByzantium(header.Number) {
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
|
||||||
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
||||||
// rules, transferring all balances of a set of DAO accounts to a single refund
|
// rules, transferring all balances of a set of DAO accounts to a single refund
|
||||||
// contract.
|
// contract.
|
||||||
func ApplyDAOHardFork(statedb *state.StateDB) {
|
func ApplyDAOHardFork(statedb vm.StateDB) {
|
||||||
// Retrieve the contract to refund balances into
|
// Retrieve the contract to refund balances into
|
||||||
if !statedb.Exist(params.DAORefundContract) {
|
if !statedb.Exist(params.DAORefundContract) {
|
||||||
statedb.CreateAccount(params.DAORefundContract)
|
statedb.CreateAccount(params.DAORefundContract)
|
||||||
|
|
@ -81,7 +81,8 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
|
||||||
|
|
||||||
// Move every DAO account and extra-balance account funds into the refund contract
|
// Move every DAO account and extra-balance account funds into the refund contract
|
||||||
for _, addr := range params.DAODrainList() {
|
for _, addr := range params.DAODrainList() {
|
||||||
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract)
|
balance := statedb.GetBalance(addr)
|
||||||
statedb.SetBalance(addr, new(big.Int), tracing.BalanceDecreaseDaoAccount)
|
statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
|
||||||
|
statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1552,7 +1552,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it.index, events, coalescedLogs, err
|
return it.index, events, coalescedLogs, err
|
||||||
}
|
}
|
||||||
statedb.SetLogger(bc.logger)
|
|
||||||
|
|
||||||
// If we have a followup block, run that against the current state to pre-cache
|
// If we have a followup block, run that against the current state to pre-cache
|
||||||
// transactions and probabilistically some of the account/storage trie nodes.
|
// transactions and probabilistically some of the account/storage trie nodes.
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanTransfer checks wether there are enough funds in the address' account to make a transfer.
|
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
|
||||||
// This does not take the necessary gas in to account to make the transfer valid.
|
// This does not take the necessary gas in to account to make the transfer valid.
|
||||||
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
|
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
|
||||||
return db.GetBalance(addr).Cmp(amount) >= 0
|
return db.GetBalance(addr).Cmp(amount) >= 0
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,21 @@ func (j *journal) length() int {
|
||||||
return len(j.entries)
|
return len(j.entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *journal) createContract(addr common.Address) {
|
||||||
|
j.append(createContractChange{account: addr})
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// Changes to the account trie.
|
// Changes to the account trie.
|
||||||
createObjectChange struct {
|
createObjectChange struct {
|
||||||
account common.Address
|
account common.Address
|
||||||
}
|
}
|
||||||
|
// createContractChange represents an account becoming a contract-account.
|
||||||
|
// This event happens prior to executing initcode. The journal-event simply
|
||||||
|
// manages the created-flag, in order to allow same-tx destruction.
|
||||||
|
createContractChange struct {
|
||||||
|
account common.Address
|
||||||
|
}
|
||||||
resetObjectChange struct {
|
resetObjectChange struct {
|
||||||
account common.Address
|
account common.Address
|
||||||
prev *stateObject
|
prev *stateObject
|
||||||
|
|
@ -156,6 +166,14 @@ func (ch createObjectChange) dirtied() *common.Address {
|
||||||
return &ch.account
|
return &ch.account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ch createContractChange) revert(s *StateDB) {
|
||||||
|
s.getStateObject(ch.account).created = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch createContractChange) dirtied() *common.Address {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ch resetObjectChange) revert(s *StateDB) {
|
func (ch resetObjectChange) revert(s *StateDB) {
|
||||||
s.setStateObject(ch.prev)
|
s.setStateObject(ch.prev)
|
||||||
if !ch.prevdestruct {
|
if !ch.prevdestruct {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||||
|
|
@ -218,11 +217,12 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetState updates a value in account storage.
|
// SetState updates a value in account storage.
|
||||||
func (s *stateObject) SetState(db Database, key, value common.Hash) {
|
func (s *stateObject) SetState(db Database, key, value common.Hash) common.Hash {
|
||||||
// If the new value is the same as old, don't set
|
// If the new value is the same as old, don't set. Otherwise, track only the
|
||||||
|
// dirty changes, supporting reverting all of it back to no change.
|
||||||
prev := s.GetState(db, key)
|
prev := s.GetState(db, key)
|
||||||
if prev == value {
|
if prev == value {
|
||||||
return
|
return prev
|
||||||
}
|
}
|
||||||
// New value is different, update and journal the change
|
// New value is different, update and journal the change
|
||||||
s.db.journal.append(storageChange{
|
s.db.journal.append(storageChange{
|
||||||
|
|
@ -230,10 +230,8 @@ func (s *stateObject) SetState(db Database, key, value common.Hash) {
|
||||||
key: key,
|
key: key,
|
||||||
prevalue: prev,
|
prevalue: prev,
|
||||||
})
|
})
|
||||||
if s.db.logger != nil && s.db.logger.OnStorageChange != nil {
|
|
||||||
s.db.logger.OnStorageChange(s.address, key, prev, value)
|
|
||||||
}
|
|
||||||
s.setState(key, value)
|
s.setState(key, value)
|
||||||
|
return prev
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stateObject) setState(key, value common.Hash) {
|
func (s *stateObject) setState(key, value common.Hash) {
|
||||||
|
|
@ -338,36 +336,28 @@ func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) {
|
||||||
|
|
||||||
// AddBalance adds amount to s's balance.
|
// AddBalance adds amount to s's balance.
|
||||||
// It is used to add funds to the destination account of a transfer.
|
// It is used to add funds to the destination account of a transfer.
|
||||||
func (s *stateObject) AddBalance(amount *big.Int, reason tracing.BalanceChangeReason) {
|
// returns the previous balance
|
||||||
|
func (s *stateObject) AddBalance(amount *big.Int) *big.Int {
|
||||||
// EIP161: We must check emptiness for the objects such that the account
|
// EIP161: We must check emptiness for the objects such that the account
|
||||||
// clearing (0,0,0 objects) can take effect.
|
// clearing (0,0,0 objects) can take effect.
|
||||||
if amount.Sign() == 0 {
|
if amount.Sign() == 0 {
|
||||||
if s.empty() {
|
if s.empty() {
|
||||||
s.touch()
|
s.touch()
|
||||||
}
|
}
|
||||||
return
|
return new(big.Int).Set(s.Balance())
|
||||||
}
|
}
|
||||||
s.SetBalance(new(big.Int).Add(s.Balance(), amount), reason)
|
return s.SetBalance(new(big.Int).Add(s.Balance(), amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubBalance removes amount from s's balance.
|
// SetBalance sets the balance for the object, and returns the previous balance.
|
||||||
// It is used to remove funds from the origin account of a transfer.
|
func (s *stateObject) SetBalance(amount *big.Int) *big.Int {
|
||||||
func (s *stateObject) SubBalance(amount *big.Int, reason tracing.BalanceChangeReason) {
|
prev := new(big.Int).Set(s.data.Balance)
|
||||||
if amount.Sign() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.SetBalance(new(big.Int).Sub(s.Balance(), amount), reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stateObject) SetBalance(amount *big.Int, reason tracing.BalanceChangeReason) {
|
|
||||||
s.db.journal.append(balanceChange{
|
s.db.journal.append(balanceChange{
|
||||||
account: s.address,
|
account: s.address,
|
||||||
prev: new(big.Int).Set(s.data.Balance),
|
prev: new(big.Int).Set(s.data.Balance),
|
||||||
})
|
})
|
||||||
if s.db.logger != nil && s.db.logger.OnBalanceChange != nil {
|
|
||||||
s.db.logger.OnBalanceChange(s.address, s.Balance(), amount, reason)
|
|
||||||
}
|
|
||||||
s.setBalance(amount)
|
s.setBalance(amount)
|
||||||
|
return prev
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stateObject) setBalance(amount *big.Int) {
|
func (s *stateObject) setBalance(amount *big.Int) {
|
||||||
|
|
@ -437,9 +427,6 @@ func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
|
||||||
account: s.address,
|
account: s.address,
|
||||||
prevCode: prevCode,
|
prevCode: prevCode,
|
||||||
})
|
})
|
||||||
if s.db.logger != nil && s.db.logger.OnCodeChange != nil {
|
|
||||||
s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), prevCode, codeHash, code)
|
|
||||||
}
|
|
||||||
s.setCode(codeHash, code)
|
s.setCode(codeHash, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -454,9 +441,6 @@ func (s *stateObject) SetNonce(nonce uint64) {
|
||||||
account: s.address,
|
account: s.address,
|
||||||
prev: s.data.Nonce,
|
prev: s.data.Nonce,
|
||||||
})
|
})
|
||||||
if s.db.logger != nil && s.db.logger.OnNonceChange != nil {
|
|
||||||
s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce)
|
|
||||||
}
|
|
||||||
s.setNonce(nonce)
|
s.setNonce(nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
|
|
@ -49,11 +48,11 @@ func TestDump(t *testing.T) {
|
||||||
|
|
||||||
// generate a few entries
|
// generate a few entries
|
||||||
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
||||||
obj1.AddBalance(big.NewInt(22), tracing.BalanceChangeUnspecified)
|
obj1.AddBalance(big.NewInt(22))
|
||||||
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
|
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
|
||||||
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
||||||
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
|
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
|
||||||
obj3.SetBalance(big.NewInt(44), tracing.BalanceChangeUnspecified)
|
obj3.SetBalance(big.NewInt(44))
|
||||||
|
|
||||||
// write some of them to the trie
|
// write some of them to the trie
|
||||||
s.state.updateStateObject(obj1)
|
s.state.updateStateObject(obj1)
|
||||||
|
|
@ -101,13 +100,13 @@ func TestIterativeDump(t *testing.T) {
|
||||||
|
|
||||||
// generate a few entries
|
// generate a few entries
|
||||||
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
obj1 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01}))
|
||||||
obj1.AddBalance(big.NewInt(22), tracing.BalanceChangeUnspecified)
|
obj1.AddBalance(big.NewInt(22))
|
||||||
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
|
obj2 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
|
||||||
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
|
||||||
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
|
obj3 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x02}))
|
||||||
obj3.SetBalance(big.NewInt(44), tracing.BalanceChangeUnspecified)
|
obj3.SetBalance(big.NewInt(44))
|
||||||
obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
|
obj4 := s.state.GetOrNewStateObject(common.BytesToAddress([]byte{0x00}))
|
||||||
obj4.AddBalance(big.NewInt(1337), tracing.BalanceChangeUnspecified)
|
obj4.AddBalance(big.NewInt(1337))
|
||||||
|
|
||||||
// write some of them to the trie
|
// write some of them to the trie
|
||||||
s.state.updateStateObject(obj1)
|
s.state.updateStateObject(obj1)
|
||||||
|
|
@ -203,7 +202,7 @@ func TestSnapshot2(t *testing.T) {
|
||||||
|
|
||||||
// db, trie are already non-empty values
|
// db, trie are already non-empty values
|
||||||
so0 := state.getStateObject(stateobjaddr0)
|
so0 := state.getStateObject(stateobjaddr0)
|
||||||
so0.SetBalance(big.NewInt(42), tracing.BalanceChangeUnspecified)
|
so0.SetBalance(big.NewInt(42))
|
||||||
so0.SetNonce(43)
|
so0.SetNonce(43)
|
||||||
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
||||||
so0.selfDestructed = false
|
so0.selfDestructed = false
|
||||||
|
|
@ -215,7 +214,7 @@ func TestSnapshot2(t *testing.T) {
|
||||||
|
|
||||||
// and one with deleted == true
|
// and one with deleted == true
|
||||||
so1 := state.getStateObject(stateobjaddr1)
|
so1 := state.getStateObject(stateobjaddr1)
|
||||||
so1.SetBalance(big.NewInt(52), tracing.BalanceChangeUnspecified)
|
so1.SetBalance(big.NewInt(52))
|
||||||
so1.SetNonce(53)
|
so1.SetNonce(53)
|
||||||
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
||||||
so1.selfDestructed = true
|
so1.selfDestructed = true
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,8 @@ type revision struct {
|
||||||
// * Contracts
|
// * Contracts
|
||||||
// * Accounts
|
// * Accounts
|
||||||
type StateDB struct {
|
type StateDB struct {
|
||||||
db Database
|
db Database
|
||||||
trie Trie
|
trie Trie
|
||||||
logger *tracing.Hooks
|
|
||||||
|
|
||||||
// originalRoot is the pre-state root, before any changes were made.
|
// originalRoot is the pre-state root, before any changes were made.
|
||||||
// It will be updated when the Commit is called.
|
// It will be updated when the Commit is called.
|
||||||
|
|
@ -139,11 +138,6 @@ func New(root common.Hash, db Database) (*StateDB, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogger sets the logger for account update hooks.
|
|
||||||
func (s *StateDB) SetLogger(l *tracing.Hooks) {
|
|
||||||
s.logger = l
|
|
||||||
}
|
|
||||||
|
|
||||||
// setError remembers the first non-nil error it is called with.
|
// setError remembers the first non-nil error it is called with.
|
||||||
func (s *StateDB) setError(err error) {
|
func (s *StateDB) setError(err error) {
|
||||||
if s.dbErr == nil {
|
if s.dbErr == nil {
|
||||||
|
|
@ -183,9 +177,6 @@ func (s *StateDB) AddLog(log *types.Log) {
|
||||||
log.TxHash = s.thash
|
log.TxHash = s.thash
|
||||||
log.TxIndex = uint(s.txIndex)
|
log.TxIndex = uint(s.txIndex)
|
||||||
log.Index = s.logSize
|
log.Index = s.logSize
|
||||||
if s.logger != nil && s.logger.OnLog != nil {
|
|
||||||
s.logger.OnLog(log)
|
|
||||||
}
|
|
||||||
s.logs[s.thash] = append(s.logs[s.thash], log)
|
s.logs[s.thash] = append(s.logs[s.thash], log)
|
||||||
s.logSize++
|
s.logSize++
|
||||||
}
|
}
|
||||||
|
|
@ -390,25 +381,31 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// AddBalance adds amount to the account associated with addr.
|
// AddBalance adds amount to the account associated with addr.
|
||||||
func (s *StateDB) AddBalance(addr common.Address, amount *big.Int, reason tracing.BalanceChangeReason) {
|
func (s *StateDB) AddBalance(addr common.Address, amount *big.Int, _ tracing.BalanceChangeReason) *big.Int {
|
||||||
stateObject := s.GetOrNewStateObject(addr)
|
stateObject := s.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject == nil {
|
||||||
stateObject.AddBalance(amount, reason)
|
return new(big.Int)
|
||||||
}
|
}
|
||||||
|
return stateObject.AddBalance(amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubBalance subtracts amount from the account associated with addr.
|
// SubBalance subtracts amount from the account associated with addr.
|
||||||
func (s *StateDB) SubBalance(addr common.Address, amount *big.Int, reason tracing.BalanceChangeReason) {
|
func (s *StateDB) SubBalance(addr common.Address, amount *big.Int, _ tracing.BalanceChangeReason) *big.Int {
|
||||||
stateObject := s.GetOrNewStateObject(addr)
|
stateObject := s.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject == nil {
|
||||||
stateObject.SubBalance(amount, reason)
|
return new(big.Int)
|
||||||
}
|
}
|
||||||
|
prev := stateObject.Balance()
|
||||||
|
if amount.Sign() == 0 {
|
||||||
|
return new(big.Int).Set(prev)
|
||||||
|
}
|
||||||
|
return stateObject.SetBalance(new(big.Int).Sub(prev, amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) SetBalance(addr common.Address, amount *big.Int, reason tracing.BalanceChangeReason) {
|
func (s *StateDB) SetBalance(addr common.Address, amount *big.Int, _ tracing.BalanceChangeReason) {
|
||||||
stateObject := s.GetOrNewStateObject(addr)
|
stateObject := s.GetOrNewStateObject(addr)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SetBalance(amount, reason)
|
stateObject.SetBalance(amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,11 +423,11 @@ func (s *StateDB) SetCode(addr common.Address, code []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
|
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) common.Hash {
|
||||||
stateObject := s.GetOrNewStateObject(addr)
|
if stateObject := s.GetOrNewStateObject(addr); stateObject != nil {
|
||||||
if stateObject != nil {
|
return stateObject.SetState(s.db, key, value)
|
||||||
stateObject.SetState(s.db, key, value)
|
|
||||||
}
|
}
|
||||||
|
return common.Hash{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStorage replaces the entire storage for the specified account with given
|
// SetStorage replaces the entire storage for the specified account with given
|
||||||
|
|
@ -458,7 +455,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
|
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
|
||||||
newObj.SetNonce(obj.Nonce())
|
newObj.SetNonce(obj.Nonce())
|
||||||
newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified)
|
newObj.SetBalance(obj.Balance())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,36 +464,40 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
|
||||||
//
|
//
|
||||||
// The account's state object is still available until the state is committed,
|
// The account's state object is still available until the state is committed,
|
||||||
// getStateObject will return a non-nil account after SelfDestruct.
|
// getStateObject will return a non-nil account after SelfDestruct.
|
||||||
func (s *StateDB) SelfDestruct(addr common.Address) {
|
func (s *StateDB) SelfDestruct(addr common.Address) *big.Int {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
|
prevBalance := new(big.Int)
|
||||||
if stateObject == nil {
|
if stateObject == nil {
|
||||||
return
|
return prevBalance
|
||||||
}
|
}
|
||||||
var (
|
prevBalance.Set(stateObject.Balance())
|
||||||
prev = new(big.Int).Set(stateObject.Balance())
|
// Regardless of whether it is already destructed or not, we do have to
|
||||||
n = new(big.Int)
|
// journal the balance-change, if we set it to zero here.
|
||||||
)
|
if prevBalance.Sign() != 0 {
|
||||||
s.journal.append(selfDestructChange{
|
stateObject.SetBalance(new(big.Int))
|
||||||
account: addr,
|
|
||||||
prev: stateObject.selfDestructed,
|
|
||||||
prevbalance: prev,
|
|
||||||
})
|
|
||||||
if s.logger != nil && s.logger.OnBalanceChange != nil && prev.Sign() > 0 {
|
|
||||||
s.logger.OnBalanceChange(addr, prev, n, tracing.BalanceDecreaseSelfdestruct)
|
|
||||||
}
|
}
|
||||||
stateObject.markSelfdestructed()
|
// If it is already marked as self-destructed, we do not need to add it
|
||||||
stateObject.data.Balance = n
|
// for journalling a second time.
|
||||||
|
if !stateObject.selfDestructed {
|
||||||
|
s.journal.append(selfDestructChange{
|
||||||
|
account: addr,
|
||||||
|
prev: stateObject.selfDestructed,
|
||||||
|
prevbalance: prevBalance,
|
||||||
|
})
|
||||||
|
stateObject.markSelfdestructed()
|
||||||
|
}
|
||||||
|
return prevBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateDB) Selfdestruct6780(addr common.Address) {
|
func (s *StateDB) SelfDestruct6780(addr common.Address) (*big.Int, bool) {
|
||||||
stateObject := s.getStateObject(addr)
|
stateObject := s.getStateObject(addr)
|
||||||
if stateObject == nil {
|
if stateObject == nil {
|
||||||
return
|
return new(big.Int), false
|
||||||
}
|
}
|
||||||
|
|
||||||
if stateObject.created {
|
if stateObject.created {
|
||||||
s.SelfDestruct(addr)
|
return s.SelfDestruct(addr), true
|
||||||
}
|
}
|
||||||
|
return new(big.Int).Set(stateObject.Balance()), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTransientState sets transient storage for a given account. It
|
// SetTransientState sets transient storage for a given account. It
|
||||||
|
|
@ -653,6 +654,19 @@ func (s *StateDB) CreateAccount(addr common.Address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateContract is used whenever a contract is created. This may be preceded
|
||||||
|
// by CreateAccount, but that is not required if it already existed in the
|
||||||
|
// state due to funds sent beforehand.
|
||||||
|
// This operation sets the 'newContract'-flag, which is required in order to
|
||||||
|
// correctly handle EIP-6780 'delete-in-same-transaction' logic.
|
||||||
|
func (s *StateDB) CreateContract(addr common.Address) {
|
||||||
|
obj := s.getStateObject(addr)
|
||||||
|
if obj != nil && !obj.created {
|
||||||
|
obj.created = true
|
||||||
|
s.journal.createContract(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
|
func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
|
||||||
so := s.getStateObject(addr)
|
so := s.getStateObject(addr)
|
||||||
if so == nil {
|
if so == nil {
|
||||||
|
|
@ -801,14 +815,11 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
|
|
||||||
if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) {
|
if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) {
|
||||||
obj.deleted = true
|
obj.deleted = true
|
||||||
|
|
||||||
// We need to maintain account deletions explicitly (will remain
|
// We need to maintain account deletions explicitly (will remain
|
||||||
// set indefinitely).
|
// set indefinitely). Note only the first occurred self-destruct
|
||||||
s.stateObjectsDestruct[obj.address] = struct{}{}
|
// event is tracked.
|
||||||
|
if _, ok := s.stateObjectsDestruct[obj.address]; !ok {
|
||||||
// If ether was sent to account post-selfdestruct it is burnt.
|
s.stateObjectsDestruct[obj.address] = struct{}{}
|
||||||
if bal := obj.Balance(); s.logger != nil && s.logger.OnBalanceChange != nil && obj.selfDestructed && bal.Sign() != 0 {
|
|
||||||
s.logger.OnBalanceChange(obj.address, bal, new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj.finalise()
|
obj.finalise()
|
||||||
|
|
|
||||||
277
core/state/statedb_hooked.go
Normal file
277
core/state/statedb_hooked.go
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
// 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
)
|
||||||
|
|
||||||
|
// hookedStateDB represents a statedb which emits calls to tracing-hooks
|
||||||
|
// on state operations.
|
||||||
|
type hookedStateDB struct {
|
||||||
|
inner *StateDB
|
||||||
|
hooks *tracing.Hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHookedState wraps the given stateDb with the given hooks
|
||||||
|
func NewHookedState(stateDb *StateDB, hooks *tracing.Hooks) *hookedStateDB {
|
||||||
|
s := &hookedStateDB{stateDb, hooks}
|
||||||
|
if s.hooks == nil {
|
||||||
|
s.hooks = new(tracing.Hooks)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) CreateAccount(addr common.Address) {
|
||||||
|
s.inner.CreateAccount(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) CreateContract(addr common.Address) {
|
||||||
|
s.inner.CreateContract(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetBalance(addr common.Address) *big.Int {
|
||||||
|
return s.inner.GetBalance(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetNonce(addr common.Address) uint64 {
|
||||||
|
return s.inner.GetNonce(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash {
|
||||||
|
return s.inner.GetCodeHash(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetCode(addr common.Address) []byte {
|
||||||
|
return s.inner.GetCode(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetCodeSize(addr common.Address) int {
|
||||||
|
return s.inner.GetCodeSize(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddRefund(u uint64) {
|
||||||
|
s.inner.AddRefund(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SubRefund(u uint64) {
|
||||||
|
s.inner.SubRefund(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetRefund() uint64 {
|
||||||
|
return s.inner.GetRefund()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
|
||||||
|
return s.inner.GetCommittedState(addr, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
|
||||||
|
return s.inner.GetState(addr, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash {
|
||||||
|
return s.inner.GetStorageRoot(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
|
||||||
|
return s.inner.GetTransientState(addr, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SetTransientState(addr common.Address, key, value common.Hash) {
|
||||||
|
s.inner.SetTransientState(addr, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool {
|
||||||
|
return s.inner.HasSelfDestructed(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) Exist(addr common.Address) bool {
|
||||||
|
return s.inner.Exist(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) Empty(addr common.Address) bool {
|
||||||
|
return s.inner.Empty(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddressInAccessList(addr common.Address) bool {
|
||||||
|
return s.inner.AddressInAccessList(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
|
||||||
|
return s.inner.SlotInAccessList(addr, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddAddressToAccessList(addr common.Address) {
|
||||||
|
s.inner.AddAddressToAccessList(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
|
||||||
|
s.inner.AddSlotToAccessList(addr, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
|
||||||
|
s.inner.Prepare(rules, sender, coinbase, dest, precompiles, txAccesses)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) RevertToSnapshot(i int) {
|
||||||
|
s.inner.RevertToSnapshot(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) Snapshot() int {
|
||||||
|
return s.inner.Snapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddPreimage(hash common.Hash, bytes []byte) {
|
||||||
|
s.inner.AddPreimage(hash, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SubBalance(addr common.Address, amount *big.Int, reason tracing.BalanceChangeReason) *big.Int {
|
||||||
|
prev := s.inner.SubBalance(addr, amount, reason)
|
||||||
|
if s.hooks.OnBalanceChange != nil && amount.Sign() != 0 {
|
||||||
|
newBalance := new(big.Int).Sub(prev, amount)
|
||||||
|
s.hooks.OnBalanceChange(addr, prev, newBalance, reason)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddBalance(addr common.Address, amount *big.Int, reason tracing.BalanceChangeReason) *big.Int {
|
||||||
|
prev := s.inner.AddBalance(addr, amount, reason)
|
||||||
|
if s.hooks.OnBalanceChange != nil && amount.Sign() != 0 {
|
||||||
|
newBalance := new(big.Int).Add(prev, amount)
|
||||||
|
s.hooks.OnBalanceChange(addr, prev, newBalance, reason)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) {
|
||||||
|
prev := s.inner.GetNonce(address)
|
||||||
|
s.inner.SetNonce(address, nonce)
|
||||||
|
if s.hooks.OnNonceChange != nil {
|
||||||
|
s.hooks.OnNonceChange(address, prev, nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SetCode(address common.Address, code []byte) {
|
||||||
|
prevCode := s.inner.GetCode(address)
|
||||||
|
s.inner.SetCode(address, code)
|
||||||
|
if s.hooks.OnCodeChange != nil {
|
||||||
|
prevHash := crypto.Keccak256Hash(prevCode)
|
||||||
|
codeHash := crypto.Keccak256Hash(code)
|
||||||
|
|
||||||
|
// Invoke the hooks only if the contract code is changed
|
||||||
|
if prevHash != codeHash {
|
||||||
|
s.hooks.OnCodeChange(address, prevHash, prevCode, codeHash, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value common.Hash) common.Hash {
|
||||||
|
prev := s.inner.SetState(address, key, value)
|
||||||
|
if s.hooks.OnStorageChange != nil && prev != value {
|
||||||
|
s.hooks.OnStorageChange(address, key, prev, value)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SelfDestruct(address common.Address) *big.Int {
|
||||||
|
prev := s.inner.SelfDestruct(address)
|
||||||
|
if s.hooks.OnBalanceChange != nil {
|
||||||
|
s.hooks.OnBalanceChange(address, prev, new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||||
|
}
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) SelfDestruct6780(address common.Address) (*big.Int, bool) {
|
||||||
|
prev, changed := s.inner.SelfDestruct6780(address)
|
||||||
|
if changed {
|
||||||
|
if s.hooks.OnBalanceChange != nil {
|
||||||
|
s.hooks.OnBalanceChange(address, prev, new(big.Int), tracing.BalanceDecreaseSelfdestruct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prev, changed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AddLog(log *types.Log) {
|
||||||
|
// The inner will modify the log (add fields), so invoke that first
|
||||||
|
s.inner.AddLog(log)
|
||||||
|
if s.hooks.OnLog != nil {
|
||||||
|
s.hooks.OnLog(log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) {
|
||||||
|
defer s.inner.Finalise(deleteEmptyObjects)
|
||||||
|
if s.hooks.OnBalanceChange == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for addr := range s.inner.journal.dirties {
|
||||||
|
obj := s.inner.stateObjects[addr]
|
||||||
|
if obj != nil && obj.selfDestructed {
|
||||||
|
// If ether was sent to account post-selfdestruct it is burnt.
|
||||||
|
if bal := obj.Balance(); bal.Sign() != 0 {
|
||||||
|
s.hooks.OnBalanceChange(addr, bal, new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
|
return s.inner.IntermediateRoot(deleteEmptyObjects)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) UpdateTRC21Fee(newBalance map[common.Address]*big.Int, totalFeeUsed *big.Int) {
|
||||||
|
s.inner.UpdateTRC21Fee(newBalance, totalFeeUsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) PutMintedRecordOnsetBlock(value common.Hash) {
|
||||||
|
s.inner.PutMintedRecordOnsetBlock(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) PutMintedRecordOnsetEpoch(value common.Hash) {
|
||||||
|
s.inner.PutMintedRecordOnsetEpoch(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetPostBurned(epoch uint64) common.Hash {
|
||||||
|
return s.inner.GetPostBurned(epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) PutPostBurned(epoch uint64, value common.Hash) {
|
||||||
|
s.inner.PutPostBurned(epoch, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) GetPostMinted(epoch uint64) common.Hash {
|
||||||
|
return s.inner.GetPostMinted(epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) PutPostMinted(epoch uint64, value common.Hash) {
|
||||||
|
s.inner.PutPostMinted(epoch, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) PutPostRewardBlock(epoch uint64, value common.Hash) {
|
||||||
|
s.inner.PutPostRewardBlock(epoch, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) IncrementMintedRecordNonce() {
|
||||||
|
s.inner.IncrementMintedRecordNonce()
|
||||||
|
}
|
||||||
129
core/state/statedb_hooked_test.go
Normal file
129
core/state/statedb_hooked_test.go
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
// 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This method tests that the 'burn' from sending-to-selfdestructed accounts
|
||||||
|
// is accounted for.
|
||||||
|
// (There is also a higher-level test in eth/tracers: TestSupplySelfDestruct )
|
||||||
|
func TestBurn(t *testing.T) {
|
||||||
|
// Note: burn can happen even after EIP-6780, if within one single transaction,
|
||||||
|
// the following occur:
|
||||||
|
// 1. contract B creates contract A
|
||||||
|
// 2. contract A is destructed
|
||||||
|
// 3. contract B sends ether to A
|
||||||
|
|
||||||
|
var burned = new(big.Int)
|
||||||
|
s, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
hooked := NewHookedState(s, &tracing.Hooks{
|
||||||
|
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
||||||
|
if reason == tracing.BalanceDecreaseSelfdestructBurn {
|
||||||
|
burned.Add(burned, prev)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
createAndDestroy := func(addr common.Address) {
|
||||||
|
hooked.AddBalance(addr, big.NewInt(100), tracing.BalanceChangeUnspecified)
|
||||||
|
hooked.CreateContract(addr)
|
||||||
|
hooked.SelfDestruct(addr)
|
||||||
|
// sanity-check that balance is now 0
|
||||||
|
if have, want := hooked.GetBalance(addr), new(big.Int); have.Cmp(want) != 0 {
|
||||||
|
t.Fatalf("post-destruct balance wrong: have %v want %v", have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addA := common.Address{0xaa}
|
||||||
|
addB := common.Address{0xbb}
|
||||||
|
addC := common.Address{0xcc}
|
||||||
|
|
||||||
|
// Tx 1: create and destroy address A and B in one tx
|
||||||
|
createAndDestroy(addA)
|
||||||
|
createAndDestroy(addB)
|
||||||
|
hooked.AddBalance(addA, big.NewInt(200), tracing.BalanceChangeUnspecified)
|
||||||
|
hooked.AddBalance(addB, big.NewInt(200), tracing.BalanceChangeUnspecified)
|
||||||
|
hooked.Finalise(true)
|
||||||
|
|
||||||
|
// Tx 2: create and destroy address C, then commit
|
||||||
|
createAndDestroy(addC)
|
||||||
|
hooked.AddBalance(addC, big.NewInt(200), tracing.BalanceChangeUnspecified)
|
||||||
|
hooked.Finalise(true)
|
||||||
|
|
||||||
|
s.Commit(false)
|
||||||
|
if have, want := burned, big.NewInt(600); have.Cmp(want) != 0 {
|
||||||
|
t.Fatalf("burn-count wrong, have %v want %v", have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHooks is a basic sanity-check of all hooks
|
||||||
|
func TestHooks(t *testing.T) {
|
||||||
|
inner, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
|
||||||
|
inner.SetTxContext(common.Hash{0x11}, 100) // For the log
|
||||||
|
var result []string
|
||||||
|
var wants = []string{
|
||||||
|
"0xaa00000000000000000000000000000000000000.balance: 0->100 (BalanceChangeUnspecified)",
|
||||||
|
"0xaa00000000000000000000000000000000000000.balance: 100->50 (BalanceChangeTransfer)",
|
||||||
|
"0xaa00000000000000000000000000000000000000.nonce: 0->1337",
|
||||||
|
"0xaa00000000000000000000000000000000000000.code: (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470) ->0x1325 (0xa12ae05590de0c93a00bc7ac773c2fdb621e44f814985e72194f921c0050f728)",
|
||||||
|
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000000 ->0x0000000000000000000000000000000000000000000000000000000000000011",
|
||||||
|
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000011 ->0x0000000000000000000000000000000000000000000000000000000000000022",
|
||||||
|
"log 100",
|
||||||
|
}
|
||||||
|
emitF := func(format string, a ...any) {
|
||||||
|
result = append(result, fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
sdb := NewHookedState(inner, &tracing.Hooks{
|
||||||
|
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
|
||||||
|
emitF("%v.balance: %v->%v (%v)", addr, prev, new, reason)
|
||||||
|
},
|
||||||
|
OnNonceChange: func(addr common.Address, prev, new uint64) {
|
||||||
|
emitF("%v.nonce: %v->%v", addr, prev, new)
|
||||||
|
},
|
||||||
|
OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
|
||||||
|
emitF("%v.code: %#x (%v) ->%#x (%v)", addr, prevCode, prevCodeHash, code, codeHash)
|
||||||
|
},
|
||||||
|
OnStorageChange: func(addr common.Address, slot common.Hash, prev, new common.Hash) {
|
||||||
|
emitF("%v.storage slot %v: %v ->%v", addr, slot, prev, new)
|
||||||
|
},
|
||||||
|
OnLog: func(log *types.Log) {
|
||||||
|
emitF("log %v", log.TxIndex)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
sdb.AddBalance(common.Address{0xaa}, big.NewInt(100), tracing.BalanceChangeUnspecified)
|
||||||
|
sdb.SubBalance(common.Address{0xaa}, big.NewInt(50), tracing.BalanceChangeTransfer)
|
||||||
|
sdb.SetNonce(common.Address{0xaa}, 1337)
|
||||||
|
sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37})
|
||||||
|
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11"))
|
||||||
|
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22"))
|
||||||
|
sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x01"))
|
||||||
|
sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x02"))
|
||||||
|
sdb.AddLog(&types.Log{
|
||||||
|
Address: common.Address{0xbb},
|
||||||
|
})
|
||||||
|
for i, want := range wants {
|
||||||
|
if have := result[i]; have != want {
|
||||||
|
t.Fatalf("error event %d\nhave: %v\nwant: %v", i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -155,7 +155,7 @@ func TestCopy(t *testing.T) {
|
||||||
|
|
||||||
for i := byte(0); i < 255; i++ {
|
for i := byte(0); i < 255; i++ {
|
||||||
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
obj := orig.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
obj.AddBalance(big.NewInt(int64(i)), tracing.BalanceChangeUnspecified)
|
obj.AddBalance(big.NewInt(int64(i)))
|
||||||
orig.updateStateObject(obj)
|
orig.updateStateObject(obj)
|
||||||
}
|
}
|
||||||
orig.Finalise(false)
|
orig.Finalise(false)
|
||||||
|
|
@ -172,9 +172,9 @@ func TestCopy(t *testing.T) {
|
||||||
copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
copyObj := copy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
ccopyObj := ccopy.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
|
|
||||||
origObj.AddBalance(big.NewInt(2*int64(i)), tracing.BalanceChangeUnspecified)
|
origObj.AddBalance(big.NewInt(2 * int64(i)))
|
||||||
copyObj.AddBalance(big.NewInt(3*int64(i)), tracing.BalanceChangeUnspecified)
|
copyObj.AddBalance(big.NewInt(3 * int64(i)))
|
||||||
ccopyObj.AddBalance(big.NewInt(4*int64(i)), tracing.BalanceChangeUnspecified)
|
ccopyObj.AddBalance(big.NewInt(4 * int64(i)))
|
||||||
|
|
||||||
orig.updateStateObject(origObj)
|
orig.updateStateObject(origObj)
|
||||||
copy.updateStateObject(copyObj)
|
copy.updateStateObject(copyObj)
|
||||||
|
|
@ -292,6 +292,27 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
|
||||||
s.CreateAccount(addr)
|
s.CreateAccount(addr)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "CreateContract",
|
||||||
|
fn: func(a testAction, s *StateDB) {
|
||||||
|
if !s.Exist(addr) {
|
||||||
|
s.CreateAccount(addr)
|
||||||
|
}
|
||||||
|
contractHash := s.GetCodeHash(addr)
|
||||||
|
emptyCode := contractHash == (common.Hash{}) || contractHash == types.EmptyCodeHash
|
||||||
|
storageRoot := s.GetStorageRoot(addr)
|
||||||
|
emptyStorage := storageRoot == (common.Hash{}) || storageRoot == types.EmptyRootHash
|
||||||
|
if s.GetNonce(addr) == 0 && emptyCode && emptyStorage {
|
||||||
|
s.CreateContract(addr)
|
||||||
|
// We also set some code here, to prevent the
|
||||||
|
// CreateContract action from being performed twice in a row,
|
||||||
|
// which would cause a difference in state when unrolling
|
||||||
|
// the journal. (CreateContract assumes created was false prior to
|
||||||
|
// invocation, and the journal rollback sets it to false).
|
||||||
|
s.SetCode(addr, []byte{1})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "SelfDestruct",
|
name: "SelfDestruct",
|
||||||
fn: func(a testAction, s *StateDB) {
|
fn: func(a testAction, s *StateDB) {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
|
|
@ -52,7 +51,7 @@ func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) {
|
||||||
obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
|
||||||
acc := &testAccount{address: common.BytesToAddress([]byte{i})}
|
acc := &testAccount{address: common.BytesToAddress([]byte{i})}
|
||||||
|
|
||||||
obj.AddBalance(big.NewInt(11*int64(i)), tracing.BalanceChangeUnspecified)
|
obj.AddBalance(big.NewInt(11 * int64(i)))
|
||||||
acc.balance = big.NewInt(11 * int64(i))
|
acc.balance = big.NewInt(11 * int64(i))
|
||||||
|
|
||||||
obj.SetNonce(uint64(42 * i))
|
obj.SetNonce(uint64(42 * i))
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
|
||||||
allLogs []*types.Log
|
allLogs []*types.Log
|
||||||
gp = new(GasPool).AddGas(block.GasLimit())
|
gp = new(GasPool).AddGas(block.GasLimit())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var tracingStateDB = vm.StateDB(statedb)
|
||||||
|
if hooks := cfg.Tracer; hooks != nil {
|
||||||
|
tracingStateDB = state.NewHookedState(statedb, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
// Mutate the block and state according to any hard-fork specs
|
// Mutate the block and state according to any hard-fork specs
|
||||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(tracingStateDB)
|
||||||
}
|
}
|
||||||
if common.TIPSigning.Cmp(blockNumber) == 0 {
|
if common.TIPSigning.Cmp(blockNumber) == 0 {
|
||||||
statedb.DeleteAddress(common.BlockSignersBinary)
|
statedb.DeleteAddress(common.BlockSignersBinary)
|
||||||
|
|
@ -87,10 +93,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
|
||||||
InitSignerInTransactions(p.config, header, block.Transactions())
|
InitSignerInTransactions(p.config, header, block.Transactions())
|
||||||
balanceUpdated := map[common.Address]*big.Int{}
|
balanceUpdated := map[common.Address]*big.Int{}
|
||||||
totalFeeUsed := big.NewInt(0)
|
totalFeeUsed := big.NewInt(0)
|
||||||
|
|
||||||
|
// Apply pre-execution system calls.
|
||||||
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, tradingState, p.config, cfg)
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, tracingStateDB, tradingState, p.config, cfg)
|
||||||
signer := types.MakeSigner(p.config, blockNumber)
|
signer := types.MakeSigner(p.config, blockNumber)
|
||||||
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
|
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
|
||||||
|
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// check black-list txs after hf
|
// check black-list txs after hf
|
||||||
|
|
@ -144,9 +153,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
|
||||||
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
|
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statedb.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
|
tracingStateDB.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
|
||||||
|
|
||||||
// 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.engine.Finalize(p.bc, header, statedb, parentState, block.Transactions(), block.Uncles(), receipts)
|
p.engine.Finalize(p.bc, header, tracingStateDB, parentState, block.Transactions(), block.Uncles(), receipts)
|
||||||
|
|
||||||
return receipts, allLogs, *usedGas, nil
|
return receipts, allLogs, *usedGas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,9 +172,15 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
allLogs []*types.Log
|
allLogs []*types.Log
|
||||||
gp = new(GasPool).AddGas(block.GasLimit())
|
gp = new(GasPool).AddGas(block.GasLimit())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var tracingStateDB = vm.StateDB(statedb)
|
||||||
|
if hooks := cfg.Tracer; hooks != nil {
|
||||||
|
tracingStateDB = state.NewHookedState(statedb, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
// Mutate the block and state according to any hard-fork specs
|
// Mutate the block and state according to any hard-fork specs
|
||||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(tracingStateDB)
|
||||||
}
|
}
|
||||||
if common.TIPSigning.Cmp(blockNumber) == 0 {
|
if common.TIPSigning.Cmp(blockNumber) == 0 {
|
||||||
statedb.DeleteAddress(common.BlockSignersBinary)
|
statedb.DeleteAddress(common.BlockSignersBinary)
|
||||||
|
|
@ -179,10 +196,13 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
if cBlock.stop {
|
if cBlock.stop {
|
||||||
return nil, nil, 0, ErrStopPreparingBlock
|
return nil, nil, 0, ErrStopPreparingBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply pre-execution system calls.
|
||||||
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
blockContext := NewEVMBlockContext(header, p.bc, nil)
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, tradingState, p.config, cfg)
|
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, tracingStateDB, tradingState, p.config, cfg)
|
||||||
signer := types.MakeSigner(p.config, blockNumber)
|
signer := types.MakeSigner(p.config, blockNumber)
|
||||||
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
|
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
|
||||||
|
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
receipts = make([]*types.Receipt, block.Transactions().Len())
|
receipts = make([]*types.Receipt, block.Transactions().Len())
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
|
@ -222,6 +242,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, balanceFee, coinbaseOwner)
|
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, balanceFee, coinbaseOwner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
|
|
@ -238,9 +259,10 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
|
totalFeeUsed = totalFeeUsed.Add(totalFeeUsed, fee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statedb.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
|
tracingStateDB.UpdateTRC21Fee(balanceUpdated, totalFeeUsed)
|
||||||
|
|
||||||
// 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.engine.Finalize(p.bc, header, statedb, parentState, block.Transactions(), block.Uncles(), receipts)
|
p.engine.Finalize(p.bc, header, tracingStateDB, parentState, block.Transactions(), block.Uncles(), receipts)
|
||||||
return receipts, allLogs, *usedGas, nil
|
return receipts, allLogs, *usedGas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,39 +272,39 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
|
||||||
func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, balanceFee *big.Int, coinbaseOwner common.Address) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
|
func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, balanceFee *big.Int, coinbaseOwner common.Address) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
|
||||||
// Initialize tracer at the beginning to ensure all transaction types
|
// Initialize tracer at the beginning to ensure all transaction types
|
||||||
// (including non-EVM special transactions) are properly traced.
|
// (including non-EVM special transactions) are properly traced.
|
||||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil {
|
var tracingStateDB = vm.StateDB(statedb)
|
||||||
evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
if hooks := evm.Config.Tracer; hooks != nil {
|
||||||
if evm.Config.Tracer.OnTxEnd != nil {
|
tracingStateDB = state.NewHookedState(statedb, hooks)
|
||||||
defer func() {
|
if hooks.OnTxStart != nil {
|
||||||
evm.Config.Tracer.OnTxEnd(receipt, err)
|
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}()
|
}
|
||||||
|
if hooks.OnTxEnd != nil {
|
||||||
|
defer func() { hooks.OnTxEnd(receipt, err) }()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to := tx.To()
|
to := tx.To()
|
||||||
if to != nil {
|
if to != nil {
|
||||||
if *to == common.BlockSignersBinary && config.IsTIPSigning(blockNumber) {
|
if *to == common.BlockSignersBinary && config.IsTIPSigning(blockNumber) {
|
||||||
return ApplySignTransaction(config, statedb, blockNumber, blockHash, tx, usedGas)
|
return ApplySignTransaction(msg, config, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
}
|
}
|
||||||
if *to == common.TradingStateAddrBinary && config.IsTIPXDCXReceiver(blockNumber) {
|
if *to == common.TradingStateAddrBinary && config.IsTIPXDCXReceiver(blockNumber) {
|
||||||
return ApplyEmptyTransaction(config, statedb, blockNumber, blockHash, tx, usedGas)
|
return ApplyEmptyTransaction(msg, config, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
}
|
}
|
||||||
if *to == common.XDCXLendingAddressBinary && config.IsTIPXDCXReceiver(blockNumber) {
|
if *to == common.XDCXLendingAddressBinary && config.IsTIPXDCXReceiver(blockNumber) {
|
||||||
return ApplyEmptyTransaction(config, statedb, blockNumber, blockHash, tx, usedGas)
|
return ApplyEmptyTransaction(msg, config, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tx.IsTradingTransaction() && config.IsTIPXDCXReceiver(blockNumber) {
|
if tx.IsTradingTransaction() && config.IsTIPXDCXReceiver(blockNumber) {
|
||||||
return ApplyEmptyTransaction(config, statedb, blockNumber, blockHash, tx, usedGas)
|
return ApplyEmptyTransaction(msg, config, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
}
|
}
|
||||||
if tx.IsLendingFinalizedTradeTransaction() && config.IsTIPXDCXReceiver(blockNumber) {
|
if tx.IsLendingFinalizedTradeTransaction() && config.IsTIPXDCXReceiver(blockNumber) {
|
||||||
return ApplyEmptyTransaction(config, statedb, blockNumber, blockHash, tx, usedGas)
|
return ApplyEmptyTransaction(msg, config, statedb, blockNumber, blockHash, tx, usedGas, evm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new context to be used in the EVM environment
|
// Create a new context to be used in the EVM environment
|
||||||
txContext := NewEVMTxContext(msg)
|
txContext := NewEVMTxContext(msg)
|
||||||
|
evm.Reset(txContext, tracingStateDB)
|
||||||
// Update the evm with the new transaction context.
|
|
||||||
evm.Reset(txContext, statedb)
|
|
||||||
|
|
||||||
// Bypass blacklist address
|
// Bypass blacklist address
|
||||||
maxBlockNumber := new(big.Int).SetInt64(9147459)
|
maxBlockNumber := new(big.Int).SetInt64(9147459)
|
||||||
|
|
@ -437,7 +459,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
if config.IsByzantium(blockNumber) {
|
if config.IsByzantium(blockNumber) {
|
||||||
statedb.Finalise(true)
|
tracingStateDB.Finalise(true)
|
||||||
} else {
|
} else {
|
||||||
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
|
|
@ -512,7 +534,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
|
||||||
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, balanceFee, coinbaseOwner)
|
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, balanceFee, coinbaseOwner)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, bool, error) {
|
func ApplySignTransaction(msg *Message, config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
|
||||||
// Update the state with pending changes
|
// Update the state with pending changes
|
||||||
var root []byte
|
var root []byte
|
||||||
if config.IsByzantium(blockNumber) {
|
if config.IsByzantium(blockNumber) {
|
||||||
|
|
@ -532,8 +554,8 @@ func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, bl
|
||||||
}
|
}
|
||||||
statedb.SetNonce(from, nonce+1)
|
statedb.SetNonce(from, nonce+1)
|
||||||
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
|
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
|
||||||
// based on the eip phase, we're passing wether the root touch-delete accounts.
|
// based on the eip phase, we're passing whether the root touch-delete accounts.
|
||||||
receipt := types.NewReceipt(root, false, *usedGas)
|
receipt = types.NewReceipt(root, false, *usedGas)
|
||||||
receipt.TxHash = tx.Hash()
|
receipt.TxHash = tx.Hash()
|
||||||
receipt.GasUsed = 0
|
receipt.GasUsed = 0
|
||||||
// if the transaction created a contract, store the creation address in the receipt.
|
// if the transaction created a contract, store the creation address in the receipt.
|
||||||
|
|
@ -550,7 +572,7 @@ func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, bl
|
||||||
return receipt, 0, false, nil
|
return receipt, 0, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyEmptyTransaction(config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, bool, error) {
|
func ApplyEmptyTransaction(msg *Message, config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
|
||||||
// Update the state with pending changes
|
// Update the state with pending changes
|
||||||
var root []byte
|
var root []byte
|
||||||
if config.IsByzantium(blockNumber) {
|
if config.IsByzantium(blockNumber) {
|
||||||
|
|
@ -559,8 +581,8 @@ func ApplyEmptyTransaction(config *params.ChainConfig, statedb *state.StateDB, b
|
||||||
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
|
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
|
||||||
// based on the eip phase, we're passing wether the root touch-delete accounts.
|
// based on the eip phase, we're passing whether the root touch-delete accounts.
|
||||||
receipt := types.NewReceipt(root, false, *usedGas)
|
receipt = types.NewReceipt(root, false, *usedGas)
|
||||||
receipt.TxHash = tx.Hash()
|
receipt.TxHash = tx.Hash()
|
||||||
receipt.GasUsed = 0
|
receipt.GasUsed = 0
|
||||||
// if the transaction created a contract, store the creation address in the receipt.
|
// if the transaction created a contract, store the creation address in the receipt.
|
||||||
|
|
|
||||||
|
|
@ -859,7 +859,7 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
||||||
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
||||||
evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
|
evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
|
||||||
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||||
evm.StateDB.Selfdestruct6780(scope.Contract.Address())
|
evm.StateDB.SelfDestruct6780(scope.Contract.Address())
|
||||||
if tracer := evm.Config.Tracer; tracer != nil {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
if tracer.OnEnter != nil {
|
if tracer.OnEnter != nil {
|
||||||
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance)
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import (
|
||||||
type StateDB interface {
|
type StateDB interface {
|
||||||
CreateAccount(common.Address)
|
CreateAccount(common.Address)
|
||||||
|
|
||||||
SubBalance(common.Address, *big.Int, tracing.BalanceChangeReason)
|
SubBalance(common.Address, *big.Int, tracing.BalanceChangeReason) *big.Int
|
||||||
AddBalance(common.Address, *big.Int, tracing.BalanceChangeReason)
|
AddBalance(common.Address, *big.Int, tracing.BalanceChangeReason) *big.Int
|
||||||
GetBalance(common.Address) *big.Int
|
GetBalance(common.Address) *big.Int
|
||||||
|
|
||||||
GetNonce(common.Address) uint64
|
GetNonce(common.Address) uint64
|
||||||
|
|
@ -47,16 +47,21 @@ type StateDB interface {
|
||||||
|
|
||||||
GetCommittedState(common.Address, common.Hash) common.Hash
|
GetCommittedState(common.Address, common.Hash) common.Hash
|
||||||
GetState(common.Address, common.Hash) common.Hash
|
GetState(common.Address, common.Hash) common.Hash
|
||||||
SetState(common.Address, common.Hash, common.Hash)
|
SetState(common.Address, common.Hash, common.Hash) common.Hash
|
||||||
GetStorageRoot(addr common.Address) common.Hash
|
GetStorageRoot(addr common.Address) common.Hash
|
||||||
|
|
||||||
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
GetTransientState(addr common.Address, key common.Hash) common.Hash
|
||||||
SetTransientState(addr common.Address, key, value common.Hash)
|
SetTransientState(addr common.Address, key, value common.Hash)
|
||||||
|
|
||||||
SelfDestruct(common.Address)
|
SelfDestruct(common.Address) *big.Int
|
||||||
HasSelfDestructed(common.Address) bool
|
HasSelfDestructed(common.Address) bool
|
||||||
|
|
||||||
Selfdestruct6780(common.Address)
|
// SelfDestruct6780 is post-EIP6780 selfdestruct, which means that it's a
|
||||||
|
// send-all-to-beneficiary, unless the contract was created in this same
|
||||||
|
// transaction, in which case it will be destructed.
|
||||||
|
// This method returns the prior balance, along with a boolean which is
|
||||||
|
// true iff the object was indeed destructed.
|
||||||
|
SelfDestruct6780(common.Address) (*big.Int, bool)
|
||||||
|
|
||||||
// Exist reports whether the given account exists in state.
|
// Exist reports whether the given account exists in state.
|
||||||
// Notably this should also return true for self-destructed accounts.
|
// Notably this should also return true for self-destructed accounts.
|
||||||
|
|
@ -80,6 +85,26 @@ type StateDB interface {
|
||||||
|
|
||||||
AddLog(*types.Log)
|
AddLog(*types.Log)
|
||||||
AddPreimage(common.Hash, []byte)
|
AddPreimage(common.Hash, []byte)
|
||||||
|
|
||||||
|
// Finalise must be invoked at the end of a transaction
|
||||||
|
Finalise(bool)
|
||||||
|
|
||||||
|
IntermediateRoot(deleteEmptyObjects bool) common.Hash
|
||||||
|
|
||||||
|
UpdateTRC21Fee(newBalance map[common.Address]*big.Int, totalFeeUsed *big.Int)
|
||||||
|
|
||||||
|
PutMintedRecordOnsetBlock(value common.Hash)
|
||||||
|
PutMintedRecordOnsetEpoch(value common.Hash)
|
||||||
|
|
||||||
|
GetPostBurned(epoch uint64) common.Hash
|
||||||
|
PutPostBurned(epoch uint64, value common.Hash)
|
||||||
|
|
||||||
|
GetPostMinted(epoch uint64) common.Hash
|
||||||
|
PutPostMinted(epoch uint64, value common.Hash)
|
||||||
|
|
||||||
|
PutPostRewardBlock(epoch uint64, value common.Hash)
|
||||||
|
|
||||||
|
IncrementMintedRecordNonce()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/util"
|
"github.com/XinFinOrg/XDPoSChain/eth/util"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
|
@ -255,7 +256,7 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook calculates reward for masternodes
|
// Hook calculates reward for masternodes
|
||||||
adaptor.EngineV1.HookReward = func(chain consensus.ChainReader, stateBlock *state.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error) {
|
adaptor.EngineV1.HookReward = func(chain consensus.ChainReader, stateBlock vm.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error) {
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
rCheckpoint := chain.Config().XDPoS.RewardCheckpoint
|
||||||
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/eth/util"
|
"github.com/XinFinOrg/XDPoSChain/eth/util"
|
||||||
"github.com/XinFinOrg/XDPoSChain/log"
|
"github.com/XinFinOrg/XDPoSChain/log"
|
||||||
"github.com/XinFinOrg/XDPoSChain/params"
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
|
@ -265,7 +266,7 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook calculates reward for masternodes
|
// Hook calculates reward for masternodes
|
||||||
adaptor.EngineV2.HookReward = func(chain consensus.ChainReader, stateBlock *state.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error) {
|
adaptor.EngineV2.HookReward = func(chain consensus.ChainReader, stateBlock vm.StateDB, parentState *state.StateDB, header *types.Header) (map[string]interface{}, error) {
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
|
||||||
if foundationWalletAddr == (common.Address{}) {
|
if foundationWalletAddr == (common.Address{}) {
|
||||||
|
|
|
||||||
|
|
@ -881,7 +881,6 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
}
|
}
|
||||||
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
|
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice}, statedb, nil, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice}, statedb, nil, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
||||||
statedb.SetLogger(tracer.Hooks)
|
|
||||||
|
|
||||||
// Define a meaningful timeout of a single transaction trace
|
// Define a meaningful timeout of a single transaction trace
|
||||||
if config.Timeout != nil {
|
if config.Timeout != nil {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core"
|
"github.com/XinFinOrg/XDPoSChain/core"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
|
|
@ -126,20 +127,22 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
GasLimit: uint64(test.Context.GasLimit),
|
GasLimit: uint64(test.Context.GasLimit),
|
||||||
BaseFee: test.Genesis.BaseFee,
|
BaseFee: test.Genesis.BaseFee,
|
||||||
}
|
}
|
||||||
state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
|
st = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
|
||||||
)
|
)
|
||||||
|
|
||||||
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
|
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
logState := vm.StateDB(st)
|
||||||
state.SetLogger(tracer.Hooks)
|
if tracer.Hooks != nil {
|
||||||
|
logState = state.NewHookedState(st, tracer.Hooks)
|
||||||
|
}
|
||||||
msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), logState, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{})
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -348,7 +351,7 @@ func TestInternals(t *testing.T) {
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
state := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
st := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||||
types.GenesisAlloc{
|
types.GenesisAlloc{
|
||||||
to: types.Account{
|
to: types.Account{
|
||||||
Code: tc.code,
|
Code: tc.code,
|
||||||
|
|
@ -357,7 +360,12 @@ func TestInternals(t *testing.T) {
|
||||||
Balance: big.NewInt(500000000000000),
|
Balance: big.NewInt(500000000000000),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
state.SetLogger(tc.tracer.Hooks)
|
|
||||||
|
logState := vm.StateDB(st)
|
||||||
|
if hooks := tc.tracer.Hooks; hooks != nil {
|
||||||
|
logState = state.NewHookedState(st, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
||||||
To: &to,
|
To: &to,
|
||||||
Value: big.NewInt(0),
|
Value: big.NewInt(0),
|
||||||
|
|
@ -371,7 +379,7 @@ func TestInternals(t *testing.T) {
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
GasPrice: tx.GasPrice(),
|
GasPrice: tx.GasPrice(),
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, state, nil, config, vm.Config{Tracer: tc.tracer.Hooks})
|
evm := vm.NewEVM(context, txContext, logState, nil, config, vm.Config{Tracer: tc.tracer.Hooks})
|
||||||
msg, err := core.TransactionToMessage(tx, signer, nil, nil, big.NewInt(0))
|
msg, err := core.TransactionToMessage(tx, signer, nil, nil, big.NewInt(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,6 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
||||||
return fmt.Errorf("failed to create call tracer: %v", err)
|
return fmt.Errorf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.SetLogger(tracer.Hooks)
|
|
||||||
msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -109,18 +109,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create call tracer: %v", err)
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
}
|
}
|
||||||
// msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
|
||||||
// }
|
|
||||||
// evm := vm.NewEVM(context, core.NewEVMTxContext(msg), statedb, nil, test.Genesis.Config, vm.Config{Tracer: tracer})
|
|
||||||
// st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
|
||||||
// if _, err = st.TransitionDb(common.Address{}); err != nil {
|
|
||||||
// t.Fatalf("failed to execute transaction: %v", err)
|
|
||||||
// }
|
|
||||||
// // Retrieve the trace result and compare against the expected.
|
|
||||||
|
|
||||||
state.SetLogger(tracer.Hooks)
|
|
||||||
msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, nil, context.BlockNumber, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,11 @@ type dummyStatedb struct {
|
||||||
state.StateDB
|
state.StateDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
||||||
func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} }
|
func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} }
|
||||||
func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {}
|
func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) common.Hash {
|
||||||
|
return common.Hash{}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStoreCapture(t *testing.T) {
|
func TestStoreCapture(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -1292,10 +1292,16 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
|
||||||
evm.SetPrecompiles(precompiles)
|
evm.SetPrecompiles(precompiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
return applyMessageWithEVM(ctx, evm, msg, state, timeout, gp)
|
res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp)
|
||||||
|
// If an internal state error occurred, let that have precedence. Otherwise,
|
||||||
|
// a "trie root missing" type of error will masquerade as e.g. "insufficient gas"
|
||||||
|
if err := state.Error(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, state *state.StateDB, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) {
|
func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) {
|
||||||
// Wait for the context to be done and cancel the evm. Even if the
|
// Wait for the context to be done and cancel the evm. Even if the
|
||||||
// EVM has finished, cancelling may be done (repeatedly)
|
// EVM has finished, cancelling may be done (repeatedly)
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -1305,9 +1311,6 @@ func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, st
|
||||||
|
|
||||||
// Execute the message.
|
// Execute the message.
|
||||||
result, err := core.ApplyMessage(evm, msg, gp, common.Address{})
|
result, err := core.ApplyMessage(evm, msg, gp, common.Address{})
|
||||||
if err := state.Error(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the timer caused an abort, return an appropriate error message
|
// If the timer caused an abort, return an appropriate error message
|
||||||
if evm.Cancelled() {
|
if evm.Cancelled() {
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
}
|
}
|
||||||
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, nil, sim.chainConfig, *vmConfig)
|
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, nil, sim.chainConfig, *vmConfig)
|
||||||
)
|
)
|
||||||
sim.state.SetLogger(tracer.Hooks())
|
var tracingStateDB = vm.StateDB(sim.state)
|
||||||
|
if hooks := tracer.Hooks(); hooks != nil {
|
||||||
|
tracingStateDB = state.NewHookedState(sim.state, hooks)
|
||||||
|
}
|
||||||
// It is possible to override precompiles with EVM bytecode, or
|
// It is possible to override precompiles with EVM bytecode, or
|
||||||
// move them to another address.
|
// move them to another address.
|
||||||
if precompiles != nil {
|
if precompiles != nil {
|
||||||
|
|
@ -195,8 +198,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
tracer.reset(tx.Hash(), uint(i))
|
tracer.reset(tx.Hash(), uint(i))
|
||||||
// EoA check is always skipped, even in validation mode.
|
// EoA check is always skipped, even in validation mode.
|
||||||
msg := call.ToMessage(sim.b, header.BaseFee, !sim.validate, true)
|
msg := call.ToMessage(sim.b, header.BaseFee, !sim.validate, true)
|
||||||
evm.Reset(core.NewEVMTxContext(msg), sim.state)
|
evm.Reset(core.NewEVMTxContext(msg), tracingStateDB)
|
||||||
result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, sim.gp)
|
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
txErr := txValidationError(err)
|
txErr := txValidationError(err)
|
||||||
return nil, nil, txErr
|
return nil, nil, txErr
|
||||||
|
|
@ -204,7 +207,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
if sim.chainConfig.IsByzantium(blockContext.BlockNumber) {
|
if sim.chainConfig.IsByzantium(blockContext.BlockNumber) {
|
||||||
sim.state.Finalise(true)
|
tracingStateDB.Finalise(true)
|
||||||
} else {
|
} else {
|
||||||
root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes()
|
root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue