github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/core/rawdb/accessors_chain.go (about) 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 17 package rawdb 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "math/big" 23 24 "github.com/zhiqiangxu/go-ethereum/common" 25 "github.com/zhiqiangxu/go-ethereum/core/types" 26 "github.com/zhiqiangxu/go-ethereum/crypto" 27 "github.com/zhiqiangxu/go-ethereum/ethdb" 28 "github.com/zhiqiangxu/go-ethereum/log" 29 "github.com/zhiqiangxu/go-ethereum/params" 30 "github.com/zhiqiangxu/go-ethereum/rlp" 31 ) 32 33 // ReadCanonicalHash retrieves the hash assigned to a canonical block number. 34 func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { 35 data, _ := db.Ancient(freezerHashTable, number) 36 if len(data) == 0 { 37 data, _ = db.Get(headerHashKey(number)) 38 // In the background freezer is moving data from leveldb to flatten files. 39 // So during the first check for ancient db, the data is not yet in there, 40 // but when we reach into leveldb, the data was already moved. That would 41 // result in a not found error. 42 if len(data) == 0 { 43 data, _ = db.Ancient(freezerHashTable, number) 44 } 45 } 46 if len(data) == 0 { 47 return common.Hash{} 48 } 49 return common.BytesToHash(data) 50 } 51 52 // WriteCanonicalHash stores the hash assigned to a canonical block number. 53 func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 54 if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { 55 log.Crit("Failed to store number to hash mapping", "err", err) 56 } 57 } 58 59 // DeleteCanonicalHash removes the number to hash canonical mapping. 60 func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) { 61 if err := db.Delete(headerHashKey(number)); err != nil { 62 log.Crit("Failed to delete number to hash mapping", "err", err) 63 } 64 } 65 66 // ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights, 67 // both canonical and reorged forks included. 68 func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash { 69 prefix := headerKeyPrefix(number) 70 71 hashes := make([]common.Hash, 0, 1) 72 it := db.NewIterator(prefix, nil) 73 defer it.Release() 74 75 for it.Next() { 76 if key := it.Key(); len(key) == len(prefix)+32 { 77 hashes = append(hashes, common.BytesToHash(key[len(key)-32:])) 78 } 79 } 80 return hashes 81 } 82 83 // ReadHeaderNumber returns the header number assigned to a hash. 84 func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { 85 data, _ := db.Get(headerNumberKey(hash)) 86 if len(data) != 8 { 87 return nil 88 } 89 number := binary.BigEndian.Uint64(data) 90 return &number 91 } 92 93 // WriteHeaderNumber stores the hash->number mapping. 94 func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 95 key := headerNumberKey(hash) 96 enc := encodeBlockNumber(number) 97 if err := db.Put(key, enc); err != nil { 98 log.Crit("Failed to store hash to number mapping", "err", err) 99 } 100 } 101 102 // DeleteHeaderNumber removes hash->number mapping. 103 func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { 104 if err := db.Delete(headerNumberKey(hash)); err != nil { 105 log.Crit("Failed to delete hash to number mapping", "err", err) 106 } 107 } 108 109 // ReadHeadHeaderHash retrieves the hash of the current canonical head header. 110 func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { 111 data, _ := db.Get(headHeaderKey) 112 if len(data) == 0 { 113 return common.Hash{} 114 } 115 return common.BytesToHash(data) 116 } 117 118 // WriteHeadHeaderHash stores the hash of the current canonical head header. 119 func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { 120 if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { 121 log.Crit("Failed to store last header's hash", "err", err) 122 } 123 } 124 125 // ReadHeadBlockHash retrieves the hash of the current canonical head block. 126 func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { 127 data, _ := db.Get(headBlockKey) 128 if len(data) == 0 { 129 return common.Hash{} 130 } 131 return common.BytesToHash(data) 132 } 133 134 // WriteHeadBlockHash stores the head block's hash. 135 func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { 136 if err := db.Put(headBlockKey, hash.Bytes()); err != nil { 137 log.Crit("Failed to store last block's hash", "err", err) 138 } 139 } 140 141 // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. 142 func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash { 143 data, _ := db.Get(headFastBlockKey) 144 if len(data) == 0 { 145 return common.Hash{} 146 } 147 return common.BytesToHash(data) 148 } 149 150 // WriteHeadFastBlockHash stores the hash of the current fast-sync head block. 151 func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { 152 if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { 153 log.Crit("Failed to store last fast block's hash", "err", err) 154 } 155 } 156 157 // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow 158 // reporting correct numbers across restarts. 159 func ReadFastTrieProgress(db ethdb.KeyValueReader) uint64 { 160 data, _ := db.Get(fastTrieProgressKey) 161 if len(data) == 0 { 162 return 0 163 } 164 return new(big.Int).SetBytes(data).Uint64() 165 } 166 167 // WriteFastTrieProgress stores the fast sync trie process counter to support 168 // retrieving it across restarts. 169 func WriteFastTrieProgress(db ethdb.KeyValueWriter, count uint64) { 170 if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { 171 log.Crit("Failed to store fast sync trie progress", "err", err) 172 } 173 } 174 175 // ReadTxIndexTail retrieves the number of oldest indexed block 176 // whose transaction indices has been indexed. If the corresponding entry 177 // is non-existent in database it means the indexing has been finished. 178 func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 { 179 data, _ := db.Get(txIndexTailKey) 180 if len(data) != 8 { 181 return nil 182 } 183 number := binary.BigEndian.Uint64(data) 184 return &number 185 } 186 187 // WriteTxIndexTail stores the number of oldest indexed block 188 // into database. 189 func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { 190 if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { 191 log.Crit("Failed to store the transaction index tail", "err", err) 192 } 193 } 194 195 // ReadFastTxLookupLimit retrieves the tx lookup limit used in fast sync. 196 func ReadFastTxLookupLimit(db ethdb.KeyValueReader) *uint64 { 197 data, _ := db.Get(fastTxLookupLimitKey) 198 if len(data) != 8 { 199 return nil 200 } 201 number := binary.BigEndian.Uint64(data) 202 return &number 203 } 204 205 // WriteFastTxLookupLimit stores the txlookup limit used in fast sync into database. 206 func WriteFastTxLookupLimit(db ethdb.KeyValueWriter, number uint64) { 207 if err := db.Put(fastTxLookupLimitKey, encodeBlockNumber(number)); err != nil { 208 log.Crit("Failed to store transaction lookup limit for fast sync", "err", err) 209 } 210 } 211 212 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 213 func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 214 // First try to look up the data in ancient database. Extra hash 215 // comparison is necessary since ancient database only maintains 216 // the canonical data. 217 data, _ := db.Ancient(freezerHeaderTable, number) 218 if len(data) > 0 && crypto.Keccak256Hash(data) == hash { 219 return data 220 } 221 // Then try to look up the data in leveldb. 222 data, _ = db.Get(headerKey(number, hash)) 223 if len(data) > 0 { 224 return data 225 } 226 // In the background freezer is moving data from leveldb to flatten files. 227 // So during the first check for ancient db, the data is not yet in there, 228 // but when we reach into leveldb, the data was already moved. That would 229 // result in a not found error. 230 data, _ = db.Ancient(freezerHeaderTable, number) 231 if len(data) > 0 && crypto.Keccak256Hash(data) == hash { 232 return data 233 } 234 return nil // Can't find the data anywhere. 235 } 236 237 // HasHeader verifies the existence of a block header corresponding to the hash. 238 func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { 239 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 240 return true 241 } 242 if has, err := db.Has(headerKey(number, hash)); !has || err != nil { 243 return false 244 } 245 return true 246 } 247 248 // ReadHeader retrieves the block header corresponding to the hash. 249 func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { 250 data := ReadHeaderRLP(db, hash, number) 251 if len(data) == 0 { 252 return nil 253 } 254 header := new(types.Header) 255 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 256 log.Error("Invalid block header RLP", "hash", hash, "err", err) 257 return nil 258 } 259 return header 260 } 261 262 // WriteHeader stores a block header into the database and also stores the hash- 263 // to-number mapping. 264 func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { 265 var ( 266 hash = header.Hash() 267 number = header.Number.Uint64() 268 ) 269 // Write the hash -> number mapping 270 WriteHeaderNumber(db, hash, number) 271 272 // Write the encoded header 273 data, err := rlp.EncodeToBytes(header) 274 if err != nil { 275 log.Crit("Failed to RLP encode header", "err", err) 276 } 277 key := headerKey(number, hash) 278 if err := db.Put(key, data); err != nil { 279 log.Crit("Failed to store header", "err", err) 280 } 281 } 282 283 // DeleteHeader removes all block header data associated with a hash. 284 func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 285 deleteHeaderWithoutNumber(db, hash, number) 286 if err := db.Delete(headerNumberKey(hash)); err != nil { 287 log.Crit("Failed to delete hash to number mapping", "err", err) 288 } 289 } 290 291 // deleteHeaderWithoutNumber removes only the block header but does not remove 292 // the hash to number mapping. 293 func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 294 if err := db.Delete(headerKey(number, hash)); err != nil { 295 log.Crit("Failed to delete header", "err", err) 296 } 297 } 298 299 // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 300 func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 301 // First try to look up the data in ancient database. Extra hash 302 // comparison is necessary since ancient database only maintains 303 // the canonical data. 304 data, _ := db.Ancient(freezerBodiesTable, number) 305 if len(data) > 0 { 306 h, _ := db.Ancient(freezerHashTable, number) 307 if common.BytesToHash(h) == hash { 308 return data 309 } 310 } 311 // Then try to look up the data in leveldb. 312 data, _ = db.Get(blockBodyKey(number, hash)) 313 if len(data) > 0 { 314 return data 315 } 316 // In the background freezer is moving data from leveldb to flatten files. 317 // So during the first check for ancient db, the data is not yet in there, 318 // but when we reach into leveldb, the data was already moved. That would 319 // result in a not found error. 320 data, _ = db.Ancient(freezerBodiesTable, number) 321 if len(data) > 0 { 322 h, _ := db.Ancient(freezerHashTable, number) 323 if common.BytesToHash(h) == hash { 324 return data 325 } 326 } 327 return nil // Can't find the data anywhere. 328 } 329 330 // ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical 331 // block at number, in RLP encoding. 332 func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { 333 // If it's an ancient one, we don't need the canonical hash 334 data, _ := db.Ancient(freezerBodiesTable, number) 335 if len(data) == 0 { 336 // Need to get the hash 337 data, _ = db.Get(blockBodyKey(number, ReadCanonicalHash(db, number))) 338 // In the background freezer is moving data from leveldb to flatten files. 339 // So during the first check for ancient db, the data is not yet in there, 340 // but when we reach into leveldb, the data was already moved. That would 341 // result in a not found error. 342 if len(data) == 0 { 343 data, _ = db.Ancient(freezerBodiesTable, number) 344 } 345 } 346 return data 347 } 348 349 // WriteBodyRLP stores an RLP encoded block body into the database. 350 func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { 351 if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { 352 log.Crit("Failed to store block body", "err", err) 353 } 354 } 355 356 // HasBody verifies the existence of a block body corresponding to the hash. 357 func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { 358 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 359 return true 360 } 361 if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { 362 return false 363 } 364 return true 365 } 366 367 // ReadBody retrieves the block body corresponding to the hash. 368 func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { 369 data := ReadBodyRLP(db, hash, number) 370 if len(data) == 0 { 371 return nil 372 } 373 body := new(types.Body) 374 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 375 log.Error("Invalid block body RLP", "hash", hash, "err", err) 376 return nil 377 } 378 return body 379 } 380 381 // WriteBody stores a block body into the database. 382 func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { 383 data, err := rlp.EncodeToBytes(body) 384 if err != nil { 385 log.Crit("Failed to RLP encode body", "err", err) 386 } 387 WriteBodyRLP(db, hash, number, data) 388 } 389 390 // DeleteBody removes all block body data associated with a hash. 391 func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 392 if err := db.Delete(blockBodyKey(number, hash)); err != nil { 393 log.Crit("Failed to delete block body", "err", err) 394 } 395 } 396 397 // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. 398 func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 399 // First try to look up the data in ancient database. Extra hash 400 // comparison is necessary since ancient database only maintains 401 // the canonical data. 402 data, _ := db.Ancient(freezerDifficultyTable, number) 403 if len(data) > 0 { 404 h, _ := db.Ancient(freezerHashTable, number) 405 if common.BytesToHash(h) == hash { 406 return data 407 } 408 } 409 // Then try to look up the data in leveldb. 410 data, _ = db.Get(headerTDKey(number, hash)) 411 if len(data) > 0 { 412 return data 413 } 414 // In the background freezer is moving data from leveldb to flatten files. 415 // So during the first check for ancient db, the data is not yet in there, 416 // but when we reach into leveldb, the data was already moved. That would 417 // result in a not found error. 418 data, _ = db.Ancient(freezerDifficultyTable, number) 419 if len(data) > 0 { 420 h, _ := db.Ancient(freezerHashTable, number) 421 if common.BytesToHash(h) == hash { 422 return data 423 } 424 } 425 return nil // Can't find the data anywhere. 426 } 427 428 // ReadTd retrieves a block's total difficulty corresponding to the hash. 429 func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { 430 data := ReadTdRLP(db, hash, number) 431 if len(data) == 0 { 432 return nil 433 } 434 td := new(big.Int) 435 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 436 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 437 return nil 438 } 439 return td 440 } 441 442 // WriteTd stores the total difficulty of a block into the database. 443 func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) { 444 data, err := rlp.EncodeToBytes(td) 445 if err != nil { 446 log.Crit("Failed to RLP encode block total difficulty", "err", err) 447 } 448 if err := db.Put(headerTDKey(number, hash), data); err != nil { 449 log.Crit("Failed to store block total difficulty", "err", err) 450 } 451 } 452 453 // DeleteTd removes all block total difficulty data associated with a hash. 454 func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 455 if err := db.Delete(headerTDKey(number, hash)); err != nil { 456 log.Crit("Failed to delete block total difficulty", "err", err) 457 } 458 } 459 460 // HasReceipts verifies the existence of all the transaction receipts belonging 461 // to a block. 462 func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { 463 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 464 return true 465 } 466 if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { 467 return false 468 } 469 return true 470 } 471 472 // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. 473 func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 474 // First try to look up the data in ancient database. Extra hash 475 // comparison is necessary since ancient database only maintains 476 // the canonical data. 477 data, _ := db.Ancient(freezerReceiptTable, number) 478 if len(data) > 0 { 479 h, _ := db.Ancient(freezerHashTable, number) 480 if common.BytesToHash(h) == hash { 481 return data 482 } 483 } 484 // Then try to look up the data in leveldb. 485 data, _ = db.Get(blockReceiptsKey(number, hash)) 486 if len(data) > 0 { 487 return data 488 } 489 // In the background freezer is moving data from leveldb to flatten files. 490 // So during the first check for ancient db, the data is not yet in there, 491 // but when we reach into leveldb, the data was already moved. That would 492 // result in a not found error. 493 data, _ = db.Ancient(freezerReceiptTable, number) 494 if len(data) > 0 { 495 h, _ := db.Ancient(freezerHashTable, number) 496 if common.BytesToHash(h) == hash { 497 return data 498 } 499 } 500 return nil // Can't find the data anywhere. 501 } 502 503 // ReadRawReceipts retrieves all the transaction receipts belonging to a block. 504 // The receipt metadata fields are not guaranteed to be populated, so they 505 // should not be used. Use ReadReceipts instead if the metadata is needed. 506 func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { 507 // Retrieve the flattened receipt slice 508 data := ReadReceiptsRLP(db, hash, number) 509 if len(data) == 0 { 510 return nil 511 } 512 // Convert the receipts from their storage form to their internal representation 513 storageReceipts := []*types.ReceiptForStorage{} 514 if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { 515 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 516 return nil 517 } 518 receipts := make(types.Receipts, len(storageReceipts)) 519 for i, storageReceipt := range storageReceipts { 520 receipts[i] = (*types.Receipt)(storageReceipt) 521 } 522 return receipts 523 } 524 525 // ReadReceipts retrieves all the transaction receipts belonging to a block, including 526 // its correspoinding metadata fields. If it is unable to populate these metadata 527 // fields then nil is returned. 528 // 529 // The current implementation populates these metadata fields by reading the receipts' 530 // corresponding block body, so if the block body is not found it will return nil even 531 // if the receipt itself is stored. 532 func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts { 533 // We're deriving many fields from the block body, retrieve beside the receipt 534 receipts := ReadRawReceipts(db, hash, number) 535 if receipts == nil { 536 return nil 537 } 538 body := ReadBody(db, hash, number) 539 if body == nil { 540 log.Error("Missing body but have receipt", "hash", hash, "number", number) 541 return nil 542 } 543 if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { 544 log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) 545 return nil 546 } 547 return receipts 548 } 549 550 // WriteReceipts stores all the transaction receipts belonging to a block. 551 func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { 552 // Convert the receipts into their storage form and serialize them 553 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 554 for i, receipt := range receipts { 555 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 556 } 557 bytes, err := rlp.EncodeToBytes(storageReceipts) 558 if err != nil { 559 log.Crit("Failed to encode block receipts", "err", err) 560 } 561 // Store the flattened receipt slice 562 if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { 563 log.Crit("Failed to store block receipts", "err", err) 564 } 565 } 566 567 // DeleteReceipts removes all receipt data associated with a block hash. 568 func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 569 if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { 570 log.Crit("Failed to delete block receipts", "err", err) 571 } 572 } 573 574 // ReadBlock retrieves an entire block corresponding to the hash, assembling it 575 // back from the stored header and body. If either the header or body could not 576 // be retrieved nil is returned. 577 // 578 // Note, due to concurrent download of header and block body the header and thus 579 // canonical hash can be stored in the database but the body data not (yet). 580 func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { 581 header := ReadHeader(db, hash, number) 582 if header == nil { 583 return nil 584 } 585 body := ReadBody(db, hash, number) 586 if body == nil { 587 return nil 588 } 589 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 590 } 591 592 // WriteBlock serializes a block into the database, header and body separately. 593 func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { 594 WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) 595 WriteHeader(db, block.Header()) 596 } 597 598 // WriteAncientBlock writes entire block data into ancient store and returns the total written size. 599 func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int { 600 // Encode all block components to RLP format. 601 headerBlob, err := rlp.EncodeToBytes(block.Header()) 602 if err != nil { 603 log.Crit("Failed to RLP encode block header", "err", err) 604 } 605 bodyBlob, err := rlp.EncodeToBytes(block.Body()) 606 if err != nil { 607 log.Crit("Failed to RLP encode body", "err", err) 608 } 609 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 610 for i, receipt := range receipts { 611 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 612 } 613 receiptBlob, err := rlp.EncodeToBytes(storageReceipts) 614 if err != nil { 615 log.Crit("Failed to RLP encode block receipts", "err", err) 616 } 617 tdBlob, err := rlp.EncodeToBytes(td) 618 if err != nil { 619 log.Crit("Failed to RLP encode block total difficulty", "err", err) 620 } 621 // Write all blob to flatten files. 622 err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob) 623 if err != nil { 624 log.Crit("Failed to write block data to ancient store", "err", err) 625 } 626 return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(tdBlob) + common.HashLength 627 } 628 629 // DeleteBlock removes all block data associated with a hash. 630 func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 631 DeleteReceipts(db, hash, number) 632 DeleteHeader(db, hash, number) 633 DeleteBody(db, hash, number) 634 DeleteTd(db, hash, number) 635 } 636 637 // DeleteBlockWithoutNumber removes all block data associated with a hash, except 638 // the hash to number mapping. 639 func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 640 DeleteReceipts(db, hash, number) 641 deleteHeaderWithoutNumber(db, hash, number) 642 DeleteBody(db, hash, number) 643 DeleteTd(db, hash, number) 644 } 645 646 // FindCommonAncestor returns the last common ancestor of two block headers 647 func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { 648 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 649 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 650 if a == nil { 651 return nil 652 } 653 } 654 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 655 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 656 if b == nil { 657 return nil 658 } 659 } 660 for a.Hash() != b.Hash() { 661 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 662 if a == nil { 663 return nil 664 } 665 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 666 if b == nil { 667 return nil 668 } 669 } 670 return a 671 }