You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
6.6 KiB

  1. package state
  2. import (
  3. "bytes"
  4. "sort"
  5. ac "github.com/tendermint/tendermint/account"
  6. "github.com/tendermint/tendermint/binary"
  7. . "github.com/tendermint/tendermint/common"
  8. "github.com/tendermint/tendermint/merkle"
  9. "github.com/tendermint/tendermint/vm"
  10. "github.com/tendermint/tendermint/vm/sha3"
  11. )
  12. // Converts state.Account to vm.Account struct.
  13. func toVMAccount(acc *ac.Account) *vm.Account {
  14. return &vm.Account{
  15. Address: vm.BytesToWord(acc.Address),
  16. Balance: acc.Balance,
  17. Code: acc.Code, // This is crazy.
  18. Nonce: uint64(acc.Sequence),
  19. StorageRoot: vm.BytesToWord(acc.StorageRoot),
  20. }
  21. }
  22. // Converts vm.Account to state.Account struct.
  23. func toStateAccount(acc *vm.Account) *ac.Account {
  24. return &ac.Account{
  25. Address: acc.Address.Address(),
  26. Balance: acc.Balance,
  27. Code: acc.Code,
  28. Sequence: uint(acc.Nonce),
  29. StorageRoot: acc.StorageRoot.Bytes(),
  30. }
  31. }
  32. //-----------------------------------------------------------------------------
  33. type AccountInfo struct {
  34. account *vm.Account
  35. deleted bool
  36. }
  37. type VMAppState struct {
  38. state *State
  39. accounts map[string]AccountInfo
  40. storage map[string]vm.Word
  41. logs []*vm.Log
  42. }
  43. func NewVMAppState(state *State) *VMAppState {
  44. return &VMAppState{
  45. state: state,
  46. accounts: make(map[string]AccountInfo),
  47. storage: make(map[string]vm.Word),
  48. logs: make([]*vm.Log, 0),
  49. }
  50. }
  51. func unpack(accInfo AccountInfo) (*vm.Account, bool) {
  52. return accInfo.account, accInfo.deleted
  53. }
  54. func (vas *VMAppState) GetAccount(addr vm.Word) (*vm.Account, error) {
  55. account, deleted := unpack(vas.accounts[addr.String()])
  56. if deleted {
  57. return nil, Errorf("Account was deleted: %X", addr)
  58. } else if account != nil {
  59. return account, nil
  60. } else {
  61. acc := vas.state.GetAccount(addr.Address())
  62. if acc == nil {
  63. return nil, Errorf("Invalid account addr: %X", addr)
  64. }
  65. return toVMAccount(acc), nil
  66. }
  67. }
  68. func (vas *VMAppState) UpdateAccount(account *vm.Account) error {
  69. accountInfo, ok := vas.accounts[account.Address.String()]
  70. if !ok {
  71. vas.accounts[account.Address.String()] = AccountInfo{account, false}
  72. return nil
  73. }
  74. account, deleted := unpack(accountInfo)
  75. if deleted {
  76. return Errorf("Account was deleted: %X", account.Address)
  77. } else {
  78. vas.accounts[account.Address.String()] = AccountInfo{account, false}
  79. return nil
  80. }
  81. }
  82. func (vas *VMAppState) DeleteAccount(account *vm.Account) error {
  83. accountInfo, ok := vas.accounts[account.Address.String()]
  84. if !ok {
  85. vas.accounts[account.Address.String()] = AccountInfo{account, true}
  86. return nil
  87. }
  88. account, deleted := unpack(accountInfo)
  89. if deleted {
  90. return Errorf("Account was already deleted: %X", account.Address)
  91. } else {
  92. vas.accounts[account.Address.String()] = AccountInfo{account, true}
  93. return nil
  94. }
  95. }
  96. // Creates a 20 byte address and bumps the creator's nonce.
  97. func (vas *VMAppState) CreateAccount(creator *vm.Account) (*vm.Account, error) {
  98. // Generate an address
  99. nonce := creator.Nonce
  100. creator.Nonce += 1
  101. addr := vm.RightPadWord(NewContractAddress(creator.Address[:], nonce))
  102. // Create account from address.
  103. account, deleted := unpack(vas.accounts[addr.String()])
  104. if deleted || account == nil {
  105. account = &vm.Account{
  106. Address: addr,
  107. Balance: 0,
  108. Code: nil,
  109. Nonce: 0,
  110. StorageRoot: vm.Zero,
  111. }
  112. vas.accounts[addr.String()] = AccountInfo{account, false}
  113. return account, nil
  114. } else {
  115. panic(Fmt("Could not create account, address already exists: %X", addr))
  116. // return nil, Errorf("Account already exists: %X", addr)
  117. }
  118. }
  119. func (vas *VMAppState) GetStorage(addr vm.Word, key vm.Word) (vm.Word, error) {
  120. account, deleted := unpack(vas.accounts[addr.String()])
  121. if account == nil {
  122. return vm.Zero, Errorf("Invalid account addr: %X", addr)
  123. } else if deleted {
  124. return vm.Zero, Errorf("Account was deleted: %X", addr)
  125. }
  126. value, ok := vas.storage[addr.String()+key.String()]
  127. if ok {
  128. return value, nil
  129. } else {
  130. return vm.Zero, nil
  131. }
  132. }
  133. // NOTE: Set value to zero to delete from the trie.
  134. func (vas *VMAppState) SetStorage(addr vm.Word, key vm.Word, value vm.Word) (bool, error) {
  135. account, deleted := unpack(vas.accounts[addr.String()])
  136. if account == nil {
  137. return false, Errorf("Invalid account addr: %X", addr)
  138. } else if deleted {
  139. return false, Errorf("Account was deleted: %X", addr)
  140. }
  141. _, ok := vas.storage[addr.String()+key.String()]
  142. vas.storage[addr.String()+key.String()] = value
  143. return ok, nil
  144. }
  145. // CONTRACT the updates are in deterministic order.
  146. func (vas *VMAppState) Sync() {
  147. // Determine order for accounts
  148. addrStrs := []string{}
  149. for addrStr := range vas.accounts {
  150. addrStrs = append(addrStrs, addrStr)
  151. }
  152. sort.Strings(addrStrs)
  153. // Update or delete accounts.
  154. for _, addrStr := range addrStrs {
  155. account, deleted := unpack(vas.accounts[addrStr])
  156. if deleted {
  157. removed := vas.state.RemoveAccount(account.Address.Address())
  158. if !removed {
  159. panic(Fmt("Could not remove account to be deleted: %X", account.Address))
  160. }
  161. } else {
  162. if account == nil {
  163. panic(Fmt("Account should not be nil for addr: %X", account.Address))
  164. }
  165. vas.state.UpdateAccount(toStateAccount(account))
  166. }
  167. }
  168. // Determine order for storage updates
  169. // The address comes first so it'll be grouped.
  170. storageKeyStrs := []string{}
  171. for keyStr := range vas.storage {
  172. storageKeyStrs = append(storageKeyStrs, keyStr)
  173. }
  174. sort.Strings(storageKeyStrs)
  175. // Update storage for all account/key.
  176. storage := merkle.NewIAVLTree(
  177. binary.BasicCodec, // TODO change
  178. binary.BasicCodec, // TODO change
  179. 1024, // TODO change.
  180. vas.state.DB,
  181. )
  182. var currentAccount *vm.Account
  183. var deleted bool
  184. for _, storageKey := range storageKeyStrs {
  185. value := vas.storage[storageKey]
  186. addrKeyBytes := []byte(storageKey)
  187. addr := addrKeyBytes[:32]
  188. key := addrKeyBytes[32:]
  189. if currentAccount == nil || !bytes.Equal(currentAccount.Address[:], addr) {
  190. currentAccount, deleted = unpack(vas.accounts[string(addr)])
  191. if deleted {
  192. continue
  193. }
  194. storageRoot := currentAccount.StorageRoot
  195. storage.Load(storageRoot.Bytes())
  196. }
  197. if value.IsZero() {
  198. _, removed := storage.Remove(key)
  199. if !removed {
  200. panic(Fmt("Storage could not be removed for addr: %X @ %X", addr, key))
  201. }
  202. } else {
  203. storage.Set(key, value)
  204. }
  205. }
  206. // TODO support logs, add them to the state somehow.
  207. }
  208. func (vas *VMAppState) AddLog(log *vm.Log) {
  209. vas.logs = append(vas.logs, log)
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Convenience function to return address of new contract
  213. func NewContractAddress(caller []byte, nonce uint64) []byte {
  214. temp := make([]byte, 32+8)
  215. copy(temp, caller)
  216. vm.PutUint64(temp[32:], nonce)
  217. return sha3.Sha3(temp)[:20]
  218. }