accessors_chain_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package rawdb
  17. import (
  18. "bytes"
  19. "encoding/hex"
  20. "fmt"
  21. "io/ioutil"
  22. "math/big"
  23. "os"
  24. "testing"
  25. "github.com/ethereum/go-ethereum/common"
  26. "github.com/ethereum/go-ethereum/core/types"
  27. "github.com/ethereum/go-ethereum/params"
  28. "github.com/ethereum/go-ethereum/rlp"
  29. "golang.org/x/crypto/sha3"
  30. )
  31. // Tests block header storage and retrieval operations.
  32. func TestHeaderStorage(t *testing.T) {
  33. db := NewMemoryDatabase()
  34. // Create a test header to move around the database and make sure it's really new
  35. header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
  36. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
  37. t.Fatalf("Non existent header returned: %v", entry)
  38. }
  39. // Write and verify the header in the database
  40. WriteHeader(db, header)
  41. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil {
  42. t.Fatalf("Stored header not found")
  43. } else if entry.Hash() != header.Hash() {
  44. t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header)
  45. }
  46. if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil {
  47. t.Fatalf("Stored header RLP not found")
  48. } else {
  49. hasher := sha3.NewLegacyKeccak256()
  50. hasher.Write(entry)
  51. if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() {
  52. t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header)
  53. }
  54. }
  55. // Delete the header and verify the execution
  56. DeleteHeader(db, header.Hash(), header.Number.Uint64())
  57. if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
  58. t.Fatalf("Deleted header returned: %v", entry)
  59. }
  60. }
  61. // Tests block body storage and retrieval operations.
  62. func TestBodyStorage(t *testing.T) {
  63. db := NewMemoryDatabase()
  64. // Create a test body to move around the database and make sure it's really new
  65. body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
  66. hasher := sha3.NewLegacyKeccak256()
  67. rlp.Encode(hasher, body)
  68. hash := common.BytesToHash(hasher.Sum(nil))
  69. if entry := ReadBody(db, hash, 0); entry != nil {
  70. t.Fatalf("Non existent body returned: %v", entry)
  71. }
  72. // Write and verify the body in the database
  73. WriteBody(db, hash, 0, body)
  74. if entry := ReadBody(db, hash, 0); entry == nil {
  75. t.Fatalf("Stored body not found")
  76. } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(types.Transactions(body.Transactions)) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) {
  77. t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body)
  78. }
  79. if entry := ReadBodyRLP(db, hash, 0); entry == nil {
  80. t.Fatalf("Stored body RLP not found")
  81. } else {
  82. hasher := sha3.NewLegacyKeccak256()
  83. hasher.Write(entry)
  84. if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash {
  85. t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body)
  86. }
  87. }
  88. // Delete the body and verify the execution
  89. DeleteBody(db, hash, 0)
  90. if entry := ReadBody(db, hash, 0); entry != nil {
  91. t.Fatalf("Deleted body returned: %v", entry)
  92. }
  93. }
  94. // Tests block storage and retrieval operations.
  95. func TestBlockStorage(t *testing.T) {
  96. db := NewMemoryDatabase()
  97. // Create a test block to move around the database and make sure it's really new
  98. block := types.NewBlockWithHeader(&types.Header{
  99. Extra: []byte("test block"),
  100. UncleHash: types.EmptyUncleHash,
  101. TxHash: types.EmptyRootHash,
  102. ReceiptHash: types.EmptyRootHash,
  103. })
  104. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  105. t.Fatalf("Non existent block returned: %v", entry)
  106. }
  107. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
  108. t.Fatalf("Non existent header returned: %v", entry)
  109. }
  110. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
  111. t.Fatalf("Non existent body returned: %v", entry)
  112. }
  113. // Write and verify the block in the database
  114. WriteBlock(db, block)
  115. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
  116. t.Fatalf("Stored block not found")
  117. } else if entry.Hash() != block.Hash() {
  118. t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
  119. }
  120. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil {
  121. t.Fatalf("Stored header not found")
  122. } else if entry.Hash() != block.Header().Hash() {
  123. t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header())
  124. }
  125. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil {
  126. t.Fatalf("Stored body not found")
  127. } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(block.Transactions()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) {
  128. t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body())
  129. }
  130. // Delete the block and verify the execution
  131. DeleteBlock(db, block.Hash(), block.NumberU64())
  132. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  133. t.Fatalf("Deleted block returned: %v", entry)
  134. }
  135. if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
  136. t.Fatalf("Deleted header returned: %v", entry)
  137. }
  138. if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
  139. t.Fatalf("Deleted body returned: %v", entry)
  140. }
  141. }
  142. // Tests that partial block contents don't get reassembled into full blocks.
  143. func TestPartialBlockStorage(t *testing.T) {
  144. db := NewMemoryDatabase()
  145. block := types.NewBlockWithHeader(&types.Header{
  146. Extra: []byte("test block"),
  147. UncleHash: types.EmptyUncleHash,
  148. TxHash: types.EmptyRootHash,
  149. ReceiptHash: types.EmptyRootHash,
  150. })
  151. // Store a header and check that it's not recognized as a block
  152. WriteHeader(db, block.Header())
  153. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  154. t.Fatalf("Non existent block returned: %v", entry)
  155. }
  156. DeleteHeader(db, block.Hash(), block.NumberU64())
  157. // Store a body and check that it's not recognized as a block
  158. WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
  159. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
  160. t.Fatalf("Non existent block returned: %v", entry)
  161. }
  162. DeleteBody(db, block.Hash(), block.NumberU64())
  163. // Store a header and a body separately and check reassembly
  164. WriteHeader(db, block.Header())
  165. WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
  166. if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
  167. t.Fatalf("Stored block not found")
  168. } else if entry.Hash() != block.Hash() {
  169. t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
  170. }
  171. }
  172. // Tests block total difficulty storage and retrieval operations.
  173. func TestTdStorage(t *testing.T) {
  174. db := NewMemoryDatabase()
  175. // Create a test TD to move around the database and make sure it's really new
  176. hash, td := common.Hash{}, big.NewInt(314)
  177. if entry := ReadTd(db, hash, 0); entry != nil {
  178. t.Fatalf("Non existent TD returned: %v", entry)
  179. }
  180. // Write and verify the TD in the database
  181. WriteTd(db, hash, 0, td)
  182. if entry := ReadTd(db, hash, 0); entry == nil {
  183. t.Fatalf("Stored TD not found")
  184. } else if entry.Cmp(td) != 0 {
  185. t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td)
  186. }
  187. // Delete the TD and verify the execution
  188. DeleteTd(db, hash, 0)
  189. if entry := ReadTd(db, hash, 0); entry != nil {
  190. t.Fatalf("Deleted TD returned: %v", entry)
  191. }
  192. }
  193. // Tests that canonical numbers can be mapped to hashes and retrieved.
  194. func TestCanonicalMappingStorage(t *testing.T) {
  195. db := NewMemoryDatabase()
  196. // Create a test canonical number and assinged hash to move around
  197. hash, number := common.Hash{0: 0xff}, uint64(314)
  198. if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
  199. t.Fatalf("Non existent canonical mapping returned: %v", entry)
  200. }
  201. // Write and verify the TD in the database
  202. WriteCanonicalHash(db, hash, number)
  203. if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) {
  204. t.Fatalf("Stored canonical mapping not found")
  205. } else if entry != hash {
  206. t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash)
  207. }
  208. // Delete the TD and verify the execution
  209. DeleteCanonicalHash(db, number)
  210. if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
  211. t.Fatalf("Deleted canonical mapping returned: %v", entry)
  212. }
  213. }
  214. // Tests that head headers and head blocks can be assigned, individually.
  215. func TestHeadStorage(t *testing.T) {
  216. db := NewMemoryDatabase()
  217. blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
  218. blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
  219. blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")})
  220. // Check that no head entries are in a pristine database
  221. if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) {
  222. t.Fatalf("Non head header entry returned: %v", entry)
  223. }
  224. if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) {
  225. t.Fatalf("Non head block entry returned: %v", entry)
  226. }
  227. if entry := ReadHeadFastBlockHash(db); entry != (common.Hash{}) {
  228. t.Fatalf("Non fast head block entry returned: %v", entry)
  229. }
  230. // Assign separate entries for the head header and block
  231. WriteHeadHeaderHash(db, blockHead.Hash())
  232. WriteHeadBlockHash(db, blockFull.Hash())
  233. WriteHeadFastBlockHash(db, blockFast.Hash())
  234. // Check that both heads are present, and different (i.e. two heads maintained)
  235. if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() {
  236. t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash())
  237. }
  238. if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() {
  239. t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash())
  240. }
  241. if entry := ReadHeadFastBlockHash(db); entry != blockFast.Hash() {
  242. t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash())
  243. }
  244. }
  245. // Tests that receipts associated with a single block can be stored and retrieved.
  246. func TestBlockReceiptStorage(t *testing.T) {
  247. db := NewMemoryDatabase()
  248. // Create a live block since we need metadata to reconstruct the receipt
  249. tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
  250. tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
  251. body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
  252. // Create the two receipts to manage afterwards
  253. receipt1 := &types.Receipt{
  254. Status: types.ReceiptStatusFailed,
  255. CumulativeGasUsed: 1,
  256. Logs: []*types.Log{
  257. {Address: common.BytesToAddress([]byte{0x11})},
  258. {Address: common.BytesToAddress([]byte{0x01, 0x11})},
  259. },
  260. TxHash: tx1.Hash(),
  261. ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
  262. GasUsed: 111111,
  263. }
  264. receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
  265. receipt2 := &types.Receipt{
  266. PostState: common.Hash{2}.Bytes(),
  267. CumulativeGasUsed: 2,
  268. Logs: []*types.Log{
  269. {Address: common.BytesToAddress([]byte{0x22})},
  270. {Address: common.BytesToAddress([]byte{0x02, 0x22})},
  271. },
  272. TxHash: tx2.Hash(),
  273. ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
  274. GasUsed: 222222,
  275. }
  276. receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
  277. receipts := []*types.Receipt{receipt1, receipt2}
  278. // Check that no receipt entries are in a pristine database
  279. hash := common.BytesToHash([]byte{0x03, 0x14})
  280. if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
  281. t.Fatalf("non existent receipts returned: %v", rs)
  282. }
  283. // Insert the body that corresponds to the receipts
  284. WriteBody(db, hash, 0, body)
  285. // Insert the receipt slice into the database and check presence
  286. WriteReceipts(db, hash, 0, receipts)
  287. if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
  288. t.Fatalf("no receipts returned")
  289. } else {
  290. if err := checkReceiptsRLP(rs, receipts); err != nil {
  291. t.Fatalf(err.Error())
  292. }
  293. }
  294. // Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
  295. DeleteBody(db, hash, 0)
  296. if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
  297. t.Fatalf("receipts returned when body was deleted: %v", rs)
  298. }
  299. // Ensure that receipts without metadata can be returned without the block body too
  300. if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
  301. t.Fatalf(err.Error())
  302. }
  303. // Sanity check that body alone without the receipt is a full purge
  304. WriteBody(db, hash, 0, body)
  305. DeleteReceipts(db, hash, 0)
  306. if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
  307. t.Fatalf("deleted receipts returned: %v", rs)
  308. }
  309. }
  310. func checkReceiptsRLP(have, want types.Receipts) error {
  311. if len(have) != len(want) {
  312. return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want))
  313. }
  314. for i := 0; i < len(want); i++ {
  315. rlpHave, err := rlp.EncodeToBytes(have[i])
  316. if err != nil {
  317. return err
  318. }
  319. rlpWant, err := rlp.EncodeToBytes(want[i])
  320. if err != nil {
  321. return err
  322. }
  323. if !bytes.Equal(rlpHave, rlpWant) {
  324. return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant))
  325. }
  326. }
  327. return nil
  328. }
  329. func TestAncientStorage(t *testing.T) {
  330. // Freezer style fast import the chain.
  331. frdir, err := ioutil.TempDir("", "")
  332. if err != nil {
  333. t.Fatalf("failed to create temp freezer dir: %v", err)
  334. }
  335. defer os.Remove(frdir)
  336. db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "")
  337. if err != nil {
  338. t.Fatalf("failed to create database with ancient backend")
  339. }
  340. // Create a test block
  341. block := types.NewBlockWithHeader(&types.Header{
  342. Number: big.NewInt(0),
  343. Extra: []byte("test block"),
  344. UncleHash: types.EmptyUncleHash,
  345. TxHash: types.EmptyRootHash,
  346. ReceiptHash: types.EmptyRootHash,
  347. })
  348. // Ensure nothing non-existent will be read
  349. hash, number := block.Hash(), block.NumberU64()
  350. if blob := ReadHeaderRLP(db, hash, number); len(blob) > 0 {
  351. t.Fatalf("non existent header returned")
  352. }
  353. if blob := ReadBodyRLP(db, hash, number); len(blob) > 0 {
  354. t.Fatalf("non existent body returned")
  355. }
  356. if blob := ReadReceiptsRLP(db, hash, number); len(blob) > 0 {
  357. t.Fatalf("non existent receipts returned")
  358. }
  359. if blob := ReadTdRLP(db, hash, number); len(blob) > 0 {
  360. t.Fatalf("non existent td returned")
  361. }
  362. // Write and verify the header in the database
  363. WriteAncientBlock(db, block, nil, big.NewInt(100))
  364. if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 {
  365. t.Fatalf("no header returned")
  366. }
  367. if blob := ReadBodyRLP(db, hash, number); len(blob) == 0 {
  368. t.Fatalf("no body returned")
  369. }
  370. if blob := ReadReceiptsRLP(db, hash, number); len(blob) == 0 {
  371. t.Fatalf("no receipts returned")
  372. }
  373. if blob := ReadTdRLP(db, hash, number); len(blob) == 0 {
  374. t.Fatalf("no td returned")
  375. }
  376. // Use a fake hash for data retrieval, nothing should be returned.
  377. fakeHash := common.BytesToHash([]byte{0x01, 0x02, 0x03})
  378. if blob := ReadHeaderRLP(db, fakeHash, number); len(blob) != 0 {
  379. t.Fatalf("invalid header returned")
  380. }
  381. if blob := ReadBodyRLP(db, fakeHash, number); len(blob) != 0 {
  382. t.Fatalf("invalid body returned")
  383. }
  384. if blob := ReadReceiptsRLP(db, fakeHash, number); len(blob) != 0 {
  385. t.Fatalf("invalid receipts returned")
  386. }
  387. if blob := ReadTdRLP(db, fakeHash, number); len(blob) != 0 {
  388. t.Fatalf("invalid td returned")
  389. }
  390. }