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.

293 lines
7.2 KiB

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