github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/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/ethereum-optimism/optimism/l2geth/common" 25 "github.com/ethereum-optimism/optimism/l2geth/core/types" 26 "github.com/ethereum-optimism/optimism/l2geth/crypto" 27 "github.com/ethereum-optimism/optimism/l2geth/ethdb" 28 "github.com/ethereum-optimism/optimism/l2geth/log" 29 "github.com/ethereum-optimism/optimism/l2geth/params" 30 "github.com/ethereum-optimism/optimism/l2geth/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.NewIteratorWithPrefix(prefix) 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 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 176 func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 177 // First try to look up the data in ancient database. Extra hash 178 // comparison is necessary since ancient database only maintains 179 // the canonical data. 180 data, _ := db.Ancient(freezerHeaderTable, number) 181 if len(data) > 0 && crypto.Keccak256Hash(data) == hash { 182 return data 183 } 184 // Then try to look up the data in leveldb. 185 data, _ = db.Get(headerKey(number, hash)) 186 if len(data) > 0 { 187 return data 188 } 189 // In the background freezer is moving data from leveldb to flatten files. 190 // So during the first check for ancient db, the data is not yet in there, 191 // but when we reach into leveldb, the data was already moved. That would 192 // result in a not found error. 193 data, _ = db.Ancient(freezerHeaderTable, number) 194 if len(data) > 0 && crypto.Keccak256Hash(data) == hash { 195 return data 196 } 197 return nil // Can't find the data anywhere. 198 } 199 200 // HasHeader verifies the existence of a block header corresponding to the hash. 201 func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { 202 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 203 return true 204 } 205 if has, err := db.Has(headerKey(number, hash)); !has || err != nil { 206 return false 207 } 208 return true 209 } 210 211 // ReadHeader retrieves the block header corresponding to the hash. 212 func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { 213 data := ReadHeaderRLP(db, hash, number) 214 if len(data) == 0 { 215 return nil 216 } 217 header := new(types.Header) 218 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 219 log.Error("Invalid block header RLP", "hash", hash, "err", err) 220 return nil 221 } 222 return header 223 } 224 225 // WriteHeader stores a block header into the database and also stores the hash- 226 // to-number mapping. 227 func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { 228 var ( 229 hash = header.Hash() 230 number = header.Number.Uint64() 231 ) 232 // Write the hash -> number mapping 233 WriteHeaderNumber(db, hash, number) 234 235 // Write the encoded header 236 data, err := rlp.EncodeToBytes(header) 237 if err != nil { 238 log.Crit("Failed to RLP encode header", "err", err) 239 } 240 key := headerKey(number, hash) 241 if err := db.Put(key, data); err != nil { 242 log.Crit("Failed to store header", "err", err) 243 } 244 } 245 246 // DeleteHeader removes all block header data associated with a hash. 247 func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 248 deleteHeaderWithoutNumber(db, hash, number) 249 if err := db.Delete(headerNumberKey(hash)); err != nil { 250 log.Crit("Failed to delete hash to number mapping", "err", err) 251 } 252 } 253 254 // deleteHeaderWithoutNumber removes only the block header but does not remove 255 // the hash to number mapping. 256 func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 257 if err := db.Delete(headerKey(number, hash)); err != nil { 258 log.Crit("Failed to delete header", "err", err) 259 } 260 } 261 262 // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 263 func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 264 // First try to look up the data in ancient database. Extra hash 265 // comparison is necessary since ancient database only maintains 266 // the canonical data. 267 data, _ := db.Ancient(freezerBodiesTable, number) 268 if len(data) > 0 { 269 h, _ := db.Ancient(freezerHashTable, number) 270 if common.BytesToHash(h) == hash { 271 return data 272 } 273 } 274 // Then try to look up the data in leveldb. 275 data, _ = db.Get(blockBodyKey(number, hash)) 276 if len(data) > 0 { 277 return data 278 } 279 // In the background freezer is moving data from leveldb to flatten files. 280 // So during the first check for ancient db, the data is not yet in there, 281 // but when we reach into leveldb, the data was already moved. That would 282 // result in a not found error. 283 data, _ = db.Ancient(freezerBodiesTable, number) 284 if len(data) > 0 { 285 h, _ := db.Ancient(freezerHashTable, number) 286 if common.BytesToHash(h) == hash { 287 return data 288 } 289 } 290 return nil // Can't find the data anywhere. 291 } 292 293 // WriteBodyRLP stores an RLP encoded block body into the database. 294 func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { 295 if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { 296 log.Crit("Failed to store block body", "err", err) 297 } 298 } 299 300 // HasBody verifies the existence of a block body corresponding to the hash. 301 func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { 302 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 303 return true 304 } 305 if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { 306 return false 307 } 308 return true 309 } 310 311 // ReadBody retrieves the block body corresponding to the hash. 312 func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { 313 data := ReadBodyRLP(db, hash, number) 314 if len(data) == 0 { 315 return nil 316 } 317 body := new(types.Body) 318 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 319 log.Error("Invalid block body RLP", "hash", hash, "err", err) 320 return nil 321 } 322 return body 323 } 324 325 // WriteBody stores a block body into the database. 326 func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { 327 data, err := rlp.EncodeToBytes(body) 328 if err != nil { 329 log.Crit("Failed to RLP encode body", "err", err) 330 } 331 WriteBodyRLP(db, hash, number, data) 332 } 333 334 // DeleteBody removes all block body data associated with a hash. 335 func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 336 if err := db.Delete(blockBodyKey(number, hash)); err != nil { 337 log.Crit("Failed to delete block body", "err", err) 338 } 339 } 340 341 // UsingOVM 342 // ReadTransactionMeta returns the transaction metadata associated with a 343 // transaction hash. 344 func ReadTransactionMeta(db ethdb.Reader, number uint64) *types.TransactionMeta { 345 data := ReadTransactionMetaRaw(db, number) 346 if len(data) == 0 { 347 return nil 348 } 349 350 meta, err := types.TxMetaDecode(data) 351 if err != nil { 352 log.Error("Invalid raw tx meta ", "number", number, "err", err) 353 return nil 354 } 355 356 return meta 357 } 358 359 // UsingOVM 360 // ReadTransactionMetaRaw returns the raw transaction metadata associated with a 361 // transaction hash. 362 func ReadTransactionMetaRaw(db ethdb.Reader, number uint64) []byte { 363 data, _ := db.Get(txMetaKey(number)) 364 if len(data) > 0 { 365 return data 366 } 367 return nil 368 } 369 370 // UsingOVM 371 // WriteTransactionMeta writes the TransactionMeta to disk by hash. 372 func WriteTransactionMeta(db ethdb.KeyValueWriter, number uint64, meta *types.TransactionMeta) { 373 data := types.TxMetaEncode(meta) 374 WriteTransactionMetaRaw(db, number, data) 375 } 376 377 // UsingOVM 378 // WriteTransactionMetaRaw writes the raw transaction metadata bytes to disk. 379 func WriteTransactionMetaRaw(db ethdb.KeyValueWriter, number uint64, data []byte) { 380 if err := db.Put(txMetaKey(number), data); err != nil { 381 log.Crit("Failed to store transaction meta", "err", err) 382 } 383 } 384 385 // UsingOVM 386 // DeleteTransactionMeta removes the transaction metadata associated with a hash 387 func DeleteTransactionMeta(db ethdb.KeyValueWriter, number uint64) { 388 if err := db.Delete(txMetaKey(number)); err != nil { 389 log.Crit("Failed to delete transaction meta", "err", err) 390 } 391 } 392 393 // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. 394 func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 395 // First try to look up the data in ancient database. Extra hash 396 // comparison is necessary since ancient database only maintains 397 // the canonical data. 398 data, _ := db.Ancient(freezerDifficultyTable, number) 399 if len(data) > 0 { 400 h, _ := db.Ancient(freezerHashTable, number) 401 if common.BytesToHash(h) == hash { 402 return data 403 } 404 } 405 // Then try to look up the data in leveldb. 406 data, _ = db.Get(headerTDKey(number, hash)) 407 if len(data) > 0 { 408 return data 409 } 410 // In the background freezer is moving data from leveldb to flatten files. 411 // So during the first check for ancient db, the data is not yet in there, 412 // but when we reach into leveldb, the data was already moved. That would 413 // result in a not found error. 414 data, _ = db.Ancient(freezerDifficultyTable, number) 415 if len(data) > 0 { 416 h, _ := db.Ancient(freezerHashTable, number) 417 if common.BytesToHash(h) == hash { 418 return data 419 } 420 } 421 return nil // Can't find the data anywhere. 422 } 423 424 // ReadTd retrieves a block's total difficulty corresponding to the hash. 425 func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { 426 data := ReadTdRLP(db, hash, number) 427 if len(data) == 0 { 428 return nil 429 } 430 td := new(big.Int) 431 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 432 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 433 return nil 434 } 435 return td 436 } 437 438 // WriteTd stores the total difficulty of a block into the database. 439 func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) { 440 data, err := rlp.EncodeToBytes(td) 441 if err != nil { 442 log.Crit("Failed to RLP encode block total difficulty", "err", err) 443 } 444 if err := db.Put(headerTDKey(number, hash), data); err != nil { 445 log.Crit("Failed to store block total difficulty", "err", err) 446 } 447 } 448 449 // DeleteTd removes all block total difficulty data associated with a hash. 450 func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 451 if err := db.Delete(headerTDKey(number, hash)); err != nil { 452 log.Crit("Failed to delete block total difficulty", "err", err) 453 } 454 } 455 456 // HasReceipts verifies the existence of all the transaction receipts belonging 457 // to a block. 458 func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { 459 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 460 return true 461 } 462 if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { 463 return false 464 } 465 return true 466 } 467 468 // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. 469 func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 470 // First try to look up the data in ancient database. Extra hash 471 // comparison is necessary since ancient database only maintains 472 // the canonical data. 473 data, _ := db.Ancient(freezerReceiptTable, number) 474 if len(data) > 0 { 475 h, _ := db.Ancient(freezerHashTable, number) 476 if common.BytesToHash(h) == hash { 477 return data 478 } 479 } 480 // Then try to look up the data in leveldb. 481 data, _ = db.Get(blockReceiptsKey(number, hash)) 482 if len(data) > 0 { 483 return data 484 } 485 // In the background freezer is moving data from leveldb to flatten files. 486 // So during the first check for ancient db, the data is not yet in there, 487 // but when we reach into leveldb, the data was already moved. That would 488 // result in a not found error. 489 data, _ = db.Ancient(freezerReceiptTable, number) 490 if len(data) > 0 { 491 h, _ := db.Ancient(freezerHashTable, number) 492 if common.BytesToHash(h) == hash { 493 return data 494 } 495 } 496 return nil // Can't find the data anywhere. 497 } 498 499 // ReadRawReceipts retrieves all the transaction receipts belonging to a block. 500 // The receipt metadata fields are not guaranteed to be populated, so they 501 // should not be used. Use ReadReceipts instead if the metadata is needed. 502 func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { 503 // Retrieve the flattened receipt slice 504 data := ReadReceiptsRLP(db, hash, number) 505 if len(data) == 0 { 506 return nil 507 } 508 // Convert the receipts from their storage form to their internal representation 509 storageReceipts := []*types.ReceiptForStorage{} 510 if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { 511 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 512 return nil 513 } 514 receipts := make(types.Receipts, len(storageReceipts)) 515 for i, storageReceipt := range storageReceipts { 516 receipts[i] = (*types.Receipt)(storageReceipt) 517 } 518 return receipts 519 } 520 521 // ReadReceipts retrieves all the transaction receipts belonging to a block, including 522 // its correspoinding metadata fields. If it is unable to populate these metadata 523 // fields then nil is returned. 524 // 525 // The current implementation populates these metadata fields by reading the receipts' 526 // corresponding block body, so if the block body is not found it will return nil even 527 // if the receipt itself is stored. 528 func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts { 529 // We're deriving many fields from the block body, retrieve beside the receipt 530 receipts := ReadRawReceipts(db, hash, number) 531 if receipts == nil { 532 return nil 533 } 534 body := ReadBody(db, hash, number) 535 if body == nil { 536 log.Error("Missing body but have receipt", "hash", hash, "number", number) 537 return nil 538 } 539 if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { 540 log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) 541 return nil 542 } 543 return receipts 544 } 545 546 // WriteReceipts stores all the transaction receipts belonging to a block. 547 func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { 548 // Convert the receipts into their storage form and serialize them 549 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 550 for i, receipt := range receipts { 551 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 552 } 553 bytes, err := rlp.EncodeToBytes(storageReceipts) 554 if err != nil { 555 log.Crit("Failed to encode block receipts", "err", err) 556 } 557 // Store the flattened receipt slice 558 if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { 559 log.Crit("Failed to store block receipts", "err", err) 560 } 561 } 562 563 // DeleteReceipts removes all receipt data associated with a block hash. 564 func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 565 if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { 566 log.Crit("Failed to delete block receipts", "err", err) 567 } 568 } 569 570 // ReadBlock retrieves an entire block corresponding to the hash, assembling it 571 // back from the stored header and body. If either the header or body could not 572 // be retrieved nil is returned. 573 // 574 // Note, due to concurrent download of header and block body the header and thus 575 // canonical hash can be stored in the database but the body data not (yet). 576 func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { 577 header := ReadHeader(db, hash, number) 578 if header == nil { 579 return nil 580 } 581 body := ReadBody(db, hash, number) 582 if body == nil { 583 return nil 584 } 585 // UsingOVM 586 // Read all of the transaction meta from the db when reading a block 587 // and set the txmeta on each transaction. This is because the tx meta 588 // is not included as part of the RLP encoding of a transaction to be 589 // backwards compatible with layer one 590 for i := 0; i < len(body.Transactions); i++ { 591 meta := ReadTransactionMeta(db, header.Number.Uint64()) 592 body.Transactions[i].SetTransactionMeta(meta) 593 } 594 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 595 } 596 597 // WriteBlock serializes a block into the database, header and body separately. 598 func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { 599 WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) 600 WriteHeader(db, block.Header()) 601 } 602 603 // WriteAncientBlock writes entire block data into ancient store and returns the total written size. 604 func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int { 605 // Encode all block components to RLP format. 606 headerBlob, err := rlp.EncodeToBytes(block.Header()) 607 if err != nil { 608 log.Crit("Failed to RLP encode block header", "err", err) 609 } 610 bodyBlob, err := rlp.EncodeToBytes(block.Body()) 611 if err != nil { 612 log.Crit("Failed to RLP encode body", "err", err) 613 } 614 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 615 for i, receipt := range receipts { 616 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 617 } 618 receiptBlob, err := rlp.EncodeToBytes(storageReceipts) 619 if err != nil { 620 log.Crit("Failed to RLP encode block receipts", "err", err) 621 } 622 tdBlob, err := rlp.EncodeToBytes(td) 623 if err != nil { 624 log.Crit("Failed to RLP encode block total difficulty", "err", err) 625 } 626 // Write all blob to flatten files. 627 err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob) 628 if err != nil { 629 log.Crit("Failed to write block data to ancient store", "err", err) 630 } 631 return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(tdBlob) + common.HashLength 632 } 633 634 // DeleteBlock removes all block data associated with a hash. 635 func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 636 DeleteReceipts(db, hash, number) 637 DeleteHeader(db, hash, number) 638 DeleteBody(db, hash, number) 639 DeleteTd(db, hash, number) 640 } 641 642 // DeleteBlockWithoutNumber removes all block data associated with a hash, except 643 // the hash to number mapping. 644 func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 645 DeleteReceipts(db, hash, number) 646 deleteHeaderWithoutNumber(db, hash, number) 647 DeleteBody(db, hash, number) 648 DeleteTd(db, hash, number) 649 } 650 651 // FindCommonAncestor returns the last common ancestor of two block headers 652 func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { 653 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 654 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 655 if a == nil { 656 return nil 657 } 658 } 659 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 660 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 661 if b == nil { 662 return nil 663 } 664 } 665 for a.Hash() != b.Hash() { 666 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 667 if a == nil { 668 return nil 669 } 670 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 671 if b == nil { 672 return nil 673 } 674 } 675 return a 676 }