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.

292 lines
7.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "sort"
  5. acm "github.com/tendermint/tendermint/account"
  6. "github.com/tendermint/tendermint/binary"
  7. . "github.com/tendermint/tendermint/common"
  8. dbm "github.com/tendermint/tendermint/db"
  9. "github.com/tendermint/tendermint/merkle"
  10. "github.com/tendermint/tendermint/types"
  11. )
  12. func makeStorage(db dbm.DB, root []byte) merkle.Tree {
  13. storage := merkle.NewIAVLTree(
  14. binary.BasicCodec,
  15. binary.BasicCodec,
  16. 1024,
  17. db,
  18. )
  19. storage.Load(root)
  20. return storage
  21. }
  22. type BlockCache struct {
  23. db dbm.DB
  24. backend *State
  25. accounts map[string]accountInfo
  26. storages map[Tuple256]storageInfo
  27. names map[string]nameInfo
  28. }
  29. func NewBlockCache(backend *State) *BlockCache {
  30. return &BlockCache{
  31. db: backend.DB,
  32. backend: backend,
  33. accounts: make(map[string]accountInfo),
  34. storages: make(map[Tuple256]storageInfo),
  35. names: make(map[string]nameInfo),
  36. }
  37. }
  38. func (cache *BlockCache) State() *State {
  39. return cache.backend
  40. }
  41. //-------------------------------------
  42. // BlockCache.account
  43. func (cache *BlockCache) GetAccount(addr []byte) *acm.Account {
  44. acc, _, removed, _ := cache.accounts[string(addr)].unpack()
  45. if removed {
  46. return nil
  47. } else if acc != nil {
  48. return acc
  49. } else {
  50. acc = cache.backend.GetAccount(addr)
  51. cache.accounts[string(addr)] = accountInfo{acc, nil, false, false}
  52. return acc
  53. }
  54. }
  55. func (cache *BlockCache) UpdateAccount(acc *acm.Account) {
  56. addr := acc.Address
  57. _, storage, removed, _ := cache.accounts[string(addr)].unpack()
  58. if removed {
  59. PanicSanity("UpdateAccount on a removed account")
  60. }
  61. cache.accounts[string(addr)] = accountInfo{acc, storage, false, true}
  62. }
  63. func (cache *BlockCache) RemoveAccount(addr []byte) {
  64. _, _, removed, _ := cache.accounts[string(addr)].unpack()
  65. if removed {
  66. PanicSanity("RemoveAccount on a removed account")
  67. }
  68. cache.accounts[string(addr)] = accountInfo{nil, nil, true, false}
  69. }
  70. // BlockCache.account
  71. //-------------------------------------
  72. // BlockCache.storage
  73. func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
  74. // Check cache
  75. info, ok := cache.storages[Tuple256{addr, key}]
  76. if ok {
  77. return info.value
  78. }
  79. // Get or load storage
  80. acc, storage, removed, dirty := cache.accounts[string(addr.Postfix(20))].unpack()
  81. if removed {
  82. PanicSanity("GetStorage() on removed account")
  83. }
  84. if acc != nil && storage == nil {
  85. storage = makeStorage(cache.db, acc.StorageRoot)
  86. cache.accounts[string(addr.Postfix(20))] = accountInfo{acc, storage, false, dirty}
  87. } else if acc == nil {
  88. return Zero256
  89. }
  90. // Load and set cache
  91. _, val_ := storage.Get(key.Bytes())
  92. value = Zero256
  93. if val_ != nil {
  94. value = LeftPadWord256(val_.([]byte))
  95. }
  96. cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
  97. return value
  98. }
  99. // NOTE: Set value to zero to removed from the trie.
  100. func (cache *BlockCache) SetStorage(addr Word256, key Word256, value Word256) {
  101. _, _, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
  102. if removed {
  103. PanicSanity("SetStorage() on a removed account")
  104. }
  105. cache.storages[Tuple256{addr, key}] = storageInfo{value, true}
  106. }
  107. // BlockCache.storage
  108. //-------------------------------------
  109. // BlockCache.names
  110. func (cache *BlockCache) GetNameRegEntry(name string) *types.NameRegEntry {
  111. entry, removed, _ := cache.names[name].unpack()
  112. if removed {
  113. return nil
  114. } else if entry != nil {
  115. return entry
  116. } else {
  117. entry = cache.backend.GetNameRegEntry(name)
  118. cache.names[name] = nameInfo{entry, false, false}
  119. return entry
  120. }
  121. }
  122. func (cache *BlockCache) UpdateNameRegEntry(entry *types.NameRegEntry) {
  123. name := entry.Name
  124. cache.names[name] = nameInfo{entry, false, true}
  125. }
  126. func (cache *BlockCache) RemoveNameRegEntry(name string) {
  127. _, removed, _ := cache.names[name].unpack()
  128. if removed {
  129. PanicSanity("RemoveNameRegEntry on a removed entry")
  130. }
  131. cache.names[name] = nameInfo{nil, true, false}
  132. }
  133. // BlockCache.names
  134. //-------------------------------------
  135. // CONTRACT the updates are in deterministic order.
  136. func (cache *BlockCache) Sync() {
  137. // Determine order for storage updates
  138. // The address comes first so it'll be grouped.
  139. storageKeys := make([]Tuple256, 0, len(cache.storages))
  140. for keyTuple := range cache.storages {
  141. storageKeys = append(storageKeys, keyTuple)
  142. }
  143. Tuple256Slice(storageKeys).Sort()
  144. // Update storage for all account/key.
  145. // Later we'll iterate over all the users and save storage + update storage root.
  146. var (
  147. curAddr Word256
  148. curAcc *acm.Account
  149. curAccRemoved bool
  150. curStorage merkle.Tree
  151. )
  152. for _, storageKey := range storageKeys {
  153. addr, key := Tuple256Split(storageKey)
  154. if addr != curAddr || curAcc == nil {
  155. acc, storage, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
  156. if storage == nil {
  157. storage = makeStorage(cache.db, acc.StorageRoot)
  158. }
  159. curAddr = addr
  160. curAcc = acc
  161. curAccRemoved = removed
  162. curStorage = storage
  163. }
  164. if curAccRemoved {
  165. continue
  166. }
  167. value, dirty := cache.storages[storageKey].unpack()
  168. if !dirty {
  169. continue
  170. }
  171. if value.IsZero() {
  172. curStorage.Remove(key.Bytes())
  173. } else {
  174. curStorage.Set(key.Bytes(), value.Bytes())
  175. cache.accounts[string(addr.Postfix(20))] = accountInfo{curAcc, curStorage, false, true}
  176. }
  177. }
  178. // Determine order for accounts
  179. addrStrs := []string{}
  180. for addrStr := range cache.accounts {
  181. addrStrs = append(addrStrs, addrStr)
  182. }
  183. sort.Strings(addrStrs)
  184. // Update or delete accounts.
  185. for _, addrStr := range addrStrs {
  186. acc, storage, removed, dirty := cache.accounts[addrStr].unpack()
  187. if removed {
  188. removed := cache.backend.RemoveAccount(acc.Address)
  189. if !removed {
  190. PanicCrisis(Fmt("Could not remove account to be removed: %X", acc.Address))
  191. }
  192. } else {
  193. if acc == nil {
  194. continue
  195. }
  196. if storage != nil {
  197. newStorageRoot := storage.Save()
  198. if !bytes.Equal(newStorageRoot, acc.StorageRoot) {
  199. acc.StorageRoot = newStorageRoot
  200. dirty = true
  201. }
  202. }
  203. if dirty {
  204. cache.backend.UpdateAccount(acc)
  205. }
  206. }
  207. }
  208. // Determine order for names
  209. // note names may be of any length less than some limit
  210. nameStrs := []string{}
  211. for nameStr := range cache.names {
  212. nameStrs = append(nameStrs, nameStr)
  213. }
  214. sort.Strings(nameStrs)
  215. // Update or delete names.
  216. for _, nameStr := range nameStrs {
  217. entry, removed, dirty := cache.names[nameStr].unpack()
  218. if removed {
  219. removed := cache.backend.RemoveNameRegEntry(nameStr)
  220. if !removed {
  221. PanicCrisis(Fmt("Could not remove namereg entry to be removed: %s", nameStr))
  222. }
  223. } else {
  224. if entry == nil {
  225. continue
  226. }
  227. if dirty {
  228. cache.backend.UpdateNameRegEntry(entry)
  229. }
  230. }
  231. }
  232. }
  233. //-----------------------------------------------------------------------------
  234. type accountInfo struct {
  235. account *acm.Account
  236. storage merkle.Tree
  237. removed bool
  238. dirty bool
  239. }
  240. func (accInfo accountInfo) unpack() (*acm.Account, merkle.Tree, bool, bool) {
  241. return accInfo.account, accInfo.storage, accInfo.removed, accInfo.dirty
  242. }
  243. type storageInfo struct {
  244. value Word256
  245. dirty bool
  246. }
  247. func (stjInfo storageInfo) unpack() (Word256, bool) {
  248. return stjInfo.value, stjInfo.dirty
  249. }
  250. type nameInfo struct {
  251. name *types.NameRegEntry
  252. removed bool
  253. dirty bool
  254. }
  255. func (nInfo nameInfo) unpack() (*types.NameRegEntry, bool, bool) {
  256. return nInfo.name, nInfo.removed, nInfo.dirty
  257. }