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