github.com/aergoio/aergo@v1.3.1/state/contract.go (about)

     1  package state
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"github.com/aergoio/aergo-lib/db"
     7  	"github.com/aergoio/aergo/internal/common"
     8  	"github.com/aergoio/aergo/types"
     9  	"github.com/golang/protobuf/proto"
    10  )
    11  
    12  func (states *StateDB) OpenContractStateAccount(aid types.AccountID) (*ContractState, error) {
    13  	st, err := states.GetAccountState(aid)
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  	return states.OpenContractState(aid, st)
    18  }
    19  func (states *StateDB) OpenContractState(aid types.AccountID, st *types.State) (*ContractState, error) {
    20  	storage := states.cache.get(aid)
    21  	if storage == nil {
    22  		root := common.Compactz(st.StorageRoot)
    23  		storage = newBufferedStorage(root, states.store)
    24  	}
    25  	res := &ContractState{
    26  		State:   st,
    27  		account: aid,
    28  		storage: storage,
    29  		store:   states.store,
    30  	}
    31  	return res, nil
    32  }
    33  
    34  func (states *StateDB) StageContractState(st *ContractState) error {
    35  	states.cache.put(st.account, st.storage)
    36  	st.storage = nil
    37  	return nil
    38  }
    39  
    40  // GetSystemAccountState returns the ContractState of the AERGO system account.
    41  func (states *StateDB) GetSystemAccountState() (*ContractState, error) {
    42  	return states.OpenContractStateAccount(types.ToAccountID([]byte(types.AergoSystem)))
    43  }
    44  
    45  // GetNameAccountState returns the ContractState of the AERGO name account.
    46  func (states *StateDB) GetNameAccountState() (*ContractState, error) {
    47  	return states.OpenContractStateAccount(types.ToAccountID([]byte(types.AergoName)))
    48  }
    49  
    50  // GetEnterpriseAccountState returns the ContractState of the AERGO enterprise account.
    51  func (states *StateDB) GetEnterpriseAccountState() (*ContractState, error) {
    52  	return states.OpenContractStateAccount(types.ToAccountID([]byte(types.AergoEnterprise)))
    53  }
    54  
    55  type ContractState struct {
    56  	*types.State
    57  	account types.AccountID
    58  	code    []byte
    59  	storage *bufferedStorage
    60  	store   db.DB
    61  }
    62  
    63  func (st *ContractState) SetNonce(nonce uint64) {
    64  	st.State.Nonce = nonce
    65  }
    66  func (st *ContractState) GetNonce() uint64 {
    67  	return st.State.GetNonce()
    68  }
    69  
    70  func (st *ContractState) SetBalance(balance *big.Int) {
    71  	st.State.Balance = balance.Bytes()
    72  }
    73  func (st *ContractState) GetBalance() *big.Int {
    74  	return new(big.Int).SetBytes(st.State.GetBalance())
    75  }
    76  
    77  func (st *ContractState) SetCode(code []byte) error {
    78  	codeHash := common.Hasher(code)
    79  	err := saveData(st.store, codeHash[:], &code)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	st.State.CodeHash = codeHash[:]
    84  	st.code = code
    85  	return nil
    86  }
    87  func (st *ContractState) GetCode() ([]byte, error) {
    88  	if st.code != nil {
    89  		// already loaded.
    90  		return st.code, nil
    91  	}
    92  	codeHash := st.State.GetCodeHash()
    93  	if codeHash == nil {
    94  		// not defined. do nothing.
    95  		return nil, nil
    96  	}
    97  	err := loadData(st.store, st.State.CodeHash, &st.code)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return st.code, nil
   102  }
   103  
   104  // HasKey returns existence of the key
   105  func (st *ContractState) HasKey(key []byte) bool {
   106  	return st.storage.has(types.GetHashID(key), true)
   107  }
   108  
   109  // SetData store key and value pair to the storage.
   110  func (st *ContractState) SetData(key, value []byte) error {
   111  	st.storage.put(newValueEntry(types.GetHashID(key), value))
   112  	return nil
   113  }
   114  
   115  // GetData returns the value corresponding to the key from the buffered storage.
   116  func (st *ContractState) GetData(key []byte) ([]byte, error) {
   117  	id := types.GetHashID(key)
   118  	if entry := st.storage.get(id); entry != nil {
   119  		if value := entry.Value(); value != nil {
   120  			return value.([]byte), nil
   121  		}
   122  		return nil, nil
   123  	}
   124  	return st.getInitialData(id[:])
   125  }
   126  
   127  func (st *ContractState) getInitialData(id []byte) ([]byte, error) {
   128  	dkey, err := st.storage.trie.Get(id)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	if len(dkey) == 0 {
   133  		return nil, nil
   134  	}
   135  	value := []byte{}
   136  	if err := loadData(st.store, dkey, &value); err != nil {
   137  		return nil, err
   138  	}
   139  	return value, nil
   140  }
   141  
   142  // GetInitialData returns the value corresponding to the key from the contract storage.
   143  func (st *ContractState) GetInitialData(key []byte) ([]byte, error) {
   144  	id := types.GetHashID(key)
   145  	return st.getInitialData(id[:])
   146  }
   147  
   148  // DeleteData remove key and value pair from the storage.
   149  func (st *ContractState) DeleteData(key []byte) error {
   150  	st.storage.put(newValueEntryDelete(types.GetHashID(key)))
   151  	return nil
   152  }
   153  
   154  // Snapshot returns revision number of storage buffer
   155  func (st *ContractState) Snapshot() Snapshot {
   156  	return Snapshot(st.storage.buffer.snapshot())
   157  }
   158  
   159  // Rollback discards changes of storage buffer to revision number
   160  func (st *ContractState) Rollback(revision Snapshot) error {
   161  	return st.storage.buffer.rollback(int(revision))
   162  }
   163  
   164  // Hash implements types.ImplHashBytes
   165  func (st *ContractState) Hash() []byte {
   166  	return getHashBytes(st.State)
   167  }
   168  
   169  // Marshal implements types.ImplMarshal
   170  func (st *ContractState) Marshal() ([]byte, error) {
   171  	return proto.Marshal(st.State)
   172  }
   173  
   174  func (st *ContractState) cache() *stateBuffer {
   175  	return st.storage.buffer
   176  }