github.com/immesys/bw2bc@v1.1.0/core/state/statedb.go (about)

     1  // Copyright 2014 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 state provides a caching layer atop the Ethereum state trie.
    18  package state
    19  
    20  import (
    21  	"bytes"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/logger"
    26  	"github.com/ethereum/go-ethereum/logger/glog"
    27  	"github.com/ethereum/go-ethereum/trie"
    28  )
    29  
    30  // StateDBs within the ethereum protocol are used to store anything
    31  // within the merkle trie. StateDBs take care of caching and storing
    32  // nested states. It's the general query interface to retrieve:
    33  // * Contracts
    34  // * Accounts
    35  type StateDB struct {
    36  	db   common.Database
    37  	trie *trie.SecureTrie
    38  	root common.Hash
    39  
    40  	stateObjects map[string]*StateObject
    41  
    42  	refund *big.Int
    43  
    44  	thash, bhash common.Hash
    45  	txIndex      int
    46  	logs         map[common.Hash]Logs
    47  	logSize      uint
    48  }
    49  
    50  // Create a new state from a given trie
    51  func New(root common.Hash, db common.Database) *StateDB {
    52  	trie := trie.NewSecure(root[:], db)
    53  	return &StateDB{root: root, db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)}
    54  }
    55  
    56  func (self *StateDB) PrintRoot() {
    57  	self.trie.Trie.PrintRoot()
    58  }
    59  
    60  func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
    61  	self.thash = thash
    62  	self.bhash = bhash
    63  	self.txIndex = ti
    64  }
    65  
    66  func (self *StateDB) AddLog(log *Log) {
    67  	log.TxHash = self.thash
    68  	log.BlockHash = self.bhash
    69  	log.TxIndex = uint(self.txIndex)
    70  	log.Index = self.logSize
    71  	self.logs[self.thash] = append(self.logs[self.thash], log)
    72  	self.logSize++
    73  }
    74  
    75  func (self *StateDB) GetLogs(hash common.Hash) Logs {
    76  	return self.logs[hash]
    77  }
    78  
    79  func (self *StateDB) Logs() Logs {
    80  	var logs Logs
    81  	for _, lgs := range self.logs {
    82  		logs = append(logs, lgs...)
    83  	}
    84  	return logs
    85  }
    86  
    87  func (self *StateDB) Refund(gas *big.Int) {
    88  	self.refund.Add(self.refund, gas)
    89  }
    90  
    91  /*
    92   * GETTERS
    93   */
    94  
    95  func (self *StateDB) HasAccount(addr common.Address) bool {
    96  	return self.GetStateObject(addr) != nil
    97  }
    98  
    99  // Retrieve the balance from the given address or 0 if object not found
   100  func (self *StateDB) GetBalance(addr common.Address) *big.Int {
   101  	stateObject := self.GetStateObject(addr)
   102  	if stateObject != nil {
   103  		return stateObject.balance
   104  	}
   105  
   106  	return common.Big0
   107  }
   108  
   109  func (self *StateDB) GetNonce(addr common.Address) uint64 {
   110  	stateObject := self.GetStateObject(addr)
   111  	if stateObject != nil {
   112  		return stateObject.nonce
   113  	}
   114  
   115  	return 0
   116  }
   117  
   118  func (self *StateDB) GetCode(addr common.Address) []byte {
   119  	stateObject := self.GetStateObject(addr)
   120  	if stateObject != nil {
   121  		return stateObject.code
   122  	}
   123  
   124  	return nil
   125  }
   126  
   127  func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
   128  	stateObject := self.GetStateObject(a)
   129  	if stateObject != nil {
   130  		return stateObject.GetState(b)
   131  	}
   132  
   133  	return common.Hash{}
   134  }
   135  
   136  func (self *StateDB) IsDeleted(addr common.Address) bool {
   137  	stateObject := self.GetStateObject(addr)
   138  	if stateObject != nil {
   139  		return stateObject.remove
   140  	}
   141  	return false
   142  }
   143  
   144  /*
   145   * SETTERS
   146   */
   147  
   148  func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
   149  	stateObject := self.GetOrNewStateObject(addr)
   150  	if stateObject != nil {
   151  		stateObject.AddBalance(amount)
   152  	}
   153  }
   154  
   155  func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
   156  	stateObject := self.GetOrNewStateObject(addr)
   157  	if stateObject != nil {
   158  		stateObject.SetNonce(nonce)
   159  	}
   160  }
   161  
   162  func (self *StateDB) SetCode(addr common.Address, code []byte) {
   163  	stateObject := self.GetOrNewStateObject(addr)
   164  	if stateObject != nil {
   165  		stateObject.SetCode(code)
   166  	}
   167  }
   168  
   169  func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) {
   170  	stateObject := self.GetOrNewStateObject(addr)
   171  	if stateObject != nil {
   172  		stateObject.SetState(key, value)
   173  	}
   174  }
   175  
   176  func (self *StateDB) Delete(addr common.Address) bool {
   177  	stateObject := self.GetStateObject(addr)
   178  	if stateObject != nil {
   179  		stateObject.MarkForDeletion()
   180  		stateObject.balance = new(big.Int)
   181  
   182  		return true
   183  	}
   184  
   185  	return false
   186  }
   187  
   188  //
   189  // Setting, updating & deleting state object methods
   190  //
   191  
   192  // Update the given state object and apply it to state trie
   193  func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
   194  	//addr := stateObject.Address()
   195  
   196  	if len(stateObject.CodeHash()) > 0 {
   197  		self.db.Put(stateObject.CodeHash(), stateObject.code)
   198  	}
   199  
   200  	addr := stateObject.Address()
   201  	self.trie.Update(addr[:], stateObject.RlpEncode())
   202  }
   203  
   204  // Delete the given state object and delete it from the state trie
   205  func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
   206  	stateObject.deleted = true
   207  
   208  	addr := stateObject.Address()
   209  	self.trie.Delete(addr[:])
   210  }
   211  
   212  // Retrieve a state object given my the address. Nil if not found
   213  func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
   214  	stateObject = self.stateObjects[addr.Str()]
   215  	if stateObject != nil {
   216  		if stateObject.deleted {
   217  			stateObject = nil
   218  		}
   219  
   220  		return stateObject
   221  	}
   222  
   223  	data := self.trie.Get(addr[:])
   224  	if len(data) == 0 {
   225  		return nil
   226  	}
   227  
   228  	stateObject = NewStateObjectFromBytes(addr, []byte(data), self.db)
   229  	self.SetStateObject(stateObject)
   230  
   231  	return stateObject
   232  }
   233  
   234  func (self *StateDB) SetStateObject(object *StateObject) {
   235  	self.stateObjects[object.Address().Str()] = object
   236  }
   237  
   238  // Retrieve a state object or create a new state object if nil
   239  func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
   240  	stateObject := self.GetStateObject(addr)
   241  	if stateObject == nil || stateObject.deleted {
   242  		stateObject = self.CreateAccount(addr)
   243  	}
   244  
   245  	return stateObject
   246  }
   247  
   248  // NewStateObject create a state object whether it exist in the trie or not
   249  func (self *StateDB) newStateObject(addr common.Address) *StateObject {
   250  	if glog.V(logger.Core) {
   251  		glog.Infof("(+) %x\n", addr)
   252  	}
   253  
   254  	stateObject := NewStateObject(addr, self.db)
   255  	self.stateObjects[addr.Str()] = stateObject
   256  
   257  	return stateObject
   258  }
   259  
   260  // Creates creates a new state object and takes ownership. This is different from "NewStateObject"
   261  func (self *StateDB) CreateAccount(addr common.Address) *StateObject {
   262  	// Get previous (if any)
   263  	so := self.GetStateObject(addr)
   264  	// Create a new one
   265  	newSo := self.newStateObject(addr)
   266  
   267  	// If it existed set the balance to the new account
   268  	if so != nil {
   269  		newSo.balance = so.balance
   270  	}
   271  
   272  	return newSo
   273  }
   274  
   275  //
   276  // Setting, copying of the state methods
   277  //
   278  
   279  func (s *StateDB) Cmp(other *StateDB) bool {
   280  	return bytes.Equal(s.trie.Root(), other.trie.Root())
   281  }
   282  
   283  func (self *StateDB) Copy() *StateDB {
   284  	state := New(common.Hash{}, self.db)
   285  	state.trie = self.trie
   286  	for k, stateObject := range self.stateObjects {
   287  		state.stateObjects[k] = stateObject.Copy()
   288  	}
   289  
   290  	state.refund.Set(self.refund)
   291  
   292  	for hash, logs := range self.logs {
   293  		state.logs[hash] = make(Logs, len(logs))
   294  		copy(state.logs[hash], logs)
   295  	}
   296  	state.logSize = self.logSize
   297  
   298  	return state
   299  }
   300  
   301  func (self *StateDB) Set(state *StateDB) {
   302  	self.trie = state.trie
   303  	self.stateObjects = state.stateObjects
   304  
   305  	self.refund = state.refund
   306  	self.logs = state.logs
   307  	self.logSize = state.logSize
   308  }
   309  
   310  func (s *StateDB) Root() common.Hash {
   311  	return common.BytesToHash(s.trie.Root())
   312  }
   313  
   314  func (s *StateDB) Trie() *trie.SecureTrie {
   315  	return s.trie
   316  }
   317  
   318  // Resets the trie and all siblings
   319  func (s *StateDB) Reset() {
   320  	s.trie.Reset()
   321  
   322  	// Reset all nested states
   323  	for _, stateObject := range s.stateObjects {
   324  		stateObject.Reset()
   325  	}
   326  
   327  	s.Empty()
   328  }
   329  
   330  // Syncs the trie and all siblings
   331  func (s *StateDB) Sync() {
   332  	// Sync all nested states
   333  	for _, stateObject := range s.stateObjects {
   334  		stateObject.trie.Commit()
   335  	}
   336  
   337  	s.trie.Commit()
   338  
   339  	s.Empty()
   340  }
   341  
   342  func (self *StateDB) Empty() {
   343  	self.stateObjects = make(map[string]*StateObject)
   344  	self.refund = new(big.Int)
   345  }
   346  
   347  func (self *StateDB) Refunds() *big.Int {
   348  	return self.refund
   349  }
   350  
   351  // SyncIntermediate updates the intermediate state and all mid steps
   352  func (self *StateDB) SyncIntermediate() {
   353  	self.refund = new(big.Int)
   354  
   355  	for _, stateObject := range self.stateObjects {
   356  		if stateObject.dirty {
   357  			if stateObject.remove {
   358  				self.DeleteStateObject(stateObject)
   359  			} else {
   360  				stateObject.Update()
   361  
   362  				self.UpdateStateObject(stateObject)
   363  			}
   364  			stateObject.dirty = false
   365  		}
   366  	}
   367  }
   368  
   369  // SyncObjects syncs the changed objects to the trie
   370  func (self *StateDB) SyncObjects() {
   371  	self.trie = trie.NewSecure(self.root[:], self.db)
   372  
   373  	self.refund = new(big.Int)
   374  
   375  	for _, stateObject := range self.stateObjects {
   376  		if stateObject.remove {
   377  			self.DeleteStateObject(stateObject)
   378  		} else {
   379  			stateObject.Update()
   380  
   381  			self.UpdateStateObject(stateObject)
   382  		}
   383  		stateObject.dirty = false
   384  	}
   385  }
   386  
   387  // Debug stuff
   388  func (self *StateDB) CreateOutputForDiff() {
   389  	for _, stateObject := range self.stateObjects {
   390  		stateObject.CreateOutputForDiff()
   391  	}
   392  }