mirror of
https://github.com/luxfi/coreth.git
synced 2026-10-30 17:00:51 +00:00
- Update github.com/luxfi/vm v1.0.1 → v1.0.2 - Remove local replace directive for vm - Use published package versions for reproducible builds
170 lines
6.5 KiB
Go
170 lines
6.5 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package extstate
|
|
|
|
import (
|
|
"math/big"
|
|
|
|
"github.com/holiman/uint256"
|
|
corethparams "github.com/luxfi/coreth/params"
|
|
"github.com/luxfi/coreth/predicate"
|
|
"github.com/luxfi/geth/common"
|
|
"github.com/luxfi/geth/core/state"
|
|
"github.com/luxfi/geth/core/stateconf"
|
|
"github.com/luxfi/geth/core/tracing"
|
|
"github.com/luxfi/geth/core/types"
|
|
"github.com/luxfi/geth/params"
|
|
)
|
|
|
|
type StateDB struct {
|
|
*state.StateDB
|
|
|
|
// Ordered storage slots to be used in predicate verification as set in the tx access list.
|
|
// Only set in [StateDB.Prepare], and un-modified through execution.
|
|
predicateStorageSlots map[common.Address][][]byte
|
|
}
|
|
|
|
// New creates a new [StateDB] with the given [state.StateDB], wrapping it with
|
|
// additional functionality.
|
|
func New(vm *state.StateDB) *StateDB {
|
|
return &StateDB{
|
|
StateDB: vm,
|
|
predicateStorageSlots: make(map[common.Address][][]byte),
|
|
}
|
|
}
|
|
|
|
func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) {
|
|
rulesExtra := corethparams.GetRulesExtra(rules)
|
|
s.predicateStorageSlots = predicate.PreparePredicateStorageSlots(rulesExtra, list)
|
|
s.StateDB.Prepare(rules, sender, coinbase, dst, precompiles, list)
|
|
}
|
|
|
|
// GetPredicateStorageSlots returns the storage slots associated with the address, index pair.
|
|
// A list of access tuples can be included within transaction types post EIP-2930. The address
|
|
// is declared directly on the access tuple and the index is the i'th occurrence of an access
|
|
// tuple with the specified address.
|
|
//
|
|
// Ex. AccessList[[AddrA, Predicate1], [AddrB, Predicate2], [AddrA, Predicate3]]
|
|
// In this case, the caller could retrieve predicates 1-3 with the following calls:
|
|
// GetPredicateStorageSlots(AddrA, 0) -> Predicate1
|
|
// GetPredicateStorageSlots(AddrB, 0) -> Predicate2
|
|
// GetPredicateStorageSlots(AddrA, 1) -> Predicate3
|
|
func (s *StateDB) GetPredicateStorageSlots(address common.Address, index int) ([]byte, bool) {
|
|
predicates, exists := s.predicateStorageSlots[address]
|
|
if !exists || index >= len(predicates) {
|
|
return nil, false
|
|
}
|
|
return predicates[index], true
|
|
}
|
|
|
|
// Retrieve the balance from the given address or 0 if object not found
|
|
func (s *StateDB) GetBalanceMultiCoin(addr common.Address, coinID common.Hash) *big.Int {
|
|
normalizeCoinID(&coinID)
|
|
return s.GetState(addr, coinID).Big()
|
|
}
|
|
|
|
// AddBalanceMultiCoin adds amount to the account associated with addr.
|
|
func (s *StateDB) AddBalanceMultiCoin(addr common.Address, coinID common.Hash, amount *big.Int) {
|
|
if amount.Sign() == 0 {
|
|
s.StateDB.AddBalance(addr, new(uint256.Int), tracing.BalanceChangeUnspecified) // used to cause touch
|
|
return
|
|
}
|
|
|
|
// Multicoin functionality has been removed
|
|
|
|
newAmount := new(big.Int).Add(s.GetBalanceMultiCoin(addr, coinID), amount)
|
|
normalizeCoinID(&coinID)
|
|
s.SetState(addr, coinID, common.BigToHash(newAmount))
|
|
}
|
|
|
|
// SubBalance subtracts amount from the account associated with addr.
|
|
func (s *StateDB) SubBalanceMultiCoin(addr common.Address, coinID common.Hash, amount *big.Int) {
|
|
if amount.Sign() == 0 {
|
|
return
|
|
}
|
|
// Note: It's not needed to set the IsMultiCoin (extras) flag here, as this
|
|
// call would always be preceded by a call to AddBalanceMultiCoin, which would
|
|
// set the extra flag. Seems we should remove the redundant code.
|
|
// Multicoin functionality has been removed
|
|
newAmount := new(big.Int).Sub(s.GetBalanceMultiCoin(addr, coinID), amount)
|
|
normalizeCoinID(&coinID)
|
|
s.SetState(addr, coinID, common.BigToHash(newAmount))
|
|
}
|
|
|
|
// normalizeStateKey sets the 0th bit of the first byte in `key` to 0.
|
|
// This partitions normal state storage from multicoin storage.
|
|
func normalizeStateKey(key *common.Hash) {
|
|
key[0] &^= 0x01
|
|
}
|
|
|
|
// normalizeCoinID sets the 0th bit of the first byte in `coinID` to 1.
|
|
// This partitions multicoin storage from normal state storage.
|
|
func normalizeCoinID(coinID *common.Hash) {
|
|
coinID[0] |= 0x01
|
|
}
|
|
|
|
// The following methods are forwarded to the embedded state.StateDB and are provided
|
|
// to satisfy vm.StateDB interface requirements.
|
|
|
|
// AddBalance wraps the underlying StateDB's AddBalance.
|
|
func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
|
|
return s.StateDB.AddBalance(addr, amount, reason)
|
|
}
|
|
|
|
// SubBalance wraps the underlying StateDB's SubBalance.
|
|
func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
|
|
return s.StateDB.SubBalance(addr, amount, reason)
|
|
}
|
|
|
|
// SetNonce wraps the underlying StateDB's SetNonce.
|
|
func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.NonceChangeReason) {
|
|
s.StateDB.SetNonce(addr, nonce, reason)
|
|
}
|
|
|
|
// SetState wraps the underlying StateDB's SetState.
|
|
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) common.Hash {
|
|
return s.StateDB.SetState(addr, key, value)
|
|
}
|
|
|
|
// SetCode wraps the underlying StateDB's SetCode.
|
|
func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeChangeReason) []byte {
|
|
return s.StateDB.SetCode(addr, code, reason)
|
|
}
|
|
|
|
// The following methods provide simplified signatures for use by precompile contracts.
|
|
// These are used by contract.StateDB interface implementations.
|
|
|
|
// AddBalanceSimple adds balance without returning the result.
|
|
func (s *StateDB) AddBalanceSimple(addr common.Address, amount *uint256.Int) {
|
|
s.StateDB.AddBalance(addr, amount, tracing.BalanceChangeUnspecified)
|
|
}
|
|
|
|
// SetNonceSimple sets nonce without specifying a reason.
|
|
func (s *StateDB) SetNonceSimple(addr common.Address, nonce uint64) {
|
|
s.StateDB.SetNonce(addr, nonce, tracing.NonceChangeUnspecified)
|
|
}
|
|
|
|
// GetStateWithOptions wraps GetState accepting optional stateconf options
|
|
// for compatibility with the contract.StateDB interface.
|
|
func (s *StateDB) GetStateWithOptions(addr common.Address, hash common.Hash, _ ...stateconf.StateDBStateOption) common.Hash {
|
|
return s.StateDB.GetState(addr, hash)
|
|
}
|
|
|
|
// SetStateWithOptions wraps SetState accepting optional stateconf options
|
|
// for compatibility with the contract.StateDB interface.
|
|
func (s *StateDB) SetStateWithOptions(addr common.Address, key, value common.Hash, _ ...stateconf.StateDBStateOption) {
|
|
s.StateDB.SetState(addr, key, value)
|
|
}
|
|
|
|
// TxHash returns the current transaction hash.
|
|
// This is required by contract.StateDB interface.
|
|
func (s *StateDB) TxHash() common.Hash {
|
|
// Use the transaction hash from the logs if available
|
|
logs := s.StateDB.Logs()
|
|
if len(logs) > 0 {
|
|
return logs[0].TxHash
|
|
}
|
|
return common.Hash{}
|
|
}
|