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.

217 lines
5.6 KiB

  1. package state
  2. import (
  3. "sort"
  4. ac "github.com/tendermint/tendermint/account"
  5. "github.com/tendermint/tendermint/binary"
  6. . "github.com/tendermint/tendermint/common"
  7. "github.com/tendermint/tendermint/merkle"
  8. "github.com/tendermint/tendermint/vm"
  9. )
  10. // Converts state.Account to vm.Account struct.
  11. func toVMAccount(acc *ac.Account) *vm.Account {
  12. return &vm.Account{
  13. Address: vm.BytesToWord(acc.Address),
  14. Balance: acc.Balance,
  15. Code: acc.Code, // This is crazy.
  16. Nonce: uint64(acc.Sequence),
  17. StorageRoot: vm.BytesToWord(acc.StorageRoot),
  18. }
  19. }
  20. // Converts vm.Account to state.Account struct.
  21. func toStateAccount(acc *vm.Account) *ac.Account {
  22. return &ac.Account{
  23. Address: acc.Address.Address(),
  24. Balance: acc.Balance,
  25. Code: acc.Code,
  26. Sequence: uint(acc.Nonce),
  27. StorageRoot: acc.StorageRoot.Bytes(),
  28. }
  29. }
  30. //-----------------------------------------------------------------------------
  31. type AccountInfo struct {
  32. account *vm.Account
  33. deleted bool
  34. }
  35. type VMAppState struct {
  36. state *State
  37. accounts map[string]AccountInfo
  38. storage map[string]vm.Word
  39. logs []*vm.Log
  40. }
  41. func NewVMAppState(state *State) *VMAppState {
  42. return &VMAppState{
  43. state: state,
  44. accounts: make(map[string]AccountInfo),
  45. storage: make(map[string]vm.Word),
  46. logs: make([]*vm.Log, 0),
  47. }
  48. }
  49. func unpack(accInfo AccountInfo) (*vm.Account, bool) {
  50. return accInfo.account, accInfo.deleted
  51. }
  52. // Used to add the origin of the tx to VMAppState.
  53. func (vas *VMAppState) AddAccount(account *vm.Account) error {
  54. if _, ok := vas.accounts[account.Address.String()]; ok {
  55. return Errorf("Account already exists: %X", account.Address)
  56. } else {
  57. vas.accounts[account.Address.String()] = AccountInfo{account, false}
  58. return nil
  59. }
  60. }
  61. func (vas *VMAppState) GetAccount(addr vm.Word) (*vm.Account, error) {
  62. account, deleted := unpack(vas.accounts[addr.String()])
  63. if deleted {
  64. return nil, Errorf("Account was deleted: %X", addr)
  65. } else if account != nil {
  66. return account, nil
  67. } else {
  68. acc := vas.state.GetAccount(addr.Address())
  69. if acc == nil {
  70. return nil, Errorf("Invalid account addr: %X", addr)
  71. }
  72. return toVMAccount(acc), nil
  73. }
  74. }
  75. func (vas *VMAppState) UpdateAccount(account *vm.Account) error {
  76. accountInfo, ok := vas.accounts[account.Address.String()]
  77. if !ok {
  78. vas.accounts[account.Address.String()] = AccountInfo{account, false}
  79. return nil
  80. }
  81. account, deleted := unpack(accountInfo)
  82. if deleted {
  83. return Errorf("Account was deleted: %X", account.Address)
  84. } else {
  85. vas.accounts[account.Address.String()] = AccountInfo{account, false}
  86. return nil
  87. }
  88. }
  89. func (vas *VMAppState) DeleteAccount(account *vm.Account) error {
  90. accountInfo, ok := vas.accounts[account.Address.String()]
  91. if !ok {
  92. vas.accounts[account.Address.String()] = AccountInfo{account, true}
  93. return nil
  94. }
  95. account, deleted := unpack(accountInfo)
  96. if deleted {
  97. return Errorf("Account was already deleted: %X", account.Address)
  98. } else {
  99. vas.accounts[account.Address.String()] = AccountInfo{account, true}
  100. return nil
  101. }
  102. }
  103. func (vas *VMAppState) CreateAccount(addr vm.Word) (*vm.Account, error) {
  104. account, deleted := unpack(vas.accounts[addr.String()])
  105. if deleted || account == nil {
  106. account = &vm.Account{
  107. Address: addr,
  108. Balance: 0,
  109. Code: nil,
  110. Nonce: 0,
  111. StorageRoot: vm.Zero,
  112. }
  113. vas.accounts[addr.String()] = AccountInfo{account, false}
  114. return account, nil
  115. } else {
  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. func (vas *VMAppState) Sync() {
  146. // Determine order for accounts
  147. addrStrs := []string{}
  148. for addrStr := range vas.accounts {
  149. addrStrs = append(addrStrs, addrStr)
  150. }
  151. sort.Strings(addrStrs)
  152. // Update or delete accounts.
  153. for _, addrStr := range addrStrs {
  154. account, deleted := unpack(vas.accounts[addrStr])
  155. if deleted {
  156. removed := vas.state.RemoveAccount(account.Address.Address())
  157. if !removed {
  158. panic(Fmt("Could not remove account to be deleted: %X", account.Address))
  159. }
  160. } else {
  161. if account == nil {
  162. panic(Fmt("Account should not be nil for addr: %X", account.Address))
  163. }
  164. vas.state.UpdateAccount(toStateAccount(account))
  165. }
  166. }
  167. // Update or delete storage items.
  168. storage := merkle.NewIAVLTree(
  169. binary.BasicCodec, // TODO change
  170. binary.BasicCodec, // TODO change
  171. 1024, // TODO change.
  172. vas.state.DB,
  173. )
  174. for addrKey, value := range vas.storage {
  175. addrKeyBytes := []byte(addrKey)
  176. addr := addrKeyBytes[:32]
  177. key := addrKeyBytes[32:]
  178. if value.IsZero() {
  179. _, removed := storage.Remove(key)
  180. if !removed {
  181. panic(Fmt("Storage could not be removed for addr: %X @ %X", addr, key))
  182. }
  183. } else {
  184. storage.Set(key, value)
  185. }
  186. }
  187. // TODO support logs, add them to the state somehow.
  188. }
  189. func (vas *VMAppState) AddLog(log *vm.Log) {
  190. vas.logs = append(vas.logs, log)
  191. }