update statedb
add transient storage
This commit is contained in:
parent
7575a88b03
commit
49f3d43e46
14
journal.go
14
journal.go
@ -122,6 +122,12 @@ type (
|
||||
address *common.Address
|
||||
slot *common.Hash
|
||||
}
|
||||
|
||||
// Changes to the transient storage
|
||||
transientStorageChange struct {
|
||||
account *common.Address
|
||||
key, prevalue common.Hash
|
||||
}
|
||||
)
|
||||
|
||||
func (ch createObjectChange) revert(s *StateDB) {
|
||||
@ -194,6 +200,14 @@ func (ch storageChange) dirtied() *common.Address {
|
||||
return ch.account
|
||||
}
|
||||
|
||||
func (ch transientStorageChange) revert(s *StateDB) {
|
||||
s.setTransientState(*ch.account, ch.key, ch.prevalue)
|
||||
}
|
||||
|
||||
func (ch transientStorageChange) dirtied() *common.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ch refundChange) revert(s *StateDB) {
|
||||
s.refund = ch.prev
|
||||
}
|
||||
|
84
statedb.go
84
statedb.go
@ -11,6 +11,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -77,6 +78,9 @@ type StateDB struct {
|
||||
// Per-transaction access list
|
||||
accessList *accessList
|
||||
|
||||
// Transient storage
|
||||
transientStorage transientStorage
|
||||
|
||||
// Journal of state modifications. This is the backbone of
|
||||
// Snapshot and RevertToSnapshot.
|
||||
journal *journal
|
||||
@ -100,6 +104,7 @@ func New(blockHash common.Hash, db StateDatabase) (*StateDB, error) {
|
||||
preimages: make(map[common.Hash][]byte),
|
||||
journal: newJournal(),
|
||||
accessList: newAccessList(),
|
||||
transientStorage: newTransientStorage(),
|
||||
hasher: crypto.NewKeccakState(),
|
||||
}
|
||||
return sdb, nil
|
||||
@ -307,6 +312,33 @@ func (s *StateDB) Suicide(addr common.Address) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// SetTransientState sets transient storage for a given account. It
|
||||
// adds the change to the journal so that it can be rolled back
|
||||
// to its previous value if there is a revert.
|
||||
func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash) {
|
||||
prev := s.GetTransientState(addr, key)
|
||||
if prev == value {
|
||||
return
|
||||
}
|
||||
s.journal.append(transientStorageChange{
|
||||
account: &addr,
|
||||
key: key,
|
||||
prevalue: prev,
|
||||
})
|
||||
s.setTransientState(addr, key, value)
|
||||
}
|
||||
|
||||
// setTransientState is a lower level setter for transient storage. It
|
||||
// is called during a revert to prevent modifications to the journal.
|
||||
func (s *StateDB) setTransientState(addr common.Address, key, value common.Hash) {
|
||||
s.transientStorage.Set(addr, key, value)
|
||||
}
|
||||
|
||||
// GetTransientState gets transient storage for a given account.
|
||||
func (s *StateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
|
||||
return s.transientStorage.Get(addr, key)
|
||||
}
|
||||
|
||||
//
|
||||
// Setting, updating & deleting state object methods.
|
||||
//
|
||||
@ -389,8 +421,8 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
|
||||
// CreateAccount is called during the EVM CREATE operation. The situation might arise that
|
||||
// a contract does the following:
|
||||
//
|
||||
// 1. sends funds to sha(account ++ (nonce + 1))
|
||||
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
|
||||
// 1. sends funds to sha(account ++ (nonce + 1))
|
||||
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
|
||||
//
|
||||
// Carrying over the balance ensures that Ether doesn't disappear.
|
||||
func (s *StateDB) CreateAccount(addr common.Address) {
|
||||
@ -437,33 +469,45 @@ func (s *StateDB) GetRefund() uint64 {
|
||||
return s.refund
|
||||
}
|
||||
|
||||
// PrepareAccessList handles the preparatory steps for executing a state transition with
|
||||
// regards to both EIP-2929 and EIP-2930:
|
||||
// Prepare handles the preparatory steps for executing a state transition with.
|
||||
// This method must be invoked before state transition.
|
||||
//
|
||||
// Berlin fork:
|
||||
// - Add sender to access list (2929)
|
||||
// - Add destination to access list (2929)
|
||||
// - Add precompiles to access list (2929)
|
||||
// - Add the contents of the optional tx access list (2930)
|
||||
//
|
||||
// This method should only be called if Berlin/2929+2930 is applicable at the current number.
|
||||
func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) {
|
||||
// Clear out any leftover from previous executions
|
||||
s.accessList = newAccessList()
|
||||
// Potential EIPs:
|
||||
// - Reset access list (Berlin)
|
||||
// - Add coinbase to access list (EIP-3651)
|
||||
// - Reset transient storage (EIP-1153)
|
||||
func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) {
|
||||
if rules.IsBerlin {
|
||||
// Clear out any leftover from previous executions
|
||||
al := newAccessList()
|
||||
s.accessList = al
|
||||
|
||||
s.AddAddressToAccessList(sender)
|
||||
if dst != nil {
|
||||
s.AddAddressToAccessList(*dst)
|
||||
// If it's a create-tx, the destination will be added inside evm.create
|
||||
}
|
||||
for _, addr := range precompiles {
|
||||
s.AddAddressToAccessList(addr)
|
||||
}
|
||||
for _, el := range list {
|
||||
s.AddAddressToAccessList(el.Address)
|
||||
for _, key := range el.StorageKeys {
|
||||
s.AddSlotToAccessList(el.Address, key)
|
||||
al.AddAddress(sender)
|
||||
if dst != nil {
|
||||
al.AddAddress(*dst)
|
||||
// If it's a create-tx, the destination will be added inside evm.create
|
||||
}
|
||||
for _, addr := range precompiles {
|
||||
al.AddAddress(addr)
|
||||
}
|
||||
for _, el := range list {
|
||||
al.AddAddress(el.Address)
|
||||
for _, key := range el.StorageKeys {
|
||||
al.AddSlot(el.Address, key)
|
||||
}
|
||||
}
|
||||
if rules.IsShanghai { // EIP-3651: warm coinbase
|
||||
al.AddAddress(coinbase)
|
||||
}
|
||||
}
|
||||
// Reset transient storage at the beginning of transaction execution
|
||||
s.transientStorage = newTransientStorage()
|
||||
}
|
||||
|
||||
// AddAddressToAccessList adds the given address to the access list
|
||||
|
55
transient_storage.go
Normal file
55
transient_storage.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2022 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 ipld_eth_statedb
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// transientStorage is a representation of EIP-1153 "Transient Storage".
|
||||
type transientStorage map[common.Address]Storage
|
||||
|
||||
// newTransientStorage creates a new instance of a transientStorage.
|
||||
func newTransientStorage() transientStorage {
|
||||
return make(transientStorage)
|
||||
}
|
||||
|
||||
// Set sets the transient-storage `value` for `key` at the given `addr`.
|
||||
func (t transientStorage) Set(addr common.Address, key, value common.Hash) {
|
||||
if _, ok := t[addr]; !ok {
|
||||
t[addr] = make(Storage)
|
||||
}
|
||||
t[addr][key] = value
|
||||
}
|
||||
|
||||
// Get gets the transient storage for `key` at the given `addr`.
|
||||
func (t transientStorage) Get(addr common.Address, key common.Hash) common.Hash {
|
||||
val, ok := t[addr]
|
||||
if !ok {
|
||||
return common.Hash{}
|
||||
}
|
||||
return val[key]
|
||||
}
|
||||
|
||||
// Copy does a deep copy of the transientStorage
|
||||
func (t transientStorage) Copy() transientStorage {
|
||||
storage := make(transientStorage)
|
||||
for key, value := range t {
|
||||
storage[key] = value.Copy()
|
||||
}
|
||||
return storage
|
||||
}
|
Loading…
Reference in New Issue
Block a user