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
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
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/wire"
  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. 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 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(acc.Address)
  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. }