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
|
address *common.Address
|
||||||
slot *common.Hash
|
slot *common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Changes to the transient storage
|
||||||
|
transientStorageChange struct {
|
||||||
|
account *common.Address
|
||||||
|
key, prevalue common.Hash
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ch createObjectChange) revert(s *StateDB) {
|
func (ch createObjectChange) revert(s *StateDB) {
|
||||||
@ -194,6 +200,14 @@ func (ch storageChange) dirtied() *common.Address {
|
|||||||
return ch.account
|
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) {
|
func (ch refundChange) revert(s *StateDB) {
|
||||||
s.refund = ch.prev
|
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/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -77,6 +78,9 @@ type StateDB struct {
|
|||||||
// Per-transaction access list
|
// Per-transaction access list
|
||||||
accessList *accessList
|
accessList *accessList
|
||||||
|
|
||||||
|
// Transient storage
|
||||||
|
transientStorage transientStorage
|
||||||
|
|
||||||
// Journal of state modifications. This is the backbone of
|
// Journal of state modifications. This is the backbone of
|
||||||
// Snapshot and RevertToSnapshot.
|
// Snapshot and RevertToSnapshot.
|
||||||
journal *journal
|
journal *journal
|
||||||
@ -100,6 +104,7 @@ func New(blockHash common.Hash, db StateDatabase) (*StateDB, error) {
|
|||||||
preimages: make(map[common.Hash][]byte),
|
preimages: make(map[common.Hash][]byte),
|
||||||
journal: newJournal(),
|
journal: newJournal(),
|
||||||
accessList: newAccessList(),
|
accessList: newAccessList(),
|
||||||
|
transientStorage: newTransientStorage(),
|
||||||
hasher: crypto.NewKeccakState(),
|
hasher: crypto.NewKeccakState(),
|
||||||
}
|
}
|
||||||
return sdb, nil
|
return sdb, nil
|
||||||
@ -307,6 +312,33 @@ func (s *StateDB) Suicide(addr common.Address) bool {
|
|||||||
return true
|
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.
|
// 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
|
// CreateAccount is called during the EVM CREATE operation. The situation might arise that
|
||||||
// a contract does the following:
|
// a contract does the following:
|
||||||
//
|
//
|
||||||
// 1. sends funds to sha(account ++ (nonce + 1))
|
// 1. sends funds to sha(account ++ (nonce + 1))
|
||||||
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 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.
|
// Carrying over the balance ensures that Ether doesn't disappear.
|
||||||
func (s *StateDB) CreateAccount(addr common.Address) {
|
func (s *StateDB) CreateAccount(addr common.Address) {
|
||||||
@ -437,33 +469,45 @@ func (s *StateDB) GetRefund() uint64 {
|
|||||||
return s.refund
|
return s.refund
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareAccessList handles the preparatory steps for executing a state transition with
|
// Prepare handles the preparatory steps for executing a state transition with.
|
||||||
// regards to both EIP-2929 and EIP-2930:
|
// This method must be invoked before state transition.
|
||||||
//
|
//
|
||||||
|
// Berlin fork:
|
||||||
// - Add sender to access list (2929)
|
// - Add sender to access list (2929)
|
||||||
// - Add destination to access list (2929)
|
// - Add destination to access list (2929)
|
||||||
// - Add precompiles to access list (2929)
|
// - Add precompiles to access list (2929)
|
||||||
// - Add the contents of the optional tx access list (2930)
|
// - 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.
|
// Potential EIPs:
|
||||||
func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) {
|
// - Reset access list (Berlin)
|
||||||
// Clear out any leftover from previous executions
|
// - Add coinbase to access list (EIP-3651)
|
||||||
s.accessList = newAccessList()
|
// - 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)
|
al.AddAddress(sender)
|
||||||
if dst != nil {
|
if dst != nil {
|
||||||
s.AddAddressToAccessList(*dst)
|
al.AddAddress(*dst)
|
||||||
// If it's a create-tx, the destination will be added inside evm.create
|
// If it's a create-tx, the destination will be added inside evm.create
|
||||||
}
|
}
|
||||||
for _, addr := range precompiles {
|
for _, addr := range precompiles {
|
||||||
s.AddAddressToAccessList(addr)
|
al.AddAddress(addr)
|
||||||
}
|
}
|
||||||
for _, el := range list {
|
for _, el := range list {
|
||||||
s.AddAddressToAccessList(el.Address)
|
al.AddAddress(el.Address)
|
||||||
for _, key := range el.StorageKeys {
|
for _, key := range el.StorageKeys {
|
||||||
s.AddSlotToAccessList(el.Address, key)
|
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
|
// 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