state_object.go 8.09 KB
Newer Older
1
// Copyright 2015 The go-ethereum Authors
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// 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 light

import (
	"bytes"
	"fmt"
	"math/big"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/logger/glog"
	"github.com/ethereum/go-ethereum/rlp"
	"golang.org/x/net/context"
)

32
var emptyCodeHash = crypto.Keccak256(nil)
33 34 35 36 37 38 39 40 41 42

// Code represents a contract code in binary form
type Code []byte

// String returns a string representation of the code
func (self Code) String() string {
	return string(self) //strings.Join(Disassemble(self), " ")
}

// Storage is a memory map cache of a contract storage
43
type Storage map[common.Hash]common.Hash
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

// String returns a string representation of the storage cache
func (self Storage) String() (str string) {
	for key, value := range self {
		str += fmt.Sprintf("%X : %X\n", key, value)
	}

	return
}

// Copy copies the contents of a storage cache
func (self Storage) Copy() Storage {
	cpy := make(Storage)
	for key, value := range self {
		cpy[key] = value
	}

	return cpy
}

// StateObject is a memory representation of an account or contract and its storage.
// This version is ODR capable, caching only the already accessed part of the
// storage, retrieving unknown parts on-demand from the ODR backend. Changes are
// never stored in the local database, only in the memory objects.
type StateObject struct {
	odr  OdrBackend
	trie *LightTrie

	// Address belonging to this account
	address common.Address
	// The balance of the account
	balance *big.Int
	// The nonce of the account
	nonce uint64
	// The code hash if code is present (i.e. a contract)
	codeHash []byte
	// The code for this account
	code Code
	// Cached storage (flushed when updated)
	storage Storage

	// Mark for deletion
	// When an object is marked for deletion it will be delete from the trie
	// during the "update" phase of the state transition
	remove  bool
	deleted bool
	dirty   bool
}

// NewStateObject creates a new StateObject of the specified account address
func NewStateObject(address common.Address, odr OdrBackend) *StateObject {
	object := &StateObject{
		odr:      odr,
		address:  address,
		balance:  new(big.Int),
		dirty:    true,
		codeHash: emptyCodeHash,
		storage:  make(Storage),
	}
103
	object.trie = NewLightTrie(&TrieID{}, odr, true)
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
	return object
}

// MarkForDeletion marks an account to be removed
func (self *StateObject) MarkForDeletion() {
	self.remove = true
	self.dirty = true

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v X\n", self.Address(), self.nonce, self.balance)
	}
}

// getAddr gets the storage value at the given address from the trie
func (c *StateObject) getAddr(ctx context.Context, addr common.Hash) (common.Hash, error) {
	var ret []byte
	val, err := c.trie.Get(ctx, addr[:])
	if err != nil {
		return common.Hash{}, err
	}
	rlp.DecodeBytes(val, &ret)
	return common.BytesToHash(ret), nil
}

// Storage returns the storage cache object of the account
func (self *StateObject) Storage() Storage {
	return self.storage
}

// GetState returns the storage value at the given address from either the cache
// or the trie
func (self *StateObject) GetState(ctx context.Context, key common.Hash) (common.Hash, error) {
136
	value, exists := self.storage[key]
137 138 139 140 141 142 143
	if !exists {
		var err error
		value, err = self.getAddr(ctx, key)
		if err != nil {
			return common.Hash{}, err
		}
		if (value != common.Hash{}) {
144
			self.storage[key] = value
145 146 147 148 149 150 151 152
		}
	}

	return value, nil
}

// SetState sets the storage value at the given address
func (self *StateObject) SetState(k, value common.Hash) {
153
	self.storage[k] = value
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
	self.dirty = true
}

// AddBalance adds the given amount to the account balance
func (c *StateObject) AddBalance(amount *big.Int) {
	c.SetBalance(new(big.Int).Add(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

// SubBalance subtracts the given amount from the account balance
func (c *StateObject) SubBalance(amount *big.Int) {
	c.SetBalance(new(big.Int).Sub(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

// SetBalance sets the account balance to the given amount
func (c *StateObject) SetBalance(amount *big.Int) {
	c.balance = amount
	c.dirty = true
}

181
// ReturnGas returns the gas back to the origin. Used by the Virtual machine or Closures
182
func (c *StateObject) ReturnGas(gas *big.Int) {}
183

184 185 186 187 188 189 190
// Copy creates a copy of the state object
func (self *StateObject) Copy() *StateObject {
	stateObject := NewStateObject(self.Address(), self.odr)
	stateObject.balance.Set(self.balance)
	stateObject.codeHash = common.CopyBytes(self.codeHash)
	stateObject.nonce = self.nonce
	stateObject.trie = self.trie
191
	stateObject.code = self.code
192 193 194 195 196 197 198 199 200 201 202 203
	stateObject.storage = self.storage.Copy()
	stateObject.remove = self.remove
	stateObject.dirty = self.dirty
	stateObject.deleted = self.deleted

	return stateObject
}

//
// Attribute accessors
//

204 205 206 207 208
// empty returns whether the account is considered empty.
func (self *StateObject) empty() bool {
	return self.nonce == 0 && self.balance.BitLen() == 0 && bytes.Equal(self.codeHash, emptyCodeHash)
}

209 210 211 212 213 214
// Balance returns the account balance
func (self *StateObject) Balance() *big.Int {
	return self.balance
}

// Address returns the address of the contract/account
215 216
func (self *StateObject) Address() common.Address {
	return self.address
217 218 219 220 221 222 223 224
}

// Code returns the contract code
func (self *StateObject) Code() []byte {
	return self.code
}

// SetCode sets the contract code
225
func (self *StateObject) SetCode(hash common.Hash, code []byte) {
226
	self.code = code
227
	self.codeHash = hash[:]
228 229 230 231 232 233 234 235 236 237 238 239 240 241
	self.dirty = true
}

// SetNonce sets the account nonce
func (self *StateObject) SetNonce(nonce uint64) {
	self.nonce = nonce
	self.dirty = true
}

// Nonce returns the account nonce
func (self *StateObject) Nonce() uint64 {
	return self.nonce
}

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
// ForEachStorage calls a callback function for every key/value pair found
// in the local storage cache. Note that unlike core/state.StateObject,
// light.StateObject only returns cached values and doesn't download the
// entire storage tree.
func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
	for h, v := range self.storage {
		cb(h, v)
	}
}

// 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")
}

259 260 261 262 263 264 265 266 267 268
// Encoding

type extStateObject struct {
	Nonce    uint64
	Balance  *big.Int
	Root     common.Hash
	CodeHash []byte
}

// DecodeObject decodes an RLP-encoded state object.
269
func DecodeObject(ctx context.Context, stateID *TrieID, address common.Address, odr OdrBackend, data []byte) (*StateObject, error) {
270 271 272 273 274 275 276 277
	var (
		obj = &StateObject{address: address, odr: odr, storage: make(Storage)}
		ext extStateObject
		err error
	)
	if err = rlp.DecodeBytes(data, &ext); err != nil {
		return nil, err
	}
278 279
	trieID := StorageTrieID(stateID, address, ext.Root)
	obj.trie = NewLightTrie(trieID, odr, true)
280
	if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
281
		if obj.code, err = retrieveContractCode(ctx, obj.odr, trieID, common.BytesToHash(ext.CodeHash)); err != nil {
282 283 284 285 286 287 288
			return nil, fmt.Errorf("can't find code for hash %x: %v", ext.CodeHash, err)
		}
	}
	obj.nonce = ext.Nonce
	obj.balance = ext.Balance
	obj.codeHash = ext.CodeHash
	return obj, nil
289
}