github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/light/state_object.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package light
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"math/big"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/ethereum/go-ethereum/rlp"
    28  )
    29  
    30  var emptyCodeHash = crypto.Keccak256(nil)
    31  
    32  // Code represents a contract code in binary form
    33  type Code []byte
    34  
    35  // String returns a string representation of the code
    36  func (self Code) String() string {
    37  	return string(self) //strings.Join(Disassemble(self), " ")
    38  }
    39  
    40  // Storage is a memory map cache of a contract storage
    41  type Storage map[common.Hash]common.Hash
    42  
    43  // String returns a string representation of the storage cache
    44  func (self Storage) String() (str string) {
    45  	for key, value := range self {
    46  		str += fmt.Sprintf("%X : %X\n", key, value)
    47  	}
    48  
    49  	return
    50  }
    51  
    52  // Copy copies the contents of a storage cache
    53  func (self Storage) Copy() Storage {
    54  	cpy := make(Storage)
    55  	for key, value := range self {
    56  		cpy[key] = value
    57  	}
    58  
    59  	return cpy
    60  }
    61  
    62  // StateObject is a memory representation of an account or contract and its storage.
    63  // This version is ODR capable, caching only the already accessed part of the
    64  // storage, retrieving unknown parts on-demand from the ODR backend. Changes are
    65  // never stored in the local database, only in the memory objects.
    66  type StateObject struct {
    67  	odr  OdrBackend
    68  	trie *LightTrie
    69  
    70  	// Address belonging to this account
    71  	address common.Address
    72  	// The balance of the account
    73  	balance *big.Int
    74  	// The nonce of the account
    75  	nonce uint64
    76  	// The code hash if code is present (i.e. a contract)
    77  	codeHash []byte
    78  	// The code for this account
    79  	code Code
    80  	// Cached storage (flushed when updated)
    81  	storage Storage
    82  
    83  	// Mark for deletion
    84  	// When an object is marked for deletion it will be delete from the trie
    85  	// during the "update" phase of the state transition
    86  	remove  bool
    87  	deleted bool
    88  	dirty   bool
    89  }
    90  
    91  // NewStateObject creates a new StateObject of the specified account address
    92  func NewStateObject(address common.Address, odr OdrBackend) *StateObject {
    93  	object := &StateObject{
    94  		odr:      odr,
    95  		address:  address,
    96  		balance:  new(big.Int),
    97  		dirty:    true,
    98  		codeHash: emptyCodeHash,
    99  		storage:  make(Storage),
   100  	}
   101  	object.trie = NewLightTrie(&TrieID{}, odr, true)
   102  	return object
   103  }
   104  
   105  // MarkForDeletion marks an account to be removed
   106  func (self *StateObject) MarkForDeletion() {
   107  	self.remove = true
   108  	self.dirty = true
   109  }
   110  
   111  // getAddr gets the storage value at the given address from the trie
   112  func (c *StateObject) getAddr(ctx context.Context, addr common.Hash) (common.Hash, error) {
   113  	var ret []byte
   114  	val, err := c.trie.Get(ctx, addr[:])
   115  	if err != nil {
   116  		return common.Hash{}, err
   117  	}
   118  	rlp.DecodeBytes(val, &ret)
   119  	return common.BytesToHash(ret), nil
   120  }
   121  
   122  // Storage returns the storage cache object of the account
   123  func (self *StateObject) Storage() Storage {
   124  	return self.storage
   125  }
   126  
   127  // GetState returns the storage value at the given address from either the cache
   128  // or the trie
   129  func (self *StateObject) GetState(ctx context.Context, key common.Hash) (common.Hash, error) {
   130  	value, exists := self.storage[key]
   131  	if !exists {
   132  		var err error
   133  		value, err = self.getAddr(ctx, key)
   134  		if err != nil {
   135  			return common.Hash{}, err
   136  		}
   137  		if (value != common.Hash{}) {
   138  			self.storage[key] = value
   139  		}
   140  	}
   141  
   142  	return value, nil
   143  }
   144  
   145  // SetState sets the storage value at the given address
   146  func (self *StateObject) SetState(k, value common.Hash) {
   147  	self.storage[k] = value
   148  	self.dirty = true
   149  }
   150  
   151  // AddBalance adds the given amount to the account balance
   152  func (c *StateObject) AddBalance(amount *big.Int) {
   153  	c.SetBalance(new(big.Int).Add(c.balance, amount))
   154  }
   155  
   156  // SubBalance subtracts the given amount from the account balance
   157  func (c *StateObject) SubBalance(amount *big.Int) {
   158  	c.SetBalance(new(big.Int).Sub(c.balance, amount))
   159  }
   160  
   161  // SetBalance sets the account balance to the given amount
   162  func (c *StateObject) SetBalance(amount *big.Int) {
   163  	c.balance = amount
   164  	c.dirty = true
   165  }
   166  
   167  // ReturnGas returns the gas back to the origin. Used by the Virtual machine or Closures
   168  func (c *StateObject) ReturnGas(gas *big.Int) {}
   169  
   170  // Copy creates a copy of the state object
   171  func (self *StateObject) Copy() *StateObject {
   172  	stateObject := NewStateObject(self.Address(), self.odr)
   173  	stateObject.balance.Set(self.balance)
   174  	stateObject.codeHash = common.CopyBytes(self.codeHash)
   175  	stateObject.nonce = self.nonce
   176  	stateObject.trie = self.trie
   177  	stateObject.code = self.code
   178  	stateObject.storage = self.storage.Copy()
   179  	stateObject.remove = self.remove
   180  	stateObject.dirty = self.dirty
   181  	stateObject.deleted = self.deleted
   182  
   183  	return stateObject
   184  }
   185  
   186  //
   187  // Attribute accessors
   188  //
   189  
   190  // empty returns whether the account is considered empty.
   191  func (self *StateObject) empty() bool {
   192  	return self.nonce == 0 && self.balance.Sign() == 0 && bytes.Equal(self.codeHash, emptyCodeHash)
   193  }
   194  
   195  // Balance returns the account balance
   196  func (self *StateObject) Balance() *big.Int {
   197  	return self.balance
   198  }
   199  
   200  // Address returns the address of the contract/account
   201  func (self *StateObject) Address() common.Address {
   202  	return self.address
   203  }
   204  
   205  // Code returns the contract code
   206  func (self *StateObject) Code() []byte {
   207  	return self.code
   208  }
   209  
   210  // SetCode sets the contract code
   211  func (self *StateObject) SetCode(hash common.Hash, code []byte) {
   212  	self.code = code
   213  	self.codeHash = hash[:]
   214  	self.dirty = true
   215  }
   216  
   217  // SetNonce sets the account nonce
   218  func (self *StateObject) SetNonce(nonce uint64) {
   219  	self.nonce = nonce
   220  	self.dirty = true
   221  }
   222  
   223  // Nonce returns the account nonce
   224  func (self *StateObject) Nonce() uint64 {
   225  	return self.nonce
   226  }
   227  
   228  // ForEachStorage calls a callback function for every key/value pair found
   229  // in the local storage cache. Note that unlike core/state.StateObject,
   230  // light.StateObject only returns cached values and doesn't download the
   231  // entire storage tree.
   232  func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
   233  	for h, v := range self.storage {
   234  		cb(h, v)
   235  	}
   236  }
   237  
   238  // Never called, but must be present to allow StateObject to be used
   239  // as a vm.Account interface that also satisfies the vm.ContractRef
   240  // interface. Interfaces are awesome.
   241  func (self *StateObject) Value() *big.Int {
   242  	panic("Value on StateObject should never be called")
   243  }
   244  
   245  // Encoding
   246  
   247  type extStateObject struct {
   248  	Nonce    uint64
   249  	Balance  *big.Int
   250  	Root     common.Hash
   251  	CodeHash []byte
   252  }
   253  
   254  // DecodeObject decodes an RLP-encoded state object.
   255  func DecodeObject(ctx context.Context, stateID *TrieID, address common.Address, odr OdrBackend, data []byte) (*StateObject, error) {
   256  	var (
   257  		obj = &StateObject{address: address, odr: odr, storage: make(Storage)}
   258  		ext extStateObject
   259  		err error
   260  	)
   261  	if err = rlp.DecodeBytes(data, &ext); err != nil {
   262  		return nil, err
   263  	}
   264  	trieID := StorageTrieID(stateID, address, ext.Root)
   265  	obj.trie = NewLightTrie(trieID, odr, true)
   266  	if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
   267  		if obj.code, err = retrieveContractCode(ctx, obj.odr, trieID, common.BytesToHash(ext.CodeHash)); err != nil {
   268  			return nil, fmt.Errorf("can't find code for hash %x: %v", ext.CodeHash, err)
   269  		}
   270  	}
   271  	obj.nonce = ext.Nonce
   272  	obj.balance = ext.Balance
   273  	obj.codeHash = ext.CodeHash
   274  	return obj, nil
   275  }