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 }