mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
core, core/state, core/vm: removal of exported account getters
Removed exported statedb object accessors, reducing the chance for nasty bugs to creep in. It's also ugly and unnecessary to have these methods.
This commit is contained in:
parent
94334c233e
commit
9f1bdae638
22 changed files with 168 additions and 200 deletions
|
|
@ -29,7 +29,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/core/vm/runtime"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
|
|
@ -115,9 +114,13 @@ func run(ctx *cli.Context) error {
|
|||
glog.SetToStderr(true)
|
||||
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))
|
||||
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
sender := statedb.CreateAccount(common.StringToAddress("sender"))
|
||||
var (
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
statedb, _ = state.New(common.Hash{}, db)
|
||||
address = common.StringToAddress("sender")
|
||||
sender = vm.Reference(address)
|
||||
)
|
||||
statedb.CreateAccount(common.StringToAddress("sender"))
|
||||
|
||||
logger := vm.NewStructLogger(nil)
|
||||
|
||||
|
|
@ -166,10 +169,11 @@ func run(ctx *cli.Context) error {
|
|||
},
|
||||
})
|
||||
} else {
|
||||
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
|
||||
receiver.SetCode(crypto.Keccak256Hash(code), code)
|
||||
receiverAddress := common.StringToAddress("receiver")
|
||||
statedb.CreateAccount(receiverAddress)
|
||||
statedb.SetCode(receiverAddress, code)
|
||||
|
||||
ret, err = runtime.Call(receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{
|
||||
ret, err = runtime.Call(receiverAddress, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{
|
||||
Origin: sender.Address(),
|
||||
State: statedb,
|
||||
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(),
|
||||
|
|
|
|||
|
|
@ -214,7 +214,8 @@ func (self *BlockChain) loadLastState() error {
|
|||
return err
|
||||
}
|
||||
self.stateCache = statedb
|
||||
self.stateCache.GetAccount(common.Address{})
|
||||
// XXX Reviewers: what's this for? I need to know if I need to backport this somehow
|
||||
//self.stateCache.GetAccount(common.Address{})
|
||||
|
||||
// Issue a status log for the user
|
||||
headerTd := self.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64())
|
||||
|
|
|
|||
10
core/dao.go
10
core/dao.go
|
|
@ -62,13 +62,13 @@ func ValidateDAOHeaderExtraData(config *params.ChainConfig, header *types.Header
|
|||
// contract.
|
||||
func ApplyDAOHardFork(statedb *state.StateDB) {
|
||||
// Retrieve the contract to refund balances into
|
||||
refund := statedb.GetOrNewStateObject(params.DAORefundContract)
|
||||
if !statedb.Exist(params.DAORefundContract) {
|
||||
statedb.CreateAccount(params.DAORefundContract)
|
||||
}
|
||||
|
||||
// Move every DAO account and extra-balance account funds into the refund contract
|
||||
for _, addr := range params.DAODrainList {
|
||||
if account := statedb.GetStateObject(addr); account != nil {
|
||||
refund.AddBalance(account.Balance())
|
||||
account.SetBalance(new(big.Int))
|
||||
}
|
||||
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr))
|
||||
statedb.SetBalance(addr, new(big.Int))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ type (
|
|||
account *common.Address
|
||||
}
|
||||
resetObjectChange struct {
|
||||
prev *StateObject
|
||||
prev *stateObject
|
||||
}
|
||||
suicideChange struct {
|
||||
account *common.Address
|
||||
|
|
@ -86,7 +86,7 @@ func (ch resetObjectChange) undo(s *StateDB) {
|
|||
}
|
||||
|
||||
func (ch suicideChange) undo(s *StateDB) {
|
||||
obj := s.GetStateObject(*ch.account)
|
||||
obj := s.getStateObject(*ch.account)
|
||||
if obj != nil {
|
||||
obj.suicided = ch.prev
|
||||
obj.setBalance(ch.prevbalance)
|
||||
|
|
@ -103,19 +103,19 @@ func (ch touchChange) undo(s *StateDB) {
|
|||
}
|
||||
|
||||
func (ch balanceChange) undo(s *StateDB) {
|
||||
s.GetStateObject(*ch.account).setBalance(ch.prev)
|
||||
s.getStateObject(*ch.account).setBalance(ch.prev)
|
||||
}
|
||||
|
||||
func (ch nonceChange) undo(s *StateDB) {
|
||||
s.GetStateObject(*ch.account).setNonce(ch.prev)
|
||||
s.getStateObject(*ch.account).setNonce(ch.prev)
|
||||
}
|
||||
|
||||
func (ch codeChange) undo(s *StateDB) {
|
||||
s.GetStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
|
||||
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
|
||||
}
|
||||
|
||||
func (ch storageChange) undo(s *StateDB) {
|
||||
s.GetStateObject(*ch.account).setState(ch.key, ch.prevalue)
|
||||
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
|
||||
}
|
||||
|
||||
func (ch refundChange) undo(s *StateDB) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
)
|
||||
|
||||
type account struct {
|
||||
stateObject *StateObject
|
||||
stateObject *stateObject
|
||||
nstart uint64
|
||||
nonces []bool
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ func (ms *ManagedState) getAccount(addr common.Address) *account {
|
|||
} else {
|
||||
// Always make sure the state account nonce isn't actually higher
|
||||
// than the tracked one.
|
||||
so := ms.StateDB.GetStateObject(addr)
|
||||
so := ms.StateDB.getStateObject(addr)
|
||||
if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() {
|
||||
ms.accounts[addr] = newAccount(so)
|
||||
}
|
||||
|
|
@ -138,6 +138,6 @@ func (ms *ManagedState) getAccount(addr common.Address) *account {
|
|||
return ms.accounts[addr]
|
||||
}
|
||||
|
||||
func newAccount(so *StateObject) *account {
|
||||
func newAccount(so *stateObject) *account {
|
||||
return &account{so, so.Nonce(), nil}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ func create() (*ManagedState, *account) {
|
|||
statedb, _ := New(common.Hash{}, db)
|
||||
ms := ManageState(statedb)
|
||||
ms.StateDB.SetNonce(addr, 100)
|
||||
ms.accounts[addr] = newAccount(ms.StateDB.GetStateObject(addr))
|
||||
ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr))
|
||||
return ms, ms.accounts[addr]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,13 +57,13 @@ func (self Storage) Copy() Storage {
|
|||
return cpy
|
||||
}
|
||||
|
||||
// StateObject represents an Ethereum account which is being modified.
|
||||
// stateObject represents an Ethereum account which is being modified.
|
||||
//
|
||||
// The usage pattern is as follows:
|
||||
// First you need to obtain a state object.
|
||||
// Account values can be accessed and modified through the object.
|
||||
// Finally, call CommitTrie to write the modified storage trie into a database.
|
||||
type StateObject struct {
|
||||
type stateObject struct {
|
||||
address common.Address // Ethereum address of this account
|
||||
data Account
|
||||
db *StateDB
|
||||
|
|
@ -93,7 +93,7 @@ type StateObject struct {
|
|||
}
|
||||
|
||||
// empty returns whether the account is considered empty.
|
||||
func (s *StateObject) empty() bool {
|
||||
func (s *stateObject) empty() bool {
|
||||
return s.data.Nonce == 0 && s.data.Balance.BitLen() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash)
|
||||
}
|
||||
|
||||
|
|
@ -107,29 +107,29 @@ type Account struct {
|
|||
}
|
||||
|
||||
// newObject creates a state object.
|
||||
func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *StateObject {
|
||||
func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject {
|
||||
if data.Balance == nil {
|
||||
data.Balance = new(big.Int)
|
||||
}
|
||||
if data.CodeHash == nil {
|
||||
data.CodeHash = emptyCodeHash
|
||||
}
|
||||
return &StateObject{db: db, address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty}
|
||||
return &stateObject{db: db, address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty}
|
||||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *StateObject) EncodeRLP(w io.Writer) error {
|
||||
func (c *stateObject) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *StateObject) setError(err error) {
|
||||
func (self *stateObject) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StateObject) markSuicided() {
|
||||
func (self *stateObject) markSuicided() {
|
||||
self.suicided = true
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Address())
|
||||
|
|
@ -140,7 +140,7 @@ func (self *StateObject) markSuicided() {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *StateObject) touch() {
|
||||
func (c *stateObject) touch() {
|
||||
c.db.journal = append(c.db.journal, touchChange{
|
||||
account: &c.address,
|
||||
prev: c.touched,
|
||||
|
|
@ -152,7 +152,7 @@ func (c *StateObject) touch() {
|
|||
c.touched = true
|
||||
}
|
||||
|
||||
func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
|
||||
func (c *stateObject) getTrie(db trie.Database) *trie.SecureTrie {
|
||||
if c.trie == nil {
|
||||
var err error
|
||||
c.trie, err = trie.NewSecure(c.data.Root, db, 0)
|
||||
|
|
@ -165,7 +165,7 @@ func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
|
|||
}
|
||||
|
||||
// GetState returns a value in account storage.
|
||||
func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash {
|
||||
func (self *stateObject) GetState(db trie.Database, key common.Hash) common.Hash {
|
||||
value, exists := self.cachedStorage[key]
|
||||
if exists {
|
||||
return value
|
||||
|
|
@ -185,7 +185,7 @@ func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash
|
|||
}
|
||||
|
||||
// SetState updates a value in account storage.
|
||||
func (self *StateObject) SetState(db trie.Database, key, value common.Hash) {
|
||||
func (self *stateObject) SetState(db trie.Database, key, value common.Hash) {
|
||||
self.db.journal = append(self.db.journal, storageChange{
|
||||
account: &self.address,
|
||||
key: key,
|
||||
|
|
@ -194,7 +194,7 @@ func (self *StateObject) SetState(db trie.Database, key, value common.Hash) {
|
|||
self.setState(key, value)
|
||||
}
|
||||
|
||||
func (self *StateObject) setState(key, value common.Hash) {
|
||||
func (self *stateObject) setState(key, value common.Hash) {
|
||||
self.cachedStorage[key] = value
|
||||
self.dirtyStorage[key] = value
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ func (self *StateObject) setState(key, value common.Hash) {
|
|||
}
|
||||
|
||||
// updateTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *StateObject) updateTrie(db trie.Database) {
|
||||
func (self *stateObject) updateTrie(db trie.Database) {
|
||||
tr := self.getTrie(db)
|
||||
for key, value := range self.dirtyStorage {
|
||||
delete(self.dirtyStorage, key)
|
||||
|
|
@ -220,14 +220,14 @@ func (self *StateObject) updateTrie(db trie.Database) {
|
|||
}
|
||||
|
||||
// UpdateRoot sets the trie root to the current root hash of
|
||||
func (self *StateObject) updateRoot(db trie.Database) {
|
||||
func (self *stateObject) updateRoot(db trie.Database) {
|
||||
self.updateTrie(db)
|
||||
self.data.Root = self.trie.Hash()
|
||||
}
|
||||
|
||||
// CommitTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) error {
|
||||
func (self *stateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
|
|
@ -241,7 +241,7 @@ func (self *StateObject) CommitTrie(db trie.Database, dbw trie.DatabaseWriter) e
|
|||
|
||||
// AddBalance removes amount from c's balance.
|
||||
// It is used to add funds to the destination account of a transfer.
|
||||
func (c *StateObject) AddBalance(amount *big.Int) {
|
||||
func (c *stateObject) AddBalance(amount *big.Int) {
|
||||
// EIP158: We must check emptiness for the objects such that the account
|
||||
// clearing (0,0,0 objects) can take effect.
|
||||
if amount.Cmp(common.Big0) == 0 {
|
||||
|
|
@ -260,7 +260,7 @@ func (c *StateObject) AddBalance(amount *big.Int) {
|
|||
|
||||
// SubBalance removes amount from c's balance.
|
||||
// It is used to remove funds from the origin account of a transfer.
|
||||
func (c *StateObject) SubBalance(amount *big.Int) {
|
||||
func (c *stateObject) SubBalance(amount *big.Int) {
|
||||
if amount.Cmp(common.Big0) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ func (c *StateObject) SubBalance(amount *big.Int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *StateObject) SetBalance(amount *big.Int) {
|
||||
func (self *stateObject) SetBalance(amount *big.Int) {
|
||||
self.db.journal = append(self.db.journal, balanceChange{
|
||||
account: &self.address,
|
||||
prev: new(big.Int).Set(self.data.Balance),
|
||||
|
|
@ -279,7 +279,7 @@ func (self *StateObject) SetBalance(amount *big.Int) {
|
|||
self.setBalance(amount)
|
||||
}
|
||||
|
||||
func (self *StateObject) setBalance(amount *big.Int) {
|
||||
func (self *stateObject) setBalance(amount *big.Int) {
|
||||
self.data.Balance = amount
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Address())
|
||||
|
|
@ -288,9 +288,9 @@ func (self *StateObject) setBalance(amount *big.Int) {
|
|||
}
|
||||
|
||||
// Return the gas back to the origin. Used by the Virtual machine or Closures
|
||||
func (c *StateObject) ReturnGas(gas *big.Int) {}
|
||||
func (c *stateObject) ReturnGas(gas *big.Int) {}
|
||||
|
||||
func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject {
|
||||
func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject {
|
||||
stateObject := newObject(db, self.address, self.data, onDirty)
|
||||
stateObject.trie = self.trie
|
||||
stateObject.code = self.code
|
||||
|
|
@ -307,12 +307,12 @@ func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)
|
|||
//
|
||||
|
||||
// Returns the address of the contract/account
|
||||
func (c *StateObject) Address() common.Address {
|
||||
func (c *stateObject) Address() common.Address {
|
||||
return c.address
|
||||
}
|
||||
|
||||
// Code returns the contract code associated with this object, if any.
|
||||
func (self *StateObject) Code(db trie.Database) []byte {
|
||||
func (self *stateObject) Code(db trie.Database) []byte {
|
||||
if self.code != nil {
|
||||
return self.code
|
||||
}
|
||||
|
|
@ -327,7 +327,7 @@ func (self *StateObject) Code(db trie.Database) []byte {
|
|||
return code
|
||||
}
|
||||
|
||||
func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
|
||||
func (self *stateObject) SetCode(codeHash common.Hash, code []byte) {
|
||||
prevcode := self.Code(self.db.db)
|
||||
self.db.journal = append(self.db.journal, codeChange{
|
||||
account: &self.address,
|
||||
|
|
@ -337,7 +337,7 @@ func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
|
|||
self.setCode(codeHash, code)
|
||||
}
|
||||
|
||||
func (self *StateObject) setCode(codeHash common.Hash, code []byte) {
|
||||
func (self *stateObject) setCode(codeHash common.Hash, code []byte) {
|
||||
self.code = code
|
||||
self.data.CodeHash = codeHash[:]
|
||||
self.dirtyCode = true
|
||||
|
|
@ -347,7 +347,7 @@ func (self *StateObject) setCode(codeHash common.Hash, code []byte) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *StateObject) SetNonce(nonce uint64) {
|
||||
func (self *stateObject) SetNonce(nonce uint64) {
|
||||
self.db.journal = append(self.db.journal, nonceChange{
|
||||
account: &self.address,
|
||||
prev: self.data.Nonce,
|
||||
|
|
@ -355,7 +355,7 @@ func (self *StateObject) SetNonce(nonce uint64) {
|
|||
self.setNonce(nonce)
|
||||
}
|
||||
|
||||
func (self *StateObject) setNonce(nonce uint64) {
|
||||
func (self *stateObject) setNonce(nonce uint64) {
|
||||
self.data.Nonce = nonce
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Address())
|
||||
|
|
@ -363,26 +363,26 @@ func (self *StateObject) setNonce(nonce uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *StateObject) CodeHash() []byte {
|
||||
func (self *stateObject) CodeHash() []byte {
|
||||
return self.data.CodeHash
|
||||
}
|
||||
|
||||
func (self *StateObject) Balance() *big.Int {
|
||||
func (self *stateObject) Balance() *big.Int {
|
||||
return self.data.Balance
|
||||
}
|
||||
|
||||
func (self *StateObject) Nonce() uint64 {
|
||||
func (self *stateObject) Nonce() uint64 {
|
||||
return self.data.Nonce
|
||||
}
|
||||
|
||||
// Never called, but must be present to allow StateObject to be used
|
||||
// Never called, but must be present to allow stateObject to be used
|
||||
// as a vm.Account interface that also satisfies the vm.ContractRef
|
||||
// interface. Interfaces are awesome.
|
||||
func (self *StateObject) Value() *big.Int {
|
||||
panic("Value on StateObject should never be called")
|
||||
func (self *stateObject) Value() *big.Int {
|
||||
panic("Value on stateObject should never be called")
|
||||
}
|
||||
|
||||
func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
|
||||
func (self *stateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
|
||||
// When iterating over the storage check the cache first
|
||||
for h, value := range self.cachedStorage {
|
||||
cb(h, value)
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
state.SetState(stateobjaddr1, storageaddr, data1)
|
||||
|
||||
// db, trie are already non-empty values
|
||||
so0 := state.GetStateObject(stateobjaddr0)
|
||||
so0 := state.getStateObject(stateobjaddr0)
|
||||
so0.SetBalance(big.NewInt(42))
|
||||
so0.SetNonce(43)
|
||||
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
|
||||
|
|
@ -164,7 +164,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
state.Reset(root)
|
||||
|
||||
// and one with deleted == true
|
||||
so1 := state.GetStateObject(stateobjaddr1)
|
||||
so1 := state.getStateObject(stateobjaddr1)
|
||||
so1.SetBalance(big.NewInt(52))
|
||||
so1.SetNonce(53)
|
||||
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
|
||||
|
|
@ -172,7 +172,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
so1.deleted = true
|
||||
state.setStateObject(so1)
|
||||
|
||||
so1 = state.GetStateObject(stateobjaddr1)
|
||||
so1 = state.getStateObject(stateobjaddr1)
|
||||
if so1 != nil {
|
||||
t.Fatalf("deleted object not nil when getting")
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
snapshot := state.Snapshot()
|
||||
state.RevertToSnapshot(snapshot)
|
||||
|
||||
so0Restored := state.GetStateObject(stateobjaddr0)
|
||||
so0Restored := state.getStateObject(stateobjaddr0)
|
||||
// Update lazily-loaded values before comparing.
|
||||
so0Restored.GetState(db, storageaddr)
|
||||
so0Restored.Code(db)
|
||||
|
|
@ -188,13 +188,13 @@ func TestSnapshot2(t *testing.T) {
|
|||
compareStateObjects(so0Restored, so0, t)
|
||||
|
||||
// deleted should be nil, both before and after restore of state copy
|
||||
so1Restored := state.GetStateObject(stateobjaddr1)
|
||||
so1Restored := state.getStateObject(stateobjaddr1)
|
||||
if so1Restored != nil {
|
||||
t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored)
|
||||
}
|
||||
}
|
||||
|
||||
func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
|
||||
func compareStateObjects(so0, so1 *stateObject, t *testing.T) {
|
||||
if so0.Address() != so1.Address() {
|
||||
t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
|
|
@ -64,7 +63,7 @@ type StateDB struct {
|
|||
codeSizeCache *lru.Cache
|
||||
|
||||
// This map holds 'live' objects, which will get modified while processing a state transition.
|
||||
stateObjects map[common.Address]*StateObject
|
||||
stateObjects map[common.Address]*stateObject
|
||||
stateObjectsDirty map[common.Address]struct{}
|
||||
|
||||
// The refund counter, also used by state transitioning.
|
||||
|
|
@ -97,7 +96,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
|
|||
db: db,
|
||||
trie: tr,
|
||||
codeSizeCache: csc,
|
||||
stateObjects: make(map[common.Address]*StateObject),
|
||||
stateObjects: make(map[common.Address]*stateObject),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||
refund: new(big.Int),
|
||||
logs: make(map[common.Hash][]*types.Log),
|
||||
|
|
@ -119,7 +118,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
|
|||
db: self.db,
|
||||
trie: tr,
|
||||
codeSizeCache: self.codeSizeCache,
|
||||
stateObjects: make(map[common.Address]*StateObject),
|
||||
stateObjects: make(map[common.Address]*stateObject),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||
refund: new(big.Int),
|
||||
logs: make(map[common.Hash][]*types.Log),
|
||||
|
|
@ -138,7 +137,7 @@ func (self *StateDB) Reset(root common.Hash) error {
|
|||
return err
|
||||
}
|
||||
self.trie = tr
|
||||
self.stateObjects = make(map[common.Address]*StateObject)
|
||||
self.stateObjects = make(map[common.Address]*stateObject)
|
||||
self.stateObjectsDirty = make(map[common.Address]struct{})
|
||||
self.thash = common.Hash{}
|
||||
self.bhash = common.Hash{}
|
||||
|
|
@ -227,23 +226,19 @@ func (self *StateDB) AddRefund(gas *big.Int) {
|
|||
// Exist reports whether the given account address exists in the state.
|
||||
// Notably this also returns true for suicided accounts.
|
||||
func (self *StateDB) Exist(addr common.Address) bool {
|
||||
return self.GetStateObject(addr) != nil
|
||||
return self.getStateObject(addr) != nil
|
||||
}
|
||||
|
||||
// Empty returns whether the state object is either non-existent
|
||||
// or empty according to the EIP161 specification (balance = nonce = code = 0)
|
||||
func (self *StateDB) Empty(addr common.Address) bool {
|
||||
so := self.GetStateObject(addr)
|
||||
so := self.getStateObject(addr)
|
||||
return so == nil || so.empty()
|
||||
}
|
||||
|
||||
func (self *StateDB) GetAccount(addr common.Address) vm.Account {
|
||||
return self.GetStateObject(addr)
|
||||
}
|
||||
|
||||
// Retrieve the balance from the given address or 0 if object not found
|
||||
func (self *StateDB) GetBalance(addr common.Address) *big.Int {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.Balance()
|
||||
}
|
||||
|
|
@ -251,7 +246,7 @@ func (self *StateDB) GetBalance(addr common.Address) *big.Int {
|
|||
}
|
||||
|
||||
func (self *StateDB) GetNonce(addr common.Address) uint64 {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.Nonce()
|
||||
}
|
||||
|
|
@ -260,7 +255,7 @@ func (self *StateDB) GetNonce(addr common.Address) uint64 {
|
|||
}
|
||||
|
||||
func (self *StateDB) GetCode(addr common.Address) []byte {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject != nil {
|
||||
code := stateObject.Code(self.db)
|
||||
key := common.BytesToHash(stateObject.CodeHash())
|
||||
|
|
@ -271,7 +266,7 @@ func (self *StateDB) GetCode(addr common.Address) []byte {
|
|||
}
|
||||
|
||||
func (self *StateDB) GetCodeSize(addr common.Address) int {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject == nil {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -287,7 +282,7 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
|
|||
}
|
||||
|
||||
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject == nil {
|
||||
return common.Hash{}
|
||||
}
|
||||
|
|
@ -295,7 +290,7 @@ func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
|
|||
}
|
||||
|
||||
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
|
||||
stateObject := self.GetStateObject(a)
|
||||
stateObject := self.getStateObject(a)
|
||||
if stateObject != nil {
|
||||
return stateObject.GetState(self.db, b)
|
||||
}
|
||||
|
|
@ -303,7 +298,7 @@ func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
|
|||
}
|
||||
|
||||
func (self *StateDB) HasSuicided(addr common.Address) bool {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.suicided
|
||||
}
|
||||
|
|
@ -362,9 +357,9 @@ func (self *StateDB) SetState(addr common.Address, key common.Hash, value common
|
|||
// This clears the account balance.
|
||||
//
|
||||
// The account's state object is still available until the state is committed,
|
||||
// GetStateObject will return a non-nil account after Suicide.
|
||||
// getStateObject will return a non-nil account after Suicide.
|
||||
func (self *StateDB) Suicide(addr common.Address) bool {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject == nil {
|
||||
return false
|
||||
}
|
||||
|
|
@ -383,7 +378,7 @@ func (self *StateDB) Suicide(addr common.Address) bool {
|
|||
//
|
||||
|
||||
// updateStateObject writes the given object to the trie.
|
||||
func (self *StateDB) updateStateObject(stateObject *StateObject) {
|
||||
func (self *StateDB) updateStateObject(stateObject *stateObject) {
|
||||
addr := stateObject.Address()
|
||||
data, err := rlp.EncodeToBytes(stateObject)
|
||||
if err != nil {
|
||||
|
|
@ -393,14 +388,14 @@ func (self *StateDB) updateStateObject(stateObject *StateObject) {
|
|||
}
|
||||
|
||||
// deleteStateObject removes the given object from the state trie.
|
||||
func (self *StateDB) deleteStateObject(stateObject *StateObject) {
|
||||
func (self *StateDB) deleteStateObject(stateObject *stateObject) {
|
||||
stateObject.deleted = true
|
||||
addr := stateObject.Address()
|
||||
self.trie.Delete(addr[:])
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
|
||||
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateObjects[addr]; obj != nil {
|
||||
if obj.deleted {
|
||||
|
|
@ -425,13 +420,13 @@ func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObje
|
|||
return obj
|
||||
}
|
||||
|
||||
func (self *StateDB) setStateObject(object *StateObject) {
|
||||
func (self *StateDB) setStateObject(object *stateObject) {
|
||||
self.stateObjects[object.Address()] = object
|
||||
}
|
||||
|
||||
// Retrieve a state object or create a new state object if nil
|
||||
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
func (self *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
|
||||
stateObject := self.getStateObject(addr)
|
||||
if stateObject == nil || stateObject.deleted {
|
||||
stateObject, _ = self.createObject(addr)
|
||||
}
|
||||
|
|
@ -446,8 +441,8 @@ func (self *StateDB) MarkStateObjectDirty(addr common.Address) {
|
|||
|
||||
// createObject creates a new state object. If there is an existing account with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *StateDB) createObject(addr common.Address) (newobj, prev *StateObject) {
|
||||
prev = self.GetStateObject(addr)
|
||||
func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
|
||||
prev = self.getStateObject(addr)
|
||||
newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty)
|
||||
newobj.setNonce(0) // sets the object to dirty
|
||||
if prev == nil {
|
||||
|
|
@ -472,12 +467,11 @@ func (self *StateDB) createObject(addr common.Address) (newobj, prev *StateObjec
|
|||
// 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 (self *StateDB) CreateAccount(addr common.Address) vm.Account {
|
||||
func (self *StateDB) CreateAccount(addr common.Address) {
|
||||
new, prev := self.createObject(addr)
|
||||
if prev != nil {
|
||||
new.setBalance(prev.data.Balance)
|
||||
}
|
||||
return new
|
||||
}
|
||||
|
||||
// Copy creates a deep, independent copy of the state.
|
||||
|
|
@ -492,7 +486,7 @@ func (self *StateDB) Copy() *StateDB {
|
|||
trie: self.trie,
|
||||
pastTries: self.pastTries,
|
||||
codeSizeCache: self.codeSizeCache,
|
||||
stateObjects: make(map[common.Address]*StateObject, len(self.stateObjectsDirty)),
|
||||
stateObjects: make(map[common.Address]*stateObject, len(self.stateObjectsDirty)),
|
||||
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
|
||||
refund: new(big.Int).Set(self.refund),
|
||||
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
|
||||
|
|
|
|||
|
|
@ -331,11 +331,11 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
|
|||
checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr))
|
||||
checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr))
|
||||
// Check storage.
|
||||
if obj := state.GetStateObject(addr); obj != nil {
|
||||
if obj := state.getStateObject(addr); obj != nil {
|
||||
obj.ForEachStorage(func(key, val common.Hash) bool {
|
||||
return checkeq("GetState("+key.Hex()+")", val, checkstate.GetState(addr, key))
|
||||
})
|
||||
checkobj := checkstate.GetStateObject(addr)
|
||||
checkobj := checkstate.getStateObject(addr)
|
||||
checkobj.ForEachStorage(func(key, checkval common.Hash) bool {
|
||||
return checkeq("GetState("+key.Hex()+")", state.GetState(addr, key), checkval)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -29,6 +29,7 @@ import (
|
|||
|
||||
var (
|
||||
Big0 = big.NewInt(0)
|
||||
errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas")
|
||||
)
|
||||
|
||||
/*
|
||||
|
|
@ -136,27 +137,28 @@ func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, erro
|
|||
return ret, gasUsed, err
|
||||
}
|
||||
|
||||
func (self *StateTransition) from() vm.Account {
|
||||
func (self *StateTransition) from() vm.AccountRef {
|
||||
f := self.msg.From()
|
||||
if !self.state.Exist(f) {
|
||||
return self.state.CreateAccount(f)
|
||||
self.state.CreateAccount(f)
|
||||
}
|
||||
return self.state.GetAccount(f)
|
||||
return vm.Reference(f)
|
||||
}
|
||||
|
||||
func (self *StateTransition) to() vm.Account {
|
||||
func (self *StateTransition) to() vm.AccountRef {
|
||||
if self.msg == nil {
|
||||
return nil
|
||||
return vm.AccountRef{}
|
||||
}
|
||||
to := self.msg.To()
|
||||
if to == nil {
|
||||
return nil // contract creation
|
||||
return vm.AccountRef{} // contract creation
|
||||
}
|
||||
|
||||
reference := vm.Reference(*to)
|
||||
if !self.state.Exist(*to) {
|
||||
return self.state.CreateAccount(*to)
|
||||
self.state.CreateAccount(*to)
|
||||
}
|
||||
return self.state.GetAccount(*to)
|
||||
return reference
|
||||
}
|
||||
|
||||
func (self *StateTransition) useGas(amount uint64) error {
|
||||
|
|
@ -176,9 +178,12 @@ func (self *StateTransition) buyGas() error {
|
|||
|
||||
mgval := new(big.Int).Mul(mgas, self.gasPrice)
|
||||
|
||||
sender := self.from()
|
||||
if sender.Balance().Cmp(mgval) < 0 {
|
||||
return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], mgval, sender.Balance())
|
||||
var (
|
||||
state = self.state
|
||||
sender = self.from()
|
||||
)
|
||||
if state.GetBalance(sender.Address()).Cmp(mgval) < 0 {
|
||||
return errInsufficientBalanceForGas
|
||||
}
|
||||
if err := self.gp.SubGas(mgas); err != nil {
|
||||
return err
|
||||
|
|
@ -186,7 +191,7 @@ func (self *StateTransition) buyGas() error {
|
|||
self.gas += mgas.Uint64()
|
||||
|
||||
self.initialGas.Set(mgas)
|
||||
sender.SubBalance(mgval)
|
||||
state.SubBalance(sender.Address(), mgval)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +277,7 @@ func (self *StateTransition) refundGas() {
|
|||
// exchanged at the original rate.
|
||||
sender := self.from() // err already checked
|
||||
remaining := new(big.Int).Mul(new(big.Int).SetUint64(self.gas), self.gasPrice)
|
||||
sender.AddBalance(remaining)
|
||||
self.state.AddBalance(sender.Address(), remaining)
|
||||
|
||||
// Apply refund counter, capped to half of the used gas.
|
||||
uhalf := remaining.Div(self.gasUsed(), common.Big2)
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ import (
|
|||
// ContractRef is a reference to the contract's backing object
|
||||
type ContractRef interface {
|
||||
Address() common.Address
|
||||
Value() *big.Int
|
||||
SetCode(common.Hash, []byte)
|
||||
ForEachStorage(callback func(key, value common.Hash) bool)
|
||||
}
|
||||
|
||||
type AccountRef common.Address
|
||||
|
||||
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
|
||||
func Reference(addr common.Address) AccountRef { return (AccountRef)(addr) }
|
||||
|
||||
// Contract represents an ethereum contract in the state database. It contains
|
||||
// the the contract code, calling arguments. Contract implements ContractRef
|
||||
type Contract struct {
|
||||
|
|
@ -69,7 +71,8 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin
|
|||
// Gas should be a pointer so it can safely be reduced through the run
|
||||
// This pointer will be off the state transition
|
||||
c.Gas = gas
|
||||
c.value = new(big.Int).Set(value)
|
||||
// ensures a value is set
|
||||
c.value = value
|
||||
|
||||
return c
|
||||
}
|
||||
|
|
@ -80,7 +83,10 @@ func (c *Contract) AsDelegate() *Contract {
|
|||
c.DelegateCall = true
|
||||
// NOTE: caller must, at all times be a contract. It should never happen
|
||||
// that caller is something other than a Contract.
|
||||
c.CallerAddress = c.caller.(*Contract).CallerAddress
|
||||
parent := c.caller.(*Contract)
|
||||
c.CallerAddress = parent.CallerAddress
|
||||
c.value = parent.value
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
@ -138,9 +144,3 @@ func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code [
|
|||
self.CodeHash = hash
|
||||
self.CodeAddr = addr
|
||||
}
|
||||
|
||||
// EachStorage iterates the contract's storage and calls a method for every key
|
||||
// value pair.
|
||||
func (self *Contract) ForEachStorage(cb func(key, value common.Hash) bool) {
|
||||
self.caller.ForEachStorage(cb)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
}
|
||||
|
||||
var (
|
||||
to Account
|
||||
to = Reference(addr)
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
)
|
||||
if !evm.StateDB.Exist(addr) {
|
||||
|
|
@ -124,9 +124,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
return nil, gas, nil
|
||||
}
|
||||
|
||||
to = evm.StateDB.CreateAccount(addr)
|
||||
} else {
|
||||
to = evm.StateDB.GetAccount(addr)
|
||||
evm.StateDB.CreateAccount(addr)
|
||||
}
|
||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
|
||||
|
|
@ -169,7 +167,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
|||
|
||||
var (
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = evm.StateDB.GetAccount(caller.Address())
|
||||
to = Reference(caller.Address())
|
||||
)
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// E The contract is a scoped evmironment for this execution context
|
||||
|
|
@ -205,11 +203,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||
|
||||
var (
|
||||
snapshot = evm.StateDB.Snapshot()
|
||||
to = evm.StateDB.GetAccount(caller.Address())
|
||||
to = Reference(caller.Address())
|
||||
)
|
||||
|
||||
// Iinitialise a new contract and make initialise the delegate values
|
||||
contract := NewContract(caller, to, caller.Value(), gas).AsDelegate()
|
||||
contract := NewContract(caller, to, nil, gas).AsDelegate()
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
|
||||
ret, err = evm.interpreter.Run(contract, input)
|
||||
|
|
@ -243,16 +241,16 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
|
|||
|
||||
snapshot := evm.StateDB.Snapshot()
|
||||
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
|
||||
to := evm.StateDB.CreateAccount(contractAddr)
|
||||
evm.StateDB.CreateAccount(contractAddr)
|
||||
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
|
||||
evm.StateDB.SetNonce(contractAddr, 1)
|
||||
}
|
||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value)
|
||||
|
||||
// initialise a new contract and set the code that is to be used by the
|
||||
// E The contract is a scoped evmironment for this execution context
|
||||
// only.
|
||||
contract := NewContract(caller, to, value, gas)
|
||||
contract := NewContract(caller, Reference(contractAddr), value, gas)
|
||||
contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
|
||||
|
||||
ret, err = evm.interpreter.Run(contract, nil)
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ import (
|
|||
|
||||
// StateDB is an EVM database for full state querying.
|
||||
type StateDB interface {
|
||||
GetAccount(common.Address) Account
|
||||
CreateAccount(common.Address) Account
|
||||
CreateAccount(common.Address)
|
||||
|
||||
SubBalance(common.Address, *big.Int)
|
||||
AddBalance(common.Address, *big.Int)
|
||||
|
|
@ -63,20 +62,6 @@ type StateDB interface {
|
|||
AddPreimage(common.Hash, []byte)
|
||||
}
|
||||
|
||||
// Account represents a contract or basic ethereum account.
|
||||
type Account interface {
|
||||
SubBalance(amount *big.Int)
|
||||
AddBalance(amount *big.Int)
|
||||
SetBalance(*big.Int)
|
||||
SetNonce(uint64)
|
||||
Balance() *big.Int
|
||||
Address() common.Address
|
||||
ReturnGas(*big.Int)
|
||||
SetCode(common.Hash, []byte)
|
||||
ForEachStorage(cb func(key, value common.Hash) bool)
|
||||
Value() *big.Int
|
||||
}
|
||||
|
||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM EVM
|
||||
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
|
||||
type CallContext interface {
|
||||
|
|
|
|||
|
|
@ -144,11 +144,14 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost *b
|
|||
storage = make(Storage)
|
||||
// Get the contract account and loop over each storage entry. This may involve looping over
|
||||
// the trie and is a very expensive process.
|
||||
|
||||
/* TODO
|
||||
env.StateDB.GetAccount(contract.Address()).ForEachStorage(func(key, value common.Hash) bool {
|
||||
storage[key] = value
|
||||
// Return true, indicating we'd like to continue.
|
||||
return true
|
||||
})
|
||||
*/
|
||||
} else {
|
||||
// copy a snapshot of the current storage to a new container.
|
||||
storage = l.changedValues[contract.Address()].Copy()
|
||||
|
|
|
|||
|
|
@ -46,10 +46,6 @@ type dummyStateDB struct {
|
|||
ref *dummyContractRef
|
||||
}
|
||||
|
||||
func (d dummyStateDB) GetAccount(common.Address) Account {
|
||||
return d.ref
|
||||
}
|
||||
|
||||
func TestStoreCapture(t *testing.T) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ func (NoopEVMCallContext) DelegateCall(me ContractRef, addr common.Address, data
|
|||
|
||||
type NoopStateDB struct{}
|
||||
|
||||
func (NoopStateDB) GetAccount(common.Address) Account { return nil }
|
||||
func (NoopStateDB) CreateAccount(common.Address) Account { return nil }
|
||||
func (NoopStateDB) CreateAccount(common.Address) {}
|
||||
func (NoopStateDB) SubBalance(common.Address, *big.Int) {}
|
||||
func (NoopStateDB) AddBalance(common.Address, *big.Int) {}
|
||||
func (NoopStateDB) GetBalance(common.Address) *big.Int { return nil }
|
||||
|
|
|
|||
|
|
@ -105,17 +105,17 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
|||
cfg.State, _ = state.New(common.Hash{}, db)
|
||||
}
|
||||
var (
|
||||
address = common.StringToAddress("contract")
|
||||
vmenv = NewEnv(cfg, cfg.State)
|
||||
sender = cfg.State.CreateAccount(cfg.Origin)
|
||||
receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
|
||||
sender = vm.Reference(cfg.Origin)
|
||||
)
|
||||
cfg.State.CreateAccount(address)
|
||||
// set the receiver's (the executing contract) code for execution.
|
||||
receiver.SetCode(crypto.Keccak256Hash(code), code)
|
||||
|
||||
cfg.State.SetCode(address, code)
|
||||
// Call the code with the given configuration.
|
||||
ret, _, err := vmenv.Call(
|
||||
sender,
|
||||
receiver.Address(),
|
||||
common.StringToAddress("contract"),
|
||||
input,
|
||||
cfg.GasLimit,
|
||||
cfg.Value,
|
||||
|
|
@ -137,7 +137,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) {
|
|||
}
|
||||
var (
|
||||
vmenv = NewEnv(cfg, cfg.State)
|
||||
sender = cfg.State.CreateAccount(cfg.Origin)
|
||||
sender = vm.Reference(cfg.Origin)
|
||||
)
|
||||
|
||||
// Call the code with the given configuration.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
|
@ -64,27 +63,10 @@ func (self *VMState) RevertToSnapshot(idx int) {
|
|||
self.snapshots = self.snapshots[:idx]
|
||||
}
|
||||
|
||||
// GetAccount returns the account object of the given account or nil if the
|
||||
// account does not exist
|
||||
func (s *VMState) GetAccount(addr common.Address) vm.Account {
|
||||
so, err := s.state.GetStateObject(s.ctx, addr)
|
||||
s.errHandler(err)
|
||||
if err != nil {
|
||||
// return a dummy state object to avoid panics
|
||||
so = s.state.newStateObject(addr)
|
||||
}
|
||||
return so
|
||||
}
|
||||
|
||||
// CreateAccount creates creates a new account object and takes ownership.
|
||||
func (s *VMState) CreateAccount(addr common.Address) vm.Account {
|
||||
so, err := s.state.CreateStateObject(s.ctx, addr)
|
||||
func (s *VMState) CreateAccount(addr common.Address) {
|
||||
_, err := s.state.CreateStateObject(s.ctx, addr)
|
||||
s.errHandler(err)
|
||||
if err != nil {
|
||||
// return a dummy state object to avoid panics
|
||||
so = s.state.newStateObject(addr)
|
||||
}
|
||||
return so
|
||||
}
|
||||
|
||||
// AddBalance adds the given amount to the balance of the specified account
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
|
|
@ -222,10 +221,12 @@ func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj := statedb.CreateAccount(common.HexToAddress(addrString))
|
||||
obj.SetCode(crypto.Keccak256Hash(code), code)
|
||||
obj.SetBalance(balance)
|
||||
obj.SetNonce(nonce)
|
||||
|
||||
addr := common.HexToAddress(addrString)
|
||||
statedb.CreateAccount(addr)
|
||||
statedb.SetCode(addr, code)
|
||||
statedb.SetBalance(addr, balance)
|
||||
statedb.SetNonce(addr, nonce)
|
||||
for k, v := range acct.Storage {
|
||||
statedb.SetState(common.HexToAddress(addrString), common.HexToHash(k), common.HexToHash(v))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,25 +165,25 @@ func runStateTest(chainConfig *params.ChainConfig, test VmTest) error {
|
|||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
address := common.HexToAddress(addr)
|
||||
if !statedb.Exist(address) {
|
||||
return fmt.Errorf("did not find expected post-state account: %s", addr)
|
||||
}
|
||||
|
||||
if obj.Balance().Cmp(common.Big(account.Balance)) != 0 {
|
||||
return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], common.String2Big(account.Balance), obj.Balance())
|
||||
if balance := statedb.GetBalance(address); balance.Cmp(common.Big(account.Balance)) != 0 {
|
||||
return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], common.String2Big(account.Balance), balance)
|
||||
}
|
||||
|
||||
if obj.Nonce() != common.String2Big(account.Nonce).Uint64() {
|
||||
return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], account.Nonce, obj.Nonce())
|
||||
if nonce := statedb.GetNonce(address); nonce != common.String2Big(account.Nonce).Uint64() {
|
||||
return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", address[:4], account.Nonce, nonce)
|
||||
}
|
||||
|
||||
for addr, value := range account.Storage {
|
||||
v := statedb.GetState(obj.Address(), common.HexToHash(addr))
|
||||
v := statedb.GetState(address, common.HexToHash(addr))
|
||||
vexp := common.HexToHash(value)
|
||||
|
||||
if v != vexp {
|
||||
return fmt.Errorf("storage failed:\n%x: %s:\nexpected: %x\nhave: %x\n(%v %v)\n", obj.Address().Bytes(), addr, vexp, v, vexp.Big(), v.Big())
|
||||
return fmt.Errorf("storage failed:\n%x: %s:\nexpected: %x\nhave: %x\n(%v %v)\n", address[:4], addr, vexp, v, vexp.Big(), v.Big())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,16 +187,16 @@ func runVmTest(test VmTest) error {
|
|||
}
|
||||
|
||||
// check post state
|
||||
for addr, account := range test.Post {
|
||||
obj := statedb.GetStateObject(common.HexToAddress(addr))
|
||||
if obj == nil {
|
||||
for address, account := range test.Post {
|
||||
accountAddr := common.HexToAddress(address)
|
||||
if !statedb.Exist(accountAddr) {
|
||||
continue
|
||||
}
|
||||
for addr, value := range account.Storage {
|
||||
v := statedb.GetState(obj.Address(), common.HexToHash(addr))
|
||||
v := statedb.GetState(accountAddr, common.HexToHash(addr))
|
||||
vexp := common.HexToHash(value)
|
||||
if v != vexp {
|
||||
return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big())
|
||||
return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", addr[:4], addr, vexp, v, vexp.Big(), v.Big())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue