mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
core: miner: reduce allocations in block building (#33375)
I recently went on a longer flight and started profiling the geth block
production pipeline.
This PR contains a bunch of individual fixes split into separate
commits.
I can drop some if necessary.
Benchmarking is not super easy, the benchmark I wrote is a bit
non-deterministic.
I will try to write a better benchmark later
```
goos: linux
goarch: amd64
pkg: github.com/ethereum/go-ethereum/miner
cpu: Intel(R) Core(TM) Ultra 7 155U
│ /tmp/old.txt │ /tmp/new.txt │
│ sec/op │ sec/op vs base │
BuildPayload-14 141.5µ ± 3% 146.0µ ± 6% ~ (p=0.346 n=200)
│ /tmp/old.txt │ /tmp/new.txt │
│ B/op │ B/op vs base │
BuildPayload-14 188.2Ki ± 4% 177.4Ki ± 4% -5.71% (p=0.018 n=200)
│ /tmp/old.txt │ /tmp/new.txt │
│ allocs/op │ allocs/op vs base │
BuildPayload-14 2.703k ± 4% 2.453k ± 5% -9.25% (p=0.000 n=200)
```
This commit is contained in:
parent
6530945dcd
commit
16a6531ac2
11 changed files with 97 additions and 101 deletions
|
|
@ -53,9 +53,9 @@ func (bc *BlobConfig) blobPrice(excessBlobGas uint64) *big.Int {
|
|||
return new(big.Int).Mul(f, big.NewInt(params.BlobTxBlobGasPerBlob))
|
||||
}
|
||||
|
||||
func latestBlobConfig(cfg *params.ChainConfig, time uint64) *BlobConfig {
|
||||
func latestBlobConfig(cfg *params.ChainConfig, time uint64) (BlobConfig, error) {
|
||||
if cfg.BlobScheduleConfig == nil {
|
||||
return nil
|
||||
return BlobConfig{}, errors.New("no blob config")
|
||||
}
|
||||
var (
|
||||
london = cfg.LondonBlock
|
||||
|
|
@ -80,14 +80,14 @@ func latestBlobConfig(cfg *params.ChainConfig, time uint64) *BlobConfig {
|
|||
case cfg.IsCancun(london, time) && s.Cancun != nil:
|
||||
bc = s.Cancun
|
||||
default:
|
||||
return nil
|
||||
return BlobConfig{}, errors.New("no blob config")
|
||||
}
|
||||
|
||||
return &BlobConfig{
|
||||
return BlobConfig{
|
||||
Target: bc.Target,
|
||||
Max: bc.Max,
|
||||
UpdateFraction: bc.UpdateFraction,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
|
||||
|
|
@ -98,8 +98,8 @@ func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Heade
|
|||
panic("bad header pair")
|
||||
}
|
||||
|
||||
bcfg := latestBlobConfig(config, header.Time)
|
||||
if bcfg == nil {
|
||||
bcfg, err := latestBlobConfig(config, header.Time)
|
||||
if err != nil {
|
||||
panic("called before EIP-4844 is active")
|
||||
}
|
||||
|
||||
|
|
@ -130,11 +130,14 @@ func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Heade
|
|||
// blobs on top of the excess blob gas.
|
||||
func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTimestamp uint64) uint64 {
|
||||
isOsaka := config.IsOsaka(config.LondonBlock, headTimestamp)
|
||||
bcfg := latestBlobConfig(config, headTimestamp)
|
||||
bcfg, err := latestBlobConfig(config, headTimestamp)
|
||||
if err != nil {
|
||||
panic("calculating excess blob gas on nil blob config")
|
||||
}
|
||||
return calcExcessBlobGas(isOsaka, bcfg, parent)
|
||||
}
|
||||
|
||||
func calcExcessBlobGas(isOsaka bool, bcfg *BlobConfig, parent *types.Header) uint64 {
|
||||
func calcExcessBlobGas(isOsaka bool, bcfg BlobConfig, parent *types.Header) uint64 {
|
||||
var parentExcessBlobGas, parentBlobGasUsed uint64
|
||||
if parent.ExcessBlobGas != nil {
|
||||
parentExcessBlobGas = *parent.ExcessBlobGas
|
||||
|
|
@ -169,8 +172,8 @@ func calcExcessBlobGas(isOsaka bool, bcfg *BlobConfig, parent *types.Header) uin
|
|||
|
||||
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
||||
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
||||
blobConfig := latestBlobConfig(config, header.Time)
|
||||
if blobConfig == nil {
|
||||
blobConfig, err := latestBlobConfig(config, header.Time)
|
||||
if err != nil {
|
||||
panic("calculating blob fee on unsupported fork")
|
||||
}
|
||||
return blobConfig.blobBaseFee(*header.ExcessBlobGas)
|
||||
|
|
@ -178,8 +181,8 @@ func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
|
|||
|
||||
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
|
||||
func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
||||
blobConfig := latestBlobConfig(cfg, time)
|
||||
if blobConfig == nil {
|
||||
blobConfig, err := latestBlobConfig(cfg, time)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return blobConfig.Max
|
||||
|
|
@ -193,8 +196,8 @@ func MaxBlobGasPerBlock(cfg *params.ChainConfig, time uint64) uint64 {
|
|||
// LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
|
||||
// configuration, regardless of the currently active fork.
|
||||
func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
|
||||
bcfg := latestBlobConfig(cfg, math.MaxUint64)
|
||||
if bcfg == nil {
|
||||
bcfg, err := latestBlobConfig(cfg, math.MaxUint64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return bcfg.Max
|
||||
|
|
@ -202,8 +205,8 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
|
|||
|
||||
// TargetBlobsPerBlock returns the target blobs per block for a block at the given timestamp.
|
||||
func TargetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
|
||||
blobConfig := latestBlobConfig(cfg, time)
|
||||
if blobConfig == nil {
|
||||
blobConfig, err := latestBlobConfig(cfg, time)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return blobConfig.Target
|
||||
|
|
|
|||
|
|
@ -80,12 +80,9 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||
func NewEVMTxContext(msg *Message) vm.TxContext {
|
||||
ctx := vm.TxContext{
|
||||
Origin: msg.From,
|
||||
GasPrice: new(big.Int).Set(msg.GasPrice),
|
||||
GasPrice: uint256.MustFromBig(msg.GasPrice),
|
||||
BlobHashes: msg.BlobHashes,
|
||||
}
|
||||
if msg.BlobGasFeeCap != nil {
|
||||
ctx.BlobFeeCap = new(big.Int).Set(msg.BlobGasFeeCap)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ type journalEntry interface {
|
|||
revert(*StateDB)
|
||||
|
||||
// dirtied returns the Ethereum address modified by this journal entry.
|
||||
dirtied() *common.Address
|
||||
// indicates false if no address was changed.
|
||||
dirtied() (common.Address, bool)
|
||||
|
||||
// copy returns a deep-copied journal entry.
|
||||
copy() journalEntry
|
||||
|
|
@ -100,8 +101,8 @@ func (j *journal) revertToSnapshot(revid int, s *StateDB) {
|
|||
// append inserts a new modification entry to the end of the change journal.
|
||||
func (j *journal) append(entry journalEntry) {
|
||||
j.entries = append(j.entries, entry)
|
||||
if addr := entry.dirtied(); addr != nil {
|
||||
j.dirties[*addr]++
|
||||
if addr, dirty := entry.dirtied(); dirty {
|
||||
j.dirties[addr]++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,9 +114,9 @@ func (j *journal) revert(statedb *StateDB, snapshot int) {
|
|||
j.entries[i].revert(statedb)
|
||||
|
||||
// Drop any dirty tracking induced by the change
|
||||
if addr := j.entries[i].dirtied(); addr != nil {
|
||||
if j.dirties[*addr]--; j.dirties[*addr] == 0 {
|
||||
delete(j.dirties, *addr)
|
||||
if addr, dirty := j.entries[i].dirtied(); dirty {
|
||||
if j.dirties[addr]--; j.dirties[addr] == 0 {
|
||||
delete(j.dirties, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -294,8 +295,8 @@ func (ch createObjectChange) revert(s *StateDB) {
|
|||
delete(s.stateObjects, ch.account)
|
||||
}
|
||||
|
||||
func (ch createObjectChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch createObjectChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch createObjectChange) copy() journalEntry {
|
||||
|
|
@ -308,8 +309,8 @@ func (ch createContractChange) revert(s *StateDB) {
|
|||
s.getStateObject(ch.account).newContract = false
|
||||
}
|
||||
|
||||
func (ch createContractChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch createContractChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch createContractChange) copy() journalEntry {
|
||||
|
|
@ -325,8 +326,8 @@ func (ch selfDestructChange) revert(s *StateDB) {
|
|||
}
|
||||
}
|
||||
|
||||
func (ch selfDestructChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch selfDestructChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch selfDestructChange) copy() journalEntry {
|
||||
|
|
@ -340,8 +341,8 @@ var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
|
|||
func (ch touchChange) revert(s *StateDB) {
|
||||
}
|
||||
|
||||
func (ch touchChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch touchChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch touchChange) copy() journalEntry {
|
||||
|
|
@ -354,8 +355,8 @@ func (ch balanceChange) revert(s *StateDB) {
|
|||
s.getStateObject(ch.account).setBalance(ch.prev)
|
||||
}
|
||||
|
||||
func (ch balanceChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch balanceChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch balanceChange) copy() journalEntry {
|
||||
|
|
@ -369,8 +370,8 @@ func (ch nonceChange) revert(s *StateDB) {
|
|||
s.getStateObject(ch.account).setNonce(ch.prev)
|
||||
}
|
||||
|
||||
func (ch nonceChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch nonceChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch nonceChange) copy() journalEntry {
|
||||
|
|
@ -384,8 +385,8 @@ func (ch codeChange) revert(s *StateDB) {
|
|||
s.getStateObject(ch.account).setCode(crypto.Keccak256Hash(ch.prevCode), ch.prevCode)
|
||||
}
|
||||
|
||||
func (ch codeChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch codeChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch codeChange) copy() journalEntry {
|
||||
|
|
@ -399,8 +400,8 @@ func (ch storageChange) revert(s *StateDB) {
|
|||
s.getStateObject(ch.account).setState(ch.key, ch.prevvalue, ch.origvalue)
|
||||
}
|
||||
|
||||
func (ch storageChange) dirtied() *common.Address {
|
||||
return &ch.account
|
||||
func (ch storageChange) dirtied() (common.Address, bool) {
|
||||
return ch.account, true
|
||||
}
|
||||
|
||||
func (ch storageChange) copy() journalEntry {
|
||||
|
|
@ -416,8 +417,8 @@ func (ch transientStorageChange) revert(s *StateDB) {
|
|||
s.setTransientState(ch.account, ch.key, ch.prevalue)
|
||||
}
|
||||
|
||||
func (ch transientStorageChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch transientStorageChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch transientStorageChange) copy() journalEntry {
|
||||
|
|
@ -432,8 +433,8 @@ func (ch refundChange) revert(s *StateDB) {
|
|||
s.refund = ch.prev
|
||||
}
|
||||
|
||||
func (ch refundChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch refundChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch refundChange) copy() journalEntry {
|
||||
|
|
@ -452,8 +453,8 @@ func (ch addLogChange) revert(s *StateDB) {
|
|||
s.logSize--
|
||||
}
|
||||
|
||||
func (ch addLogChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch addLogChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch addLogChange) copy() journalEntry {
|
||||
|
|
@ -475,8 +476,8 @@ func (ch accessListAddAccountChange) revert(s *StateDB) {
|
|||
s.accessList.DeleteAddress(ch.address)
|
||||
}
|
||||
|
||||
func (ch accessListAddAccountChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch accessListAddAccountChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch accessListAddAccountChange) copy() journalEntry {
|
||||
|
|
@ -489,8 +490,8 @@ func (ch accessListAddSlotChange) revert(s *StateDB) {
|
|||
s.accessList.DeleteSlot(ch.address, ch.slot)
|
||||
}
|
||||
|
||||
func (ch accessListAddSlotChange) dirtied() *common.Address {
|
||||
return nil
|
||||
func (ch accessListAddSlotChange) dirtied() (common.Address, bool) {
|
||||
return common.Address{}, false
|
||||
}
|
||||
|
||||
func (ch accessListAddSlotChange) copy() journalEntry {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ func (s Storage) Copy() Storage {
|
|||
type stateObject struct {
|
||||
db *StateDB
|
||||
address common.Address // address of ethereum account
|
||||
addrHash common.Hash // hash of ethereum address of the account
|
||||
addressHash *common.Hash // hash of ethereum address of the account
|
||||
origin *types.StateAccount // Account original data without any change applied, nil means it was not existent
|
||||
data types.StateAccount // Account data with all mutations applied in the scope of block
|
||||
|
||||
|
|
@ -102,7 +102,6 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s
|
|||
return &stateObject{
|
||||
db: db,
|
||||
address: address,
|
||||
addrHash: crypto.Keccak256Hash(address[:]),
|
||||
origin: origin,
|
||||
data: *acct,
|
||||
originStorage: make(Storage),
|
||||
|
|
@ -112,6 +111,14 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s
|
|||
}
|
||||
}
|
||||
|
||||
func (s *stateObject) addrHash() common.Hash {
|
||||
if s.addressHash == nil {
|
||||
h := crypto.Keccak256Hash(s.address[:])
|
||||
s.addressHash = &h
|
||||
}
|
||||
return *s.addressHash
|
||||
}
|
||||
|
||||
func (s *stateObject) markSelfdestructed() {
|
||||
s.selfDestructed = true
|
||||
}
|
||||
|
|
@ -151,7 +158,7 @@ func (s *stateObject) getPrefetchedTrie() Trie {
|
|||
return nil
|
||||
}
|
||||
// Attempt to retrieve the trie from the prefetcher
|
||||
return s.db.prefetcher.trie(s.addrHash, s.data.Root)
|
||||
return s.db.prefetcher.trie(s.addrHash(), s.data.Root)
|
||||
}
|
||||
|
||||
// GetState retrieves a value associated with the given storage key.
|
||||
|
|
@ -203,7 +210,7 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
|
|||
|
||||
// Schedule the resolved storage slots for prefetching if it's enabled.
|
||||
if s.db.prefetcher != nil && s.data.Root != types.EmptyRootHash {
|
||||
if err = s.db.prefetcher.prefetch(s.addrHash, s.origin.Root, s.address, nil, []common.Hash{key}, true); err != nil {
|
||||
if err = s.db.prefetcher.prefetch(s.addrHash(), s.origin.Root, s.address, nil, []common.Hash{key}, true); err != nil {
|
||||
log.Error("Failed to prefetch storage slot", "addr", s.address, "key", key, "err", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -264,7 +271,7 @@ func (s *stateObject) finalise() {
|
|||
s.pendingStorage[key] = value
|
||||
}
|
||||
if s.db.prefetcher != nil && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
|
||||
if err := s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, nil, slotsToPrefetch, false); err != nil {
|
||||
if err := s.db.prefetcher.prefetch(s.addrHash(), s.data.Root, s.address, nil, slotsToPrefetch, false); err != nil {
|
||||
log.Error("Failed to prefetch slots", "addr", s.address, "slots", len(slotsToPrefetch), "err", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -359,7 +366,7 @@ func (s *stateObject) updateTrie() (Trie, error) {
|
|||
s.db.StorageDeleted.Add(1)
|
||||
}
|
||||
if s.db.prefetcher != nil {
|
||||
s.db.prefetcher.used(s.addrHash, s.data.Root, nil, used)
|
||||
s.db.prefetcher.used(s.addrHash(), s.data.Root, nil, used)
|
||||
}
|
||||
s.uncommittedStorage = make(Storage) // empties the commit markers
|
||||
return tr, nil
|
||||
|
|
@ -491,7 +498,7 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
|
|||
obj := &stateObject{
|
||||
db: db,
|
||||
address: s.address,
|
||||
addrHash: s.addrHash,
|
||||
addressHash: nil,
|
||||
origin: s.origin,
|
||||
data: s.data,
|
||||
code: s.code,
|
||||
|
|
|
|||
|
|
@ -867,13 +867,13 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||
witness := trie.Witness()
|
||||
s.witness.AddState(witness)
|
||||
if s.witnessStats != nil {
|
||||
s.witnessStats.Add(witness, obj.addrHash)
|
||||
s.witnessStats.Add(witness, obj.addrHash())
|
||||
}
|
||||
} else if obj.trie != nil {
|
||||
witness := obj.trie.Witness()
|
||||
s.witness.AddState(witness)
|
||||
if s.witnessStats != nil {
|
||||
s.witnessStats.Add(witness, obj.addrHash)
|
||||
s.witnessStats.Add(witness, obj.addrHash())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -891,13 +891,13 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||
witness := trie.Witness()
|
||||
s.witness.AddState(witness)
|
||||
if s.witnessStats != nil {
|
||||
s.witnessStats.Add(witness, obj.addrHash)
|
||||
s.witnessStats.Add(witness, obj.addrHash())
|
||||
}
|
||||
} else if obj.trie != nil {
|
||||
witness := obj.trie.Witness()
|
||||
s.witness.AddState(witness)
|
||||
if s.witnessStats != nil {
|
||||
s.witnessStats.Add(witness, obj.addrHash)
|
||||
s.witnessStats.Add(witness, obj.addrHash())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1284,7 +1284,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNum
|
|||
return err
|
||||
}
|
||||
lock.Lock()
|
||||
updates[obj.addrHash] = update
|
||||
updates[obj.addrHash()] = update
|
||||
s.StorageCommits = time.Since(start) // overwrite with the longest storage commit runtime
|
||||
lock.Unlock()
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ func NewEIP2930Signer(chainId *big.Int) Signer {
|
|||
// are replay-protected as well as unprotected homestead transactions.
|
||||
// Deprecated: always use the Signer interface type
|
||||
type EIP155Signer struct {
|
||||
chainId, chainIdMul *big.Int
|
||||
chainId *big.Int
|
||||
}
|
||||
|
||||
func NewEIP155Signer(chainId *big.Int) EIP155Signer {
|
||||
|
|
@ -339,7 +339,6 @@ func NewEIP155Signer(chainId *big.Int) EIP155Signer {
|
|||
}
|
||||
return EIP155Signer{
|
||||
chainId: chainId,
|
||||
chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +364,8 @@ func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) {
|
|||
return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId)
|
||||
}
|
||||
V, R, S := tx.RawSignatureValues()
|
||||
V = new(big.Int).Sub(V, s.chainIdMul)
|
||||
V = new(big.Int).Sub(V, s.chainId)
|
||||
V = new(big.Int).Sub(V, s.chainId)
|
||||
V.Sub(V, big8)
|
||||
return recoverPlain(s.Hash(tx), R, S, V, true)
|
||||
}
|
||||
|
|
@ -382,7 +382,8 @@ func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big
|
|||
}
|
||||
if s.chainId.Sign() != 0 {
|
||||
V = big.NewInt(int64(sig[64] + 35))
|
||||
V.Add(V, s.chainIdMul)
|
||||
V.Add(V, s.chainId)
|
||||
V.Add(V, s.chainId)
|
||||
}
|
||||
return R, S, V, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,9 +73,8 @@ type BlockContext struct {
|
|||
type TxContext struct {
|
||||
// Message information
|
||||
Origin common.Address // Provides information for ORIGIN
|
||||
GasPrice *big.Int // Provides information for GASPRICE (and is used to zero the basefee if NoBaseFee is set)
|
||||
GasPrice *uint256.Int // Provides information for GASPRICE (and is used to zero the basefee if NoBaseFee is set)
|
||||
BlobHashes []common.Hash // Provides information for BLOBHASH
|
||||
BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
|
||||
AccessEvents *state.AccessEvents // Capture all state accesses for this tx
|
||||
}
|
||||
|
||||
|
|
@ -125,9 +124,6 @@ type EVM struct {
|
|||
// jumpDests stores results of JUMPDEST analysis.
|
||||
jumpDests JumpDestCache
|
||||
|
||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
||||
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
|
||||
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
}
|
||||
|
|
@ -144,7 +140,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
|||
chainConfig: chainConfig,
|
||||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
||||
jumpDests: newMapJumpDests(),
|
||||
hasher: crypto.NewKeccakState(),
|
||||
}
|
||||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||
|
||||
|
|
@ -618,7 +613,7 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
|
||||
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
|
||||
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
|
||||
inithash := crypto.HashData(evm.hasher, code)
|
||||
inithash := crypto.Keccak256Hash(code)
|
||||
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:])
|
||||
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
|
@ -233,14 +234,12 @@ func opKeccak256(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
offset, size := scope.Stack.pop(), scope.Stack.peek()
|
||||
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
|
||||
|
||||
evm.hasher.Reset()
|
||||
evm.hasher.Write(data)
|
||||
evm.hasher.Read(evm.hasherBuf[:])
|
||||
hash := crypto.Keccak256Hash(data)
|
||||
|
||||
if evm.Config.EnablePreimageRecording {
|
||||
evm.StateDB.AddPreimage(evm.hasherBuf, data)
|
||||
evm.StateDB.AddPreimage(hash, data)
|
||||
}
|
||||
size.SetBytes(evm.hasherBuf[:])
|
||||
size.SetBytes(hash[:])
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
@ -417,8 +416,7 @@ func opExtCodeHash(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
|
||||
func opGasprice(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
||||
v, _ := uint256.FromBig(evm.GasPrice)
|
||||
scope.Stack.push(v)
|
||||
scope.Stack.push(evm.GasPrice.Clone())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ package runtime
|
|||
import (
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func NewEnv(cfg *Config) *vm.EVM {
|
||||
txContext := vm.TxContext{
|
||||
Origin: cfg.Origin,
|
||||
GasPrice: cfg.GasPrice,
|
||||
GasPrice: uint256.MustFromBig(cfg.GasPrice),
|
||||
BlobHashes: cfg.BlobHashes,
|
||||
BlobFeeCap: cfg.BlobFeeCap,
|
||||
}
|
||||
blockContext := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ type vmContext struct {
|
|||
}
|
||||
|
||||
func testCtx() *vmContext {
|
||||
return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1), BaseFee: big.NewInt(0)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
|
||||
return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1), BaseFee: big.NewInt(0)}, txCtx: vm.TxContext{GasPrice: uint256.NewInt(100000)}}
|
||||
}
|
||||
|
||||
func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
|
||||
|
|
@ -63,7 +63,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
|
|||
contract.Code = contractCode
|
||||
}
|
||||
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice}), contract.Caller())
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice.ToBig()}), contract.Caller())
|
||||
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
||||
ret, err := evm.Run(contract, []byte{}, false)
|
||||
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
||||
|
|
@ -186,7 +186,7 @@ func TestHaltBetweenSteps(t *testing.T) {
|
|||
Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
}
|
||||
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: uint256.NewInt(1)})
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
||||
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
|
||||
tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
|
||||
|
|
@ -210,7 +210,7 @@ func TestNoStepExec(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(100)})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: uint256.NewInt(100)})
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
||||
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
|
||||
tracer.OnExit(0, nil, 0, nil, false)
|
||||
|
|
@ -240,7 +240,7 @@ func TestIsPrecompile(t *testing.T) {
|
|||
chaincfg.ByzantiumBlock = big.NewInt(100)
|
||||
chaincfg.IstanbulBlock = big.NewInt(200)
|
||||
chaincfg.BerlinBlock = big.NewInt(300)
|
||||
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
|
||||
txCtx := vm.TxContext{GasPrice: uint256.NewInt(100000)}
|
||||
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil, chaincfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -1375,7 +1375,6 @@ func (err *ConfigCompatError) Error() string {
|
|||
// Rules is a one time interface meaning that it shouldn't be used in between transition
|
||||
// phases.
|
||||
type Rules struct {
|
||||
ChainID *big.Int
|
||||
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
||||
IsEIP2929, IsEIP4762 bool
|
||||
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
||||
|
|
@ -1386,15 +1385,10 @@ type Rules struct {
|
|||
|
||||
// Rules ensures c's ChainID is not nil.
|
||||
func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules {
|
||||
chainID := c.ChainID
|
||||
if chainID == nil {
|
||||
chainID = new(big.Int)
|
||||
}
|
||||
// disallow setting Merge out of order
|
||||
isMerge = isMerge && c.IsLondon(num)
|
||||
isVerkle := isMerge && c.IsVerkle(num, timestamp)
|
||||
return Rules{
|
||||
ChainID: new(big.Int).Set(chainID),
|
||||
IsHomestead: c.IsHomestead(num),
|
||||
IsEIP150: c.IsEIP150(num),
|
||||
IsEIP155: c.IsEIP155(num),
|
||||
|
|
|
|||
Loading…
Reference in a new issue