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.

304 lines
7.4 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
9 years ago
9 years ago
  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. 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) *ac.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 *ac.Account) {
  56. addr := acc.Address
  57. // SANITY CHECK
  58. _, storage, removed, _ := cache.accounts[string(addr)].unpack()
  59. if removed {
  60. panic("UpdateAccount on a removed account")
  61. }
  62. // SANITY CHECK END
  63. cache.accounts[string(addr)] = accountInfo{acc, storage, false, true}
  64. }
  65. func (cache *BlockCache) RemoveAccount(addr []byte) {
  66. // SANITY CHECK
  67. _, _, removed, _ := cache.accounts[string(addr)].unpack()
  68. if removed {
  69. panic("RemoveAccount on a removed account")
  70. }
  71. // SANITY CHECK END
  72. cache.accounts[string(addr)] = accountInfo{nil, nil, true, false}
  73. }
  74. // BlockCache.account
  75. //-------------------------------------
  76. // BlockCache.storage
  77. func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
  78. // Check cache
  79. info, ok := cache.storages[Tuple256{addr, key}]
  80. if ok {
  81. return info.value
  82. }
  83. // Get or load storage
  84. acc, storage, removed, dirty := cache.accounts[string(addr.Postfix(20))].unpack()
  85. if removed {
  86. panic("GetStorage() on removed account")
  87. }
  88. if acc != nil && storage == nil {
  89. storage = makeStorage(cache.db, acc.StorageRoot)
  90. cache.accounts[string(addr.Postfix(20))] = accountInfo{acc, storage, false, dirty}
  91. } else if acc == nil {
  92. return Zero256
  93. }
  94. // Load and set cache
  95. _, val_ := storage.Get(key.Bytes())
  96. value = Zero256
  97. if val_ != nil {
  98. value = LeftPadWord256(val_.([]byte))
  99. }
  100. cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
  101. return value
  102. }
  103. // NOTE: Set value to zero to removed from the trie.
  104. func (cache *BlockCache) SetStorage(addr Word256, key Word256, value Word256) {
  105. _, _, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
  106. if removed {
  107. panic("SetStorage() on a removed account")
  108. }
  109. cache.storages[Tuple256{addr, key}] = storageInfo{value, true}
  110. }
  111. // BlockCache.storage
  112. //-------------------------------------
  113. // BlockCache.names
  114. func (cache *BlockCache) GetNameRegEntry(name string) *types.NameRegEntry {
  115. entry, removed, _ := cache.names[name].unpack()
  116. if removed {
  117. return nil
  118. } else if entry != nil {
  119. return entry
  120. } else {
  121. entry = cache.backend.GetNameRegEntry(name)
  122. cache.names[name] = nameInfo{entry, false, false}
  123. return entry
  124. }
  125. }
  126. func (cache *BlockCache) UpdateNameRegEntry(entry *types.NameRegEntry) {
  127. name := entry.Name
  128. // SANITY CHECK
  129. _, removed, _ := cache.names[name].unpack()
  130. if removed {
  131. panic("UpdateNameRegEntry on a removed name")
  132. }
  133. // SANITY CHECK END
  134. cache.names[name] = nameInfo{entry, false, true}
  135. }
  136. func (cache *BlockCache) RemoveNameRegEntry(name string) {
  137. // SANITY CHECK
  138. _, removed, _ := cache.names[name].unpack()
  139. if removed {
  140. panic("RemoveNameRegEntry on a removed entry")
  141. }
  142. // SANITY CHECK END
  143. cache.names[name] = nameInfo{nil, true, false}
  144. }
  145. // BlockCache.names
  146. //-------------------------------------
  147. // CONTRACT the updates are in deterministic order.
  148. func (cache *BlockCache) Sync() {
  149. // Determine order for storage updates
  150. // The address comes first so it'll be grouped.
  151. storageKeys := make([]Tuple256, 0, len(cache.storages))
  152. for keyTuple := range cache.storages {
  153. storageKeys = append(storageKeys, keyTuple)
  154. }
  155. Tuple256Slice(storageKeys).Sort()
  156. // Update storage for all account/key.
  157. // Later we'll iterate over all the users and save storage + update storage root.
  158. var (
  159. curAddr Word256
  160. curAcc *ac.Account
  161. curAccRemoved bool
  162. curStorage merkle.Tree
  163. )
  164. for _, storageKey := range storageKeys {
  165. addr, key := Tuple256Split(storageKey)
  166. if addr != curAddr || curAcc == nil {
  167. acc, storage, removed, _ := cache.accounts[string(addr.Postfix(20))].unpack()
  168. if storage == nil {
  169. storage = makeStorage(cache.db, acc.StorageRoot)
  170. }
  171. curAddr = addr
  172. curAcc = acc
  173. curAccRemoved = removed
  174. curStorage = storage
  175. }
  176. if curAccRemoved {
  177. continue
  178. }
  179. value, dirty := cache.storages[storageKey].unpack()
  180. if !dirty {
  181. continue
  182. }
  183. if value.IsZero() {
  184. curStorage.Remove(key.Bytes())
  185. } else {
  186. curStorage.Set(key.Bytes(), value.Bytes())
  187. cache.accounts[string(addr.Postfix(20))] = accountInfo{curAcc, curStorage, false, true}
  188. }
  189. }
  190. // Determine order for accounts
  191. addrStrs := []string{}
  192. for addrStr := range cache.accounts {
  193. addrStrs = append(addrStrs, addrStr)
  194. }
  195. sort.Strings(addrStrs)
  196. // Update or delete accounts.
  197. for _, addrStr := range addrStrs {
  198. acc, storage, removed, dirty := cache.accounts[addrStr].unpack()
  199. if removed {
  200. removed := cache.backend.RemoveAccount(acc.Address)
  201. if !removed {
  202. panic(Fmt("Could not remove account to be removed: %X", acc.Address))
  203. }
  204. } else {
  205. if acc == nil {
  206. continue
  207. }
  208. if storage != nil {
  209. newStorageRoot := storage.Save()
  210. if !bytes.Equal(newStorageRoot, acc.StorageRoot) {
  211. acc.StorageRoot = newStorageRoot
  212. dirty = true
  213. }
  214. }
  215. if dirty {
  216. cache.backend.UpdateAccount(acc)
  217. }
  218. }
  219. }
  220. // Determine order for names
  221. // note names may be of any length less than some limit
  222. nameStrs := []string{}
  223. for nameStr := range cache.names {
  224. nameStrs = append(nameStrs, nameStr)
  225. }
  226. sort.Strings(nameStrs)
  227. // Update or delete names.
  228. for _, nameStr := range nameStrs {
  229. entry, removed, dirty := cache.names[nameStr].unpack()
  230. if removed {
  231. removed := cache.backend.RemoveNameRegEntry(nameStr)
  232. if !removed {
  233. panic(Fmt("Could not remove namereg entry to be removed: %s", nameStr))
  234. }
  235. } else {
  236. if entry == nil {
  237. continue
  238. }
  239. if dirty {
  240. cache.backend.UpdateNameRegEntry(entry)
  241. }
  242. }
  243. }
  244. }
  245. //-----------------------------------------------------------------------------
  246. type accountInfo struct {
  247. account *ac.Account
  248. storage merkle.Tree
  249. removed bool
  250. dirty bool
  251. }
  252. func (accInfo accountInfo) unpack() (*ac.Account, merkle.Tree, bool, bool) {
  253. return accInfo.account, accInfo.storage, accInfo.removed, accInfo.dirty
  254. }
  255. type storageInfo struct {
  256. value Word256
  257. dirty bool
  258. }
  259. func (stjInfo storageInfo) unpack() (Word256, bool) {
  260. return stjInfo.value, stjInfo.dirty
  261. }
  262. type nameInfo struct {
  263. name *types.NameRegEntry
  264. removed bool
  265. dirty bool
  266. }
  267. func (nInfo nameInfo) unpack() (*types.NameRegEntry, bool, bool) {
  268. return nInfo.name, nInfo.removed, nInfo.dirty
  269. }