github.com/aquanetwork/aquachain@v1.7.8/core/database_util.go (about) 1 // Copyright 2015 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain 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 aquachain 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 aquachain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "math/big" 26 27 "gitlab.com/aquachain/aquachain/aquadb" 28 "gitlab.com/aquachain/aquachain/common" 29 "gitlab.com/aquachain/aquachain/common/log" 30 "gitlab.com/aquachain/aquachain/common/metrics" 31 "gitlab.com/aquachain/aquachain/core/types" 32 "gitlab.com/aquachain/aquachain/params" 33 "gitlab.com/aquachain/aquachain/rlp" 34 ) 35 36 // DatabaseReader wraps the Get method of a backing data store. 37 type DatabaseReader interface { 38 Get(key []byte) (value []byte, err error) 39 } 40 41 // DatabaseDeleter wraps the Delete method of a backing data store. 42 type DatabaseDeleter interface { 43 Delete(key []byte) error 44 } 45 46 var ( 47 headHeaderKey = []byte("LastHeader") 48 headBlockKey = []byte("LastBlock") 49 headFastKey = []byte("LastFast") 50 trieSyncKey = []byte("TrieSync") 51 52 // Data item prefixes (use single byte to avoid mixing data types, avoid `i`). 53 headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header 54 tdSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td 55 numSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash 56 blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian) 57 bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body 58 blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts 59 lookupPrefix = []byte("l") // lookupPrefix + hash -> transaction/receipt lookup metadata 60 bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits 61 62 preimagePrefix = "secure-key-" // preimagePrefix + hash -> preimage 63 configPrefix = []byte("aquachain-config-") // config prefix for the db 64 65 // Chain index prefixes (use `i` + single byte to avoid mixing data types). 66 BloomBitsIndexPrefix = []byte("iB") // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress 67 68 // used by old db, now only used for conversion 69 oldReceiptsPrefix = []byte("receipts-") 70 oldTxMetaSuffix = []byte{0x01} 71 72 ErrChainConfigNotFound = errors.New("ChainConfig not found") // general config not found error 73 74 preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) 75 preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) 76 ) 77 78 // TxLookupEntry is a positional metadata to help looking up the data content of 79 // a transaction or receipt given only its hash. 80 type TxLookupEntry struct { 81 BlockHash common.Hash 82 BlockIndex uint64 83 Index uint64 84 } 85 86 // encodeBlockNumber encodes a block number as big endian uint64 87 func encodeBlockNumber(number uint64) []byte { 88 enc := make([]byte, 8) 89 binary.BigEndian.PutUint64(enc, number) 90 return enc 91 } 92 93 // GetCanonicalHash retrieves a hash assigned to a canonical block number. 94 func GetCanonicalHash(db DatabaseReader, number uint64) common.Hash { 95 data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) 96 if len(data) == 0 { 97 return common.Hash{} 98 } 99 return common.BytesToHash(data) 100 } 101 102 // missingNumber is returned by GetBlockNumber if no header with the 103 // given block hash has been stored in the database 104 const missingNumber = uint64(0xffffffffffffffff) 105 106 // GetBlockNumber returns the block number assigned to a block hash 107 // if the corresponding header is present in the database 108 func GetBlockNumber(db DatabaseReader, hash common.Hash) uint64 { 109 data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...)) 110 if len(data) != 8 { 111 return missingNumber 112 } 113 return binary.BigEndian.Uint64(data) 114 } 115 116 // GetHeadHeaderHash retrieves the hash of the current canonical head block's 117 // header. The difference between this and GetHeadBlockHash is that whereas the 118 // last block hash is only updated upon a full block import, the last header 119 // hash is updated already at header import, allowing head tracking for the 120 // light synchronization mechanism. 121 func GetHeadHeaderHash(db DatabaseReader) common.Hash { 122 data, _ := db.Get(headHeaderKey) 123 if len(data) == 0 { 124 return common.Hash{} 125 } 126 return common.BytesToHash(data) 127 } 128 129 // GetHeadBlockHash retrieves the hash of the current canonical head block. 130 func GetHeadBlockHash(db DatabaseReader) common.Hash { 131 data, _ := db.Get(headBlockKey) 132 if len(data) == 0 { 133 return common.Hash{} 134 } 135 return common.BytesToHash(data) 136 } 137 138 // GetHeadFastBlockHash retrieves the hash of the current canonical head block during 139 // fast synchronization. The difference between this and GetHeadBlockHash is that 140 // whereas the last block hash is only updated upon a full block import, the last 141 // fast hash is updated when importing pre-processed blocks. 142 func GetHeadFastBlockHash(db DatabaseReader) common.Hash { 143 data, _ := db.Get(headFastKey) 144 if len(data) == 0 { 145 return common.Hash{} 146 } 147 return common.BytesToHash(data) 148 } 149 150 // GetTrieSyncProgress retrieves the number of tries nodes fast synced to allow 151 // reportinc correct numbers across restarts. 152 func GetTrieSyncProgress(db DatabaseReader) uint64 { 153 data, _ := db.Get(trieSyncKey) 154 if len(data) == 0 { 155 return 0 156 } 157 return new(big.Int).SetBytes(data).Uint64() 158 } 159 160 // GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil 161 // if the header's not found. 162 func GetHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { 163 data, _ := db.Get(headerKey(hash, number)) 164 return data 165 } 166 167 // GetHeader retrieves the block header corresponding to the hash, nil if none 168 // found. 169 func GetHeaderNoVersion(db DatabaseReader, hash common.Hash, number uint64) *types.Header { 170 data := GetHeaderRLP(db, hash, number) 171 if len(data) == 0 { 172 return nil 173 } 174 header := new(types.Header) 175 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 176 log.Error("Invalid block header RLP", "hash", hash, "err", err) 177 return nil 178 } 179 return header 180 } 181 182 // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 183 func GetBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { 184 data, _ := db.Get(blockBodyKey(hash, number)) 185 return data 186 } 187 188 func headerKey(hash common.Hash, number uint64) []byte { 189 return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 190 } 191 192 func blockBodyKey(hash common.Hash, number uint64) []byte { 193 return append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 194 } 195 196 // GetBodyNoVersion retrieves the block body (transactons, uncles) corresponding to the 197 // hash, nil if none found. 198 func GetBodyNoVersion(db DatabaseReader, hash common.Hash, number uint64) *types.Body { 199 data := GetBodyRLP(db, hash, number) 200 if len(data) == 0 { 201 return nil 202 } 203 body := new(types.Body) 204 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 205 log.Error("Invalid block body RLP", "hash", hash, "err", err) 206 return nil 207 } 208 return body 209 } 210 211 // GetTd retrieves a block's total difficulty corresponding to the hash, nil if 212 // none found. 213 func GetTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { 214 data, _ := db.Get(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash[:]...), tdSuffix...)) 215 if len(data) == 0 { 216 return nil 217 } 218 td := new(big.Int) 219 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 220 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 221 return nil 222 } 223 return td 224 } 225 226 // GetBlock retrieves an entire block corresponding to the hash, assembling it 227 // back from the stored header and body. If either the header or body could not 228 // be retrieved nil is returned. 229 // 230 // Note, due to concurrent download of header and block body the header and thus 231 // canonical hash can be stored in the database but the body data not (yet). 232 func GetBlockNoVersion(db DatabaseReader, hash common.Hash, number uint64) *types.Block { 233 // Retrieve the block header and body contents 234 header := GetHeaderNoVersion(db, hash, number) 235 if header == nil { 236 return nil 237 } 238 body := GetBodyNoVersion(db, hash, number) 239 if body == nil { 240 return nil 241 } 242 // Reassemble the block and return 243 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 244 } 245 246 // GetBlockReceipts retrieves the receipts generated by the transactions included 247 // in a block given by its hash. 248 func GetBlockReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts { 249 data, _ := db.Get(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash[:]...)) 250 if len(data) == 0 { 251 return nil 252 } 253 storageReceipts := []*types.ReceiptForStorage{} 254 if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { 255 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 256 return nil 257 } 258 receipts := make(types.Receipts, len(storageReceipts)) 259 for i, receipt := range storageReceipts { 260 receipts[i] = (*types.Receipt)(receipt) 261 } 262 return receipts 263 } 264 265 // GetTxLookupEntry retrieves the positional metadata associated with a transaction 266 // hash to allow retrieving the transaction or receipt by hash. 267 func GetTxLookupEntry(db DatabaseReader, hash common.Hash) (common.Hash, uint64, uint64) { 268 // Load the positional metadata from disk and bail if it fails 269 data, _ := db.Get(append(lookupPrefix, hash.Bytes()...)) 270 if len(data) == 0 { 271 return common.Hash{}, 0, 0 272 } 273 // Parse and return the contents of the lookup entry 274 var entry TxLookupEntry 275 if err := rlp.DecodeBytes(data, &entry); err != nil { 276 log.Error("Invalid lookup entry RLP", "hash", hash, "err", err) 277 return common.Hash{}, 0, 0 278 } 279 return entry.BlockHash, entry.BlockIndex, entry.Index 280 } 281 282 // GetTransaction retrieves a specific transaction from the database, along with 283 // its added positional metadata. 284 func GetTransaction(db DatabaseReader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { 285 // Retrieve the lookup metadata and resolve the transaction from the body 286 blockHash, blockNumber, txIndex := GetTxLookupEntry(db, hash) 287 288 if blockHash != (common.Hash{}) { 289 body := GetBodyNoVersion(db, blockHash, blockNumber) 290 if body == nil || len(body.Transactions) <= int(txIndex) { 291 log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash, "index", txIndex) 292 return nil, common.Hash{}, 0, 0 293 } 294 return body.Transactions[txIndex], blockHash, blockNumber, txIndex 295 } 296 // Old transaction representation, load the transaction and it's metadata separately 297 data, _ := db.Get(hash.Bytes()) 298 if len(data) == 0 { 299 return nil, common.Hash{}, 0, 0 300 } 301 var tx types.Transaction 302 if err := rlp.DecodeBytes(data, &tx); err != nil { 303 return nil, common.Hash{}, 0, 0 304 } 305 // Retrieve the blockchain positional metadata 306 data, _ = db.Get(append(hash.Bytes(), oldTxMetaSuffix...)) 307 if len(data) == 0 { 308 return nil, common.Hash{}, 0, 0 309 } 310 var entry TxLookupEntry 311 if err := rlp.DecodeBytes(data, &entry); err != nil { 312 return nil, common.Hash{}, 0, 0 313 } 314 return &tx, entry.BlockHash, entry.BlockIndex, entry.Index 315 } 316 317 // GetReceipt retrieves a specific transaction receipt from the database, along with 318 // its added positional metadata. 319 func GetReceipt(db DatabaseReader, hash common.Hash) (*types.Receipt, common.Hash, uint64, uint64) { 320 // Retrieve the lookup metadata and resolve the receipt from the receipts 321 blockHash, blockNumber, receiptIndex := GetTxLookupEntry(db, hash) 322 323 if blockHash != (common.Hash{}) { 324 receipts := GetBlockReceipts(db, blockHash, blockNumber) 325 if len(receipts) <= int(receiptIndex) { 326 log.Error("Receipt refereced missing", "number", blockNumber, "hash", blockHash, "index", receiptIndex) 327 return nil, common.Hash{}, 0, 0 328 } 329 return receipts[receiptIndex], blockHash, blockNumber, receiptIndex 330 } 331 // Old receipt representation, load the receipt and set an unknown metadata 332 data, _ := db.Get(append(oldReceiptsPrefix, hash[:]...)) 333 if len(data) == 0 { 334 return nil, common.Hash{}, 0, 0 335 } 336 var receipt types.ReceiptForStorage 337 err := rlp.DecodeBytes(data, &receipt) 338 if err != nil { 339 log.Error("Invalid receipt RLP", "hash", hash, "err", err) 340 } 341 return (*types.Receipt)(&receipt), common.Hash{}, 0, 0 342 } 343 344 // GetBloomBits retrieves the compressed bloom bit vector belonging to the given 345 // section and bit index from the. 346 func GetBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash) ([]byte, error) { 347 key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...) 348 349 binary.BigEndian.PutUint16(key[1:], uint16(bit)) 350 binary.BigEndian.PutUint64(key[3:], section) 351 352 return db.Get(key) 353 } 354 355 // WriteCanonicalHash stores the canonical hash for the given block number. 356 func WriteCanonicalHash(db aquadb.Putter, hash common.Hash, number uint64) error { 357 key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...) 358 if err := db.Put(key, hash.Bytes()); err != nil { 359 log.Crit("Failed to store number to hash mapping", "err", err) 360 } 361 return nil 362 } 363 364 // WriteHeadHeaderHash stores the head header's hash. 365 func WriteHeadHeaderHash(db aquadb.Putter, hash common.Hash) error { 366 if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { 367 log.Crit("Failed to store last header's hash", "err", err) 368 } 369 return nil 370 } 371 372 // WriteHeadBlockHash stores the head block's hash. 373 func WriteHeadBlockHash(db aquadb.Putter, hash common.Hash) error { 374 if err := db.Put(headBlockKey, hash.Bytes()); err != nil { 375 log.Crit("Failed to store last block's hash", "err", err) 376 } 377 return nil 378 } 379 380 // WriteHeadFastBlockHash stores the fast head block's hash. 381 func WriteHeadFastBlockHash(db aquadb.Putter, hash common.Hash) error { 382 if err := db.Put(headFastKey, hash.Bytes()); err != nil { 383 log.Crit("Failed to store last fast block's hash", "err", err) 384 } 385 return nil 386 } 387 388 // WriteTrieSyncProgress stores the fast sync trie process counter to support 389 // retrieving it across restarts. 390 func WriteTrieSyncProgress(db aquadb.Putter, count uint64) error { 391 if err := db.Put(trieSyncKey, new(big.Int).SetUint64(count).Bytes()); err != nil { 392 log.Crit("Failed to store fast sync trie progress", "err", err) 393 } 394 return nil 395 } 396 397 // WriteHeader serializes a block header into the database. 398 func WriteHeader(db aquadb.Putter, header *types.Header) error { 399 data, err := rlp.EncodeToBytes(header) 400 if err != nil { 401 return err 402 } 403 hash := header.Hash().Bytes() 404 num := header.Number.Uint64() 405 encNum := encodeBlockNumber(num) 406 key := append(blockHashPrefix, hash...) 407 if err := db.Put(key, encNum); err != nil { 408 log.Crit("Failed to store hash to number mapping", "err", err) 409 } 410 key = append(append(headerPrefix, encNum...), hash...) 411 if err := db.Put(key, data); err != nil { 412 log.Crit("Failed to store header", "err", err) 413 } 414 return nil 415 } 416 417 // WriteBody serializes the body of a block into the database. 418 func WriteBody(db aquadb.Putter, hash common.Hash, number uint64, body *types.Body) error { 419 data, err := rlp.EncodeToBytes(body) 420 if err != nil { 421 return err 422 } 423 return WriteBodyRLP(db, hash, number, data) 424 } 425 426 // WriteBodyRLP writes a serialized body of a block into the database. 427 func WriteBodyRLP(db aquadb.Putter, hash common.Hash, number uint64, rlp rlp.RawValue) error { 428 key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 429 if err := db.Put(key, rlp); err != nil { 430 log.Crit("Failed to store block body", "err", err) 431 } 432 return nil 433 } 434 435 // WriteTd serializes the total difficulty of a block into the database. 436 func WriteTd(db aquadb.Putter, hash common.Hash, number uint64, td *big.Int) error { 437 data, err := rlp.EncodeToBytes(td) 438 if err != nil { 439 return err 440 } 441 key := append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...) 442 if err := db.Put(key, data); err != nil { 443 log.Crit("Failed to store block total difficulty", "err", err) 444 } 445 return nil 446 } 447 448 // WriteBlock serializes a block into the database, header and body separately. 449 func WriteBlock(db aquadb.Putter, block *types.Block) error { 450 // Store the body first to retain database consistency 451 if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil { 452 return err 453 } 454 // Store the header too, signaling full block ownership 455 if err := WriteHeader(db, block.Header()); err != nil { 456 return err 457 } 458 return nil 459 } 460 461 // WriteBlockReceipts stores all the transaction receipts belonging to a block 462 // as a single receipt slice. This is used during chain reorganisations for 463 // rescheduling dropped transactions. 464 func WriteBlockReceipts(db aquadb.Putter, hash common.Hash, number uint64, receipts types.Receipts) error { 465 // Convert the receipts into their storage form and serialize them 466 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 467 for i, receipt := range receipts { 468 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 469 } 470 bytes, err := rlp.EncodeToBytes(storageReceipts) 471 if err != nil { 472 return err 473 } 474 // Store the flattened receipt slice 475 key := append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 476 if err := db.Put(key, bytes); err != nil { 477 log.Crit("Failed to store block receipts", "err", err) 478 } 479 return nil 480 } 481 482 // WriteTxLookupEntries stores a positional metadata for every transaction from 483 // a block, enabling hash based transaction and receipt lookups. 484 func WriteTxLookupEntries(db aquadb.Putter, block *types.Block) error { 485 // Iterate over each transaction and encode its metadata 486 for i, tx := range block.Transactions() { 487 entry := TxLookupEntry{ 488 BlockHash: block.Hash(), 489 BlockIndex: block.NumberU64(), 490 Index: uint64(i), 491 } 492 data, err := rlp.EncodeToBytes(entry) 493 if err != nil { 494 return err 495 } 496 if err := db.Put(append(lookupPrefix, tx.Hash().Bytes()...), data); err != nil { 497 return err 498 } 499 } 500 return nil 501 } 502 503 // WriteBloomBits writes the compressed bloom bits vector belonging to the given 504 // section and bit index. 505 func WriteBloomBits(db aquadb.Putter, bit uint, section uint64, head common.Hash, bits []byte) { 506 key := append(append(bloomBitsPrefix, make([]byte, 10)...), head.Bytes()...) 507 508 binary.BigEndian.PutUint16(key[1:], uint16(bit)) 509 binary.BigEndian.PutUint64(key[3:], section) 510 511 if err := db.Put(key, bits); err != nil { 512 log.Crit("Failed to store bloom bits", "err", err) 513 } 514 } 515 516 // DeleteCanonicalHash removes the number to hash canonical mapping. 517 func DeleteCanonicalHash(db DatabaseDeleter, number uint64) { 518 db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) 519 } 520 521 // DeleteHeader removes all block header data associated with a hash. 522 func DeleteHeader(db DatabaseDeleter, hash common.Hash, number uint64) { 523 db.Delete(append(blockHashPrefix, hash.Bytes()...)) 524 db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 525 } 526 527 // DeleteBody removes all block body data associated with a hash. 528 func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) { 529 db.Delete(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 530 } 531 532 // DeleteTd removes all block total difficulty data associated with a hash. 533 func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { 534 db.Delete(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...)) 535 } 536 537 // DeleteBlock removes all block data associated with a hash. 538 func DeleteBlock(db DatabaseDeleter, hash common.Hash, number uint64) { 539 DeleteBlockReceipts(db, hash, number) 540 DeleteHeader(db, hash, number) 541 DeleteBody(db, hash, number) 542 DeleteTd(db, hash, number) 543 } 544 545 // DeleteBlockReceipts removes all receipt data associated with a block hash. 546 func DeleteBlockReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { 547 db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 548 } 549 550 // DeleteTxLookupEntry removes all transaction data associated with a hash. 551 func DeleteTxLookupEntry(db DatabaseDeleter, hash common.Hash) { 552 db.Delete(append(lookupPrefix, hash.Bytes()...)) 553 } 554 555 // PreimageTable returns a Database instance with the key prefix for preimage entries. 556 func PreimageTable(db aquadb.Database) aquadb.Database { 557 return aquadb.NewTable(db, preimagePrefix) 558 } 559 560 // WritePreimages writes the provided set of preimages to the database. `number` is the 561 // current block number, and is used for debug messages only. 562 func WritePreimages(db aquadb.Database, number uint64, preimages map[common.Hash][]byte) error { 563 table := PreimageTable(db) 564 batch := table.NewBatch() 565 hitCount := 0 566 for hash, preimage := range preimages { 567 if _, err := table.Get(hash.Bytes()); err != nil { 568 batch.Put(hash.Bytes(), preimage) 569 hitCount++ 570 } 571 } 572 preimageCounter.Inc(int64(len(preimages))) 573 preimageHitCounter.Inc(int64(hitCount)) 574 if hitCount > 0 { 575 if err := batch.Write(); err != nil { 576 return fmt.Errorf("preimage write fail for block %d: %v", number, err) 577 } 578 } 579 return nil 580 } 581 582 // GetBlockChainVersion reads the version number from db. 583 func GetBlockChainVersion(db DatabaseReader) int { 584 var vsn uint 585 enc, _ := db.Get([]byte("BlockchainVersion")) 586 rlp.DecodeBytes(enc, &vsn) 587 return int(vsn) 588 } 589 590 // WriteBlockChainVersion writes vsn as the version number to db. 591 func WriteBlockChainVersion(db aquadb.Putter, vsn int) { 592 enc, _ := rlp.EncodeToBytes(uint(vsn)) 593 db.Put([]byte("BlockchainVersion"), enc) 594 } 595 596 // WriteChainConfig writes the chain config settings to the database. 597 func WriteChainConfig(db aquadb.Putter, hash common.Hash, cfg *params.ChainConfig) error { 598 // short circuit and ignore if nil config. GetChainConfig 599 // will return a default. 600 if cfg == nil { 601 return nil 602 } 603 604 jsonChainConfig, err := json.Marshal(cfg) 605 if err != nil { 606 return err 607 } 608 609 return db.Put(append(configPrefix, hash[:]...), jsonChainConfig) 610 } 611 612 // GetChainConfig will fetch the network settings based on the given hash. 613 func GetChainConfig(db DatabaseReader, hash common.Hash) (*params.ChainConfig, error) { 614 jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...)) 615 if len(jsonChainConfig) == 0 { 616 return nil, ErrChainConfigNotFound 617 } 618 619 var config params.ChainConfig 620 if err := json.Unmarshal(jsonChainConfig, &config); err != nil { 621 return nil, err 622 } 623 624 return &config, nil 625 } 626 627 // FindCommonAncestor returns the last common ancestor of two block headers 628 func FindCommonAncestor(db DatabaseReader, a, b *types.Header, versionFunc func(*big.Int) params.HeaderVersion) *types.Header { 629 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 630 a = GetHeaderNoVersion(db, a.ParentHash, a.Number.Uint64()-1) 631 if a == nil { 632 return nil 633 } 634 } 635 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 636 b = GetHeaderNoVersion(db, b.ParentHash, b.Number.Uint64()-1) 637 if b == nil { 638 return nil 639 } 640 } 641 for a.SetVersion(byte(versionFunc(a.Number))) != b.SetVersion(byte(versionFunc(b.Number))) { 642 a = GetHeaderNoVersion(db, a.ParentHash, a.Number.Uint64()-1) 643 if a == nil { 644 return nil 645 } 646 b = GetHeaderNoVersion(db, b.ParentHash, b.Number.Uint64()-1) 647 if b == nil { 648 return nil 649 } 650 } 651 return a 652 }