github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/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 "sort" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/ethdb" 28 "github.com/ethereum/go-ethereum/log" 29 "github.com/ethereum/go-ethereum/params" 30 "github.com/ethereum/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 // ReadAllCanonicalHashes retrieves all canonical number and hash mappings at the 84 // certain chain range. If the accumulated entries reaches the given threshold, 85 // abort the iteration and return the semi-finish result. 86 func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int) ([]uint64, []common.Hash) { 87 // Short circuit if the limit is 0. 88 if limit == 0 { 89 return nil, nil 90 } 91 var ( 92 numbers []uint64 93 hashes []common.Hash 94 ) 95 // Construct the key prefix of start point. 96 start, end := headerHashKey(from), headerHashKey(to) 97 it := db.NewIterator(nil, start) 98 defer it.Release() 99 100 for it.Next() { 101 if bytes.Compare(it.Key(), end) >= 0 { 102 break 103 } 104 if key := it.Key(); len(key) == len(headerPrefix)+8+1 && bytes.Equal(key[len(key)-1:], headerHashSuffix) { 105 numbers = append(numbers, binary.BigEndian.Uint64(key[len(headerPrefix):len(headerPrefix)+8])) 106 hashes = append(hashes, common.BytesToHash(it.Value())) 107 // If the accumulated entries reaches the limit threshold, return. 108 if len(numbers) >= limit { 109 break 110 } 111 } 112 } 113 return numbers, hashes 114 } 115 116 // ReadHeaderNumber returns the header number assigned to a hash. 117 func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { 118 data, _ := db.Get(headerNumberKey(hash)) 119 if len(data) != 8 { 120 return nil 121 } 122 number := binary.BigEndian.Uint64(data) 123 return &number 124 } 125 126 // WriteHeaderNumber stores the hash->number mapping. 127 func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 128 key := headerNumberKey(hash) 129 enc := encodeBlockNumber(number) 130 if err := db.Put(key, enc); err != nil { 131 log.Crit("Failed to store hash to number mapping", "err", err) 132 } 133 } 134 135 // DeleteHeaderNumber removes hash->number mapping. 136 func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { 137 if err := db.Delete(headerNumberKey(hash)); err != nil { 138 log.Crit("Failed to delete hash to number mapping", "err", err) 139 } 140 } 141 142 // ReadHeadHeaderHash retrieves the hash of the current canonical head header. 143 func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { 144 data, _ := db.Get(headHeaderKey) 145 if len(data) == 0 { 146 return common.Hash{} 147 } 148 return common.BytesToHash(data) 149 } 150 151 // WriteHeadHeaderHash stores the hash of the current canonical head header. 152 func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { 153 if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { 154 log.Crit("Failed to store last header's hash", "err", err) 155 } 156 } 157 158 // ReadHeadBlockHash retrieves the hash of the current canonical head block. 159 func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { 160 data, _ := db.Get(headBlockKey) 161 if len(data) == 0 { 162 return common.Hash{} 163 } 164 return common.BytesToHash(data) 165 } 166 167 // WriteHeadBlockHash stores the head block's hash. 168 func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { 169 if err := db.Put(headBlockKey, hash.Bytes()); err != nil { 170 log.Crit("Failed to store last block's hash", "err", err) 171 } 172 } 173 174 // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. 175 func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash { 176 data, _ := db.Get(headFastBlockKey) 177 if len(data) == 0 { 178 return common.Hash{} 179 } 180 return common.BytesToHash(data) 181 } 182 183 // WriteHeadFastBlockHash stores the hash of the current fast-sync head block. 184 func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { 185 if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { 186 log.Crit("Failed to store last fast block's hash", "err", err) 187 } 188 } 189 190 // ReadLastPivotNumber retrieves the number of the last pivot block. If the node 191 // full synced, the last pivot will always be nil. 192 func ReadLastPivotNumber(db ethdb.KeyValueReader) *uint64 { 193 data, _ := db.Get(lastPivotKey) 194 if len(data) == 0 { 195 return nil 196 } 197 var pivot uint64 198 if err := rlp.DecodeBytes(data, &pivot); err != nil { 199 log.Error("Invalid pivot block number in database", "err", err) 200 return nil 201 } 202 return &pivot 203 } 204 205 // WriteLastPivotNumber stores the number of the last pivot block. 206 func WriteLastPivotNumber(db ethdb.KeyValueWriter, pivot uint64) { 207 enc, err := rlp.EncodeToBytes(pivot) 208 if err != nil { 209 log.Crit("Failed to encode pivot block number", "err", err) 210 } 211 if err := db.Put(lastPivotKey, enc); err != nil { 212 log.Crit("Failed to store pivot block number", "err", err) 213 } 214 } 215 216 // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow 217 // reporting correct numbers across restarts. 218 func ReadFastTrieProgress(db ethdb.KeyValueReader) uint64 { 219 data, _ := db.Get(fastTrieProgressKey) 220 if len(data) == 0 { 221 return 0 222 } 223 return new(big.Int).SetBytes(data).Uint64() 224 } 225 226 // WriteFastTrieProgress stores the fast sync trie process counter to support 227 // retrieving it across restarts. 228 func WriteFastTrieProgress(db ethdb.KeyValueWriter, count uint64) { 229 if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { 230 log.Crit("Failed to store fast sync trie progress", "err", err) 231 } 232 } 233 234 // ReadTxIndexTail retrieves the number of oldest indexed block 235 // whose transaction indices has been indexed. If the corresponding entry 236 // is non-existent in database it means the indexing has been finished. 237 func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 { 238 data, _ := db.Get(txIndexTailKey) 239 if len(data) != 8 { 240 return nil 241 } 242 number := binary.BigEndian.Uint64(data) 243 return &number 244 } 245 246 // WriteTxIndexTail stores the number of oldest indexed block 247 // into database. 248 func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { 249 if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { 250 log.Crit("Failed to store the transaction index tail", "err", err) 251 } 252 } 253 254 // ReadFastTxLookupLimit retrieves the tx lookup limit used in fast sync. 255 func ReadFastTxLookupLimit(db ethdb.KeyValueReader) *uint64 { 256 data, _ := db.Get(fastTxLookupLimitKey) 257 if len(data) != 8 { 258 return nil 259 } 260 number := binary.BigEndian.Uint64(data) 261 return &number 262 } 263 264 // WriteFastTxLookupLimit stores the txlookup limit used in fast sync into database. 265 func WriteFastTxLookupLimit(db ethdb.KeyValueWriter, number uint64) { 266 if err := db.Put(fastTxLookupLimitKey, encodeBlockNumber(number)); err != nil { 267 log.Crit("Failed to store transaction lookup limit for fast sync", "err", err) 268 } 269 } 270 271 // Quorum 272 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 273 func readHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) (rlp.RawValue, *types.Header) { 274 // First try to look up the data in ancient database. Extra hash 275 // comparison is necessary since ancient database only maintains 276 // the canonical data. 277 data, _ := db.Ancient(freezerHeaderTable, number) 278 279 // Quorum: parse header to make sure we compare using the right hash (IBFT hash is based on a filtered header) 280 if len(data) > 0 { 281 header := decodeHeaderRLP(data) 282 if header.Hash() == hash { 283 return data, header 284 } 285 } 286 // End Quorum 287 288 // Then try to look up the data in leveldb. 289 data, _ = db.Get(headerKey(number, hash)) 290 if len(data) > 0 { 291 return data, decodeHeaderRLP(data) // Quorum: return decodeHeaderRLP(data) 292 } 293 // In the background freezer is moving data from leveldb to flatten files. 294 // So during the first check for ancient db, the data is not yet in there, 295 // but when we reach into leveldb, the data was already moved. That would 296 // result in a not found error. 297 data, _ = db.Ancient(freezerHeaderTable, number) 298 299 // Quorum: parse header to make sure we compare using the right hash (IBFT hash is based on a filtered header) 300 if len(data) > 0 { 301 header := decodeHeaderRLP(data) 302 if header.Hash() == hash { 303 return data, header 304 } 305 } 306 // End Quorum 307 308 return nil, nil // Can't find the data anywhere. 309 } 310 311 // Quorum 312 func decodeHeaderRLP(data rlp.RawValue) *types.Header { 313 header := new(types.Header) 314 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 315 log.Error("Invalid block header RLP", "err", err) 316 return nil 317 } 318 return header 319 } 320 321 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 322 func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 323 // Quorum: original code implemented inside `readHeaderRLP(...)` with some modifications from Quorum 324 data, _ := readHeaderRLP(db, hash, number) 325 return data 326 } 327 328 // HasHeader verifies the existence of a block header corresponding to the hash. 329 func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { 330 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 331 return true 332 } 333 if has, err := db.Has(headerKey(number, hash)); !has || err != nil { 334 return false 335 } 336 return true 337 } 338 339 // ReadHeader retrieves the block header corresponding to the hash. 340 func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { 341 data, header := readHeaderRLP(db, hash, number) 342 if data == nil { 343 log.Trace("header data not found in ancient or level db", "hash", hash) 344 return nil 345 } 346 if header == nil { 347 log.Error("Invalid block header RLP", "hash", hash) 348 return nil 349 } 350 return header 351 } 352 353 // WriteHeader stores a block header into the database and also stores the hash- 354 // to-number mapping. 355 func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { 356 var ( 357 hash = header.Hash() 358 number = header.Number.Uint64() 359 ) 360 // Write the hash -> number mapping 361 WriteHeaderNumber(db, hash, number) 362 363 // Write the encoded header 364 data, err := rlp.EncodeToBytes(header) 365 if err != nil { 366 log.Crit("Failed to RLP encode header", "err", err) 367 } 368 key := headerKey(number, hash) 369 if err := db.Put(key, data); err != nil { 370 log.Crit("Failed to store header", "err", err) 371 } 372 } 373 374 // DeleteHeader removes all block header data associated with a hash. 375 func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 376 deleteHeaderWithoutNumber(db, hash, number) 377 if err := db.Delete(headerNumberKey(hash)); err != nil { 378 log.Crit("Failed to delete hash to number mapping", "err", err) 379 } 380 } 381 382 // deleteHeaderWithoutNumber removes only the block header but does not remove 383 // the hash to number mapping. 384 func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 385 if err := db.Delete(headerKey(number, hash)); err != nil { 386 log.Crit("Failed to delete header", "err", err) 387 } 388 } 389 390 // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 391 func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 392 // First try to look up the data in ancient database. Extra hash 393 // comparison is necessary since ancient database only maintains 394 // the canonical data. 395 data, _ := db.Ancient(freezerBodiesTable, number) 396 if len(data) > 0 { 397 h, _ := db.Ancient(freezerHashTable, number) 398 if common.BytesToHash(h) == hash { 399 return data 400 } 401 } 402 // Then try to look up the data in leveldb. 403 data, _ = db.Get(blockBodyKey(number, hash)) 404 if len(data) > 0 { 405 return data 406 } 407 // In the background freezer is moving data from leveldb to flatten files. 408 // So during the first check for ancient db, the data is not yet in there, 409 // but when we reach into leveldb, the data was already moved. That would 410 // result in a not found error. 411 data, _ = db.Ancient(freezerBodiesTable, number) 412 if len(data) > 0 { 413 h, _ := db.Ancient(freezerHashTable, number) 414 if common.BytesToHash(h) == hash { 415 return data 416 } 417 } 418 return nil // Can't find the data anywhere. 419 } 420 421 // ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical 422 // block at number, in RLP encoding. 423 func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { 424 // If it's an ancient one, we don't need the canonical hash 425 data, _ := db.Ancient(freezerBodiesTable, number) 426 if len(data) == 0 { 427 // Need to get the hash 428 data, _ = db.Get(blockBodyKey(number, ReadCanonicalHash(db, number))) 429 // In the background freezer is moving data from leveldb to flatten files. 430 // So during the first check for ancient db, the data is not yet in there, 431 // but when we reach into leveldb, the data was already moved. That would 432 // result in a not found error. 433 if len(data) == 0 { 434 data, _ = db.Ancient(freezerBodiesTable, number) 435 } 436 } 437 return data 438 } 439 440 // WriteBodyRLP stores an RLP encoded block body into the database. 441 func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { 442 if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { 443 log.Crit("Failed to store block body", "err", err) 444 } 445 } 446 447 // HasBody verifies the existence of a block body corresponding to the hash. 448 func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { 449 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 450 return true 451 } 452 if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { 453 return false 454 } 455 return true 456 } 457 458 // ReadBody retrieves the block body corresponding to the hash. 459 func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { 460 data := ReadBodyRLP(db, hash, number) 461 if len(data) == 0 { 462 return nil 463 } 464 body := new(types.Body) 465 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 466 log.Error("Invalid block body RLP", "hash", hash, "err", err) 467 return nil 468 } 469 return body 470 } 471 472 // WriteBody stores a block body into the database. 473 func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { 474 data, err := rlp.EncodeToBytes(body) 475 if err != nil { 476 log.Crit("Failed to RLP encode body", "err", err) 477 } 478 WriteBodyRLP(db, hash, number, data) 479 } 480 481 // DeleteBody removes all block body data associated with a hash. 482 func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 483 if err := db.Delete(blockBodyKey(number, hash)); err != nil { 484 log.Crit("Failed to delete block body", "err", err) 485 } 486 } 487 488 // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. 489 func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 490 // First try to look up the data in ancient database. Extra hash 491 // comparison is necessary since ancient database only maintains 492 // the canonical data. 493 data, _ := db.Ancient(freezerDifficultyTable, number) 494 if len(data) > 0 { 495 h, _ := db.Ancient(freezerHashTable, number) 496 if common.BytesToHash(h) == hash { 497 return data 498 } 499 } 500 // Then try to look up the data in leveldb. 501 data, _ = db.Get(headerTDKey(number, hash)) 502 if len(data) > 0 { 503 return data 504 } 505 // In the background freezer is moving data from leveldb to flatten files. 506 // So during the first check for ancient db, the data is not yet in there, 507 // but when we reach into leveldb, the data was already moved. That would 508 // result in a not found error. 509 data, _ = db.Ancient(freezerDifficultyTable, number) 510 if len(data) > 0 { 511 h, _ := db.Ancient(freezerHashTable, number) 512 if common.BytesToHash(h) == hash { 513 return data 514 } 515 } 516 return nil // Can't find the data anywhere. 517 } 518 519 // ReadTd retrieves a block's total difficulty corresponding to the hash. 520 func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { 521 data := ReadTdRLP(db, hash, number) 522 if len(data) == 0 { 523 return nil 524 } 525 td := new(big.Int) 526 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 527 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 528 return nil 529 } 530 return td 531 } 532 533 // WriteTd stores the total difficulty of a block into the database. 534 func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) { 535 data, err := rlp.EncodeToBytes(td) 536 if err != nil { 537 log.Crit("Failed to RLP encode block total difficulty", "err", err) 538 } 539 if err := db.Put(headerTDKey(number, hash), data); err != nil { 540 log.Crit("Failed to store block total difficulty", "err", err) 541 } 542 } 543 544 // DeleteTd removes all block total difficulty data associated with a hash. 545 func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 546 if err := db.Delete(headerTDKey(number, hash)); err != nil { 547 log.Crit("Failed to delete block total difficulty", "err", err) 548 } 549 } 550 551 // HasReceipts verifies the existence of all the transaction receipts belonging 552 // to a block. 553 func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { 554 if has, err := db.Ancient(freezerHashTable, number); err == nil && common.BytesToHash(has) == hash { 555 return true 556 } 557 if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { 558 return false 559 } 560 return true 561 } 562 563 // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. 564 func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 565 // First try to look up the data in ancient database. Extra hash 566 // comparison is necessary since ancient database only maintains 567 // the canonical data. 568 data, _ := db.Ancient(freezerReceiptTable, number) 569 if len(data) > 0 { 570 h, _ := db.Ancient(freezerHashTable, number) 571 if common.BytesToHash(h) == hash { 572 return data 573 } 574 } 575 // Then try to look up the data in leveldb. 576 data, _ = db.Get(blockReceiptsKey(number, hash)) 577 if len(data) > 0 { 578 return data 579 } 580 // In the background freezer is moving data from leveldb to flatten files. 581 // So during the first check for ancient db, the data is not yet in there, 582 // but when we reach into leveldb, the data was already moved. That would 583 // result in a not found error. 584 data, _ = db.Ancient(freezerReceiptTable, number) 585 if len(data) > 0 { 586 h, _ := db.Ancient(freezerHashTable, number) 587 if common.BytesToHash(h) == hash { 588 return data 589 } 590 } 591 return nil // Can't find the data anywhere. 592 } 593 594 // ReadRawReceipts retrieves all the transaction receipts belonging to a block. 595 // The receipt metadata fields are not guaranteed to be populated, so they 596 // should not be used. Use ReadReceipts instead if the metadata is needed. 597 func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { 598 // Retrieve the flattened receipt slice 599 data := ReadReceiptsRLP(db, hash, number) 600 if len(data) == 0 { 601 return nil 602 } 603 // split the data into the standard receipt rlp list and the quorum extraData bytes 604 _, extraData, err := rlp.SplitList(data) 605 if err != nil { 606 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 607 return nil 608 } 609 // reslice data to remove extraData and get the receipt rlp list as the result from rlp.SplitList does not include the list header bytes 610 vanillaDataWithListHeader := data[0 : len(data)-len(extraData)] 611 612 // Convert the receipts from their storage form to their internal representation 613 storageReceipts := []*types.ReceiptForStorage{} 614 if err := rlp.DecodeBytes(vanillaDataWithListHeader, &storageReceipts); err != nil { 615 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 616 return nil 617 } 618 receipts := make(types.Receipts, len(storageReceipts)) 619 for i, storageReceipt := range storageReceipts { 620 receipts[i] = (*types.Receipt)(storageReceipt) 621 } 622 if len(extraData) > 0 { 623 quorumExtraDataReceipts := []*types.QuorumReceiptExtraData{} 624 if err := rlp.DecodeBytes(extraData, &quorumExtraDataReceipts); err != nil { 625 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 626 return nil 627 } 628 for i, quorumExtraDataReceipt := range quorumExtraDataReceipts { 629 if quorumExtraDataReceipt != nil { 630 receipts[i].FillReceiptExtraDataFromStorage(quorumExtraDataReceipt) 631 } 632 } 633 } 634 return receipts 635 } 636 637 // ReadReceipts retrieves all the transaction receipts belonging to a block, including 638 // its correspoinding metadata fields. If it is unable to populate these metadata 639 // fields then nil is returned. 640 // 641 // The current implementation populates these metadata fields by reading the receipts' 642 // corresponding block body, so if the block body is not found it will return nil even 643 // if the receipt itself is stored. 644 func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts { 645 // We're deriving many fields from the block body, retrieve beside the receipt 646 receipts := ReadRawReceipts(db, hash, number) 647 if receipts == nil { 648 return nil 649 } 650 body := ReadBody(db, hash, number) 651 if body == nil { 652 log.Error("Missing body but have receipt", "hash", hash, "number", number) 653 return nil 654 } 655 if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { 656 log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) 657 return nil 658 } 659 return receipts 660 } 661 662 // WriteReceipts stores all the transaction receipts belonging to a block. 663 func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { 664 // Convert the receipts into their storage form and serialize them 665 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 666 quorumReceiptsExtraData := make([]*types.QuorumReceiptExtraData, len(receipts)) 667 extraDataEmpty := true 668 for i, receipt := range receipts { 669 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 670 quorumReceiptsExtraData[i] = &receipt.QuorumReceiptExtraData 671 if !receipt.QuorumReceiptExtraData.IsEmpty() { 672 extraDataEmpty = false 673 } 674 } 675 bytes, err := rlp.EncodeToBytes(storageReceipts) 676 if err != nil { 677 log.Crit("Failed to encode block receipts", "err", err) 678 } 679 if !extraDataEmpty { 680 bytesExtraData, err := rlp.EncodeToBytes(quorumReceiptsExtraData) 681 if err != nil { 682 log.Crit("Failed to encode block receipts", "err", err) 683 } 684 // the vanilla receipts and the extra data receipts are concatenated and stored as a single value 685 bytes = append(bytes, bytesExtraData...) 686 } 687 // Store the flattened receipt slice 688 if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { 689 log.Crit("Failed to store block receipts", "err", err) 690 } 691 } 692 693 // DeleteReceipts removes all receipt data associated with a block hash. 694 func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 695 if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { 696 log.Crit("Failed to delete block receipts", "err", err) 697 } 698 } 699 700 // ReadBlock retrieves an entire block corresponding to the hash, assembling it 701 // back from the stored header and body. If either the header or body could not 702 // be retrieved nil is returned. 703 // 704 // Note, due to concurrent download of header and block body the header and thus 705 // canonical hash can be stored in the database but the body data not (yet). 706 func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { 707 header := ReadHeader(db, hash, number) 708 if header == nil { 709 return nil 710 } 711 body := ReadBody(db, hash, number) 712 if body == nil { 713 return nil 714 } 715 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 716 } 717 718 // WriteBlock serializes a block into the database, header and body separately. 719 func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { 720 WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) 721 WriteHeader(db, block.Header()) 722 } 723 724 // WriteAncientBlock writes entire block data into ancient store and returns the total written size. 725 func WriteAncientBlock(db ethdb.AncientWriter, block *types.Block, receipts types.Receipts, td *big.Int) int { 726 // Encode all block components to RLP format. 727 headerBlob, err := rlp.EncodeToBytes(block.Header()) 728 if err != nil { 729 log.Crit("Failed to RLP encode block header", "err", err) 730 } 731 bodyBlob, err := rlp.EncodeToBytes(block.Body()) 732 if err != nil { 733 log.Crit("Failed to RLP encode body", "err", err) 734 } 735 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 736 for i, receipt := range receipts { 737 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 738 } 739 receiptBlob, err := rlp.EncodeToBytes(storageReceipts) 740 if err != nil { 741 log.Crit("Failed to RLP encode block receipts", "err", err) 742 } 743 tdBlob, err := rlp.EncodeToBytes(td) 744 if err != nil { 745 log.Crit("Failed to RLP encode block total difficulty", "err", err) 746 } 747 // Write all blob to flatten files. 748 err = db.AppendAncient(block.NumberU64(), block.Hash().Bytes(), headerBlob, bodyBlob, receiptBlob, tdBlob) 749 if err != nil { 750 log.Crit("Failed to write block data to ancient store", "err", err) 751 } 752 return len(headerBlob) + len(bodyBlob) + len(receiptBlob) + len(tdBlob) + common.HashLength 753 } 754 755 // DeleteBlock removes all block data associated with a hash. 756 func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 757 DeleteReceipts(db, hash, number) 758 DeleteHeader(db, hash, number) 759 DeleteBody(db, hash, number) 760 DeleteTd(db, hash, number) 761 } 762 763 // DeleteBlockWithoutNumber removes all block data associated with a hash, except 764 // the hash to number mapping. 765 func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { 766 DeleteReceipts(db, hash, number) 767 deleteHeaderWithoutNumber(db, hash, number) 768 DeleteBody(db, hash, number) 769 DeleteTd(db, hash, number) 770 } 771 772 const badBlockToKeep = 10 773 774 type badBlock struct { 775 Header *types.Header 776 Body *types.Body 777 } 778 779 // badBlockList implements the sort interface to allow sorting a list of 780 // bad blocks by their number in the reverse order. 781 type badBlockList []*badBlock 782 783 func (s badBlockList) Len() int { return len(s) } 784 func (s badBlockList) Less(i, j int) bool { 785 return s[i].Header.Number.Uint64() < s[j].Header.Number.Uint64() 786 } 787 func (s badBlockList) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 788 789 // ReadBadBlock retrieves the bad block with the corresponding block hash. 790 func ReadBadBlock(db ethdb.Reader, hash common.Hash) *types.Block { 791 blob, err := db.Get(badBlockKey) 792 if err != nil { 793 return nil 794 } 795 var badBlocks badBlockList 796 if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { 797 return nil 798 } 799 for _, bad := range badBlocks { 800 if bad.Header.Hash() == hash { 801 return types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles) 802 } 803 } 804 return nil 805 } 806 807 // ReadAllBadBlocks retrieves all the bad blocks in the database. 808 // All returned blocks are sorted in reverse order by number. 809 func ReadAllBadBlocks(db ethdb.Reader) []*types.Block { 810 blob, err := db.Get(badBlockKey) 811 if err != nil { 812 return nil 813 } 814 var badBlocks badBlockList 815 if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { 816 return nil 817 } 818 var blocks []*types.Block 819 for _, bad := range badBlocks { 820 blocks = append(blocks, types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles)) 821 } 822 return blocks 823 } 824 825 // WriteBadBlock serializes the bad block into the database. If the cumulated 826 // bad blocks exceeds the limitation, the oldest will be dropped. 827 func WriteBadBlock(db ethdb.KeyValueStore, block *types.Block) { 828 blob, err := db.Get(badBlockKey) 829 if err != nil { 830 log.Warn("Failed to load old bad blocks", "error", err) 831 } 832 var badBlocks badBlockList 833 if len(blob) > 0 { 834 if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { 835 log.Crit("Failed to decode old bad blocks", "error", err) 836 } 837 } 838 for _, b := range badBlocks { 839 if b.Header.Number.Uint64() == block.NumberU64() && b.Header.Hash() == block.Hash() { 840 log.Info("Skip duplicated bad block", "number", block.NumberU64(), "hash", block.Hash()) 841 return 842 } 843 } 844 badBlocks = append(badBlocks, &badBlock{ 845 Header: block.Header(), 846 Body: block.Body(), 847 }) 848 sort.Sort(sort.Reverse(badBlocks)) 849 if len(badBlocks) > badBlockToKeep { 850 badBlocks = badBlocks[:badBlockToKeep] 851 } 852 data, err := rlp.EncodeToBytes(badBlocks) 853 if err != nil { 854 log.Crit("Failed to encode bad blocks", "err", err) 855 } 856 if err := db.Put(badBlockKey, data); err != nil { 857 log.Crit("Failed to write bad blocks", "err", err) 858 } 859 } 860 861 // DeleteBadBlocks deletes all the bad blocks from the database 862 func DeleteBadBlocks(db ethdb.KeyValueWriter) { 863 if err := db.Delete(badBlockKey); err != nil { 864 log.Crit("Failed to delete bad blocks", "err", err) 865 } 866 } 867 868 // HasBadBlock returns whether the block with the hash is a bad block. dep: Istanbul 869 func HasBadBlock(db ethdb.Reader, hash common.Hash) bool { 870 return ReadBadBlock(db, hash) != nil 871 } 872 873 // FindCommonAncestor returns the last common ancestor of two block headers 874 func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { 875 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 876 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 877 if a == nil { 878 return nil 879 } 880 } 881 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 882 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 883 if b == nil { 884 return nil 885 } 886 } 887 for a.Hash() != b.Hash() { 888 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 889 if a == nil { 890 return nil 891 } 892 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 893 if b == nil { 894 return nil 895 } 896 } 897 return a 898 }