github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/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 "sync" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/ethdb" 31 "github.com/ethereum/go-ethereum/log" 32 "github.com/ethereum/go-ethereum/metrics" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/rlp" 35 ) 36 37 var ( 38 headHeaderKey = []byte("LastHeader") 39 headBlockKey = []byte("LastBlock") 40 headFastKey = []byte("LastFast") 41 42 headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header 43 tdSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td 44 numSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + numSuffix -> hash 45 blockHashPrefix = []byte("H") // blockHashPrefix + hash -> num (uint64 big endian) 46 bodyPrefix = []byte("b") // bodyPrefix + num (uint64 big endian) + hash -> block body 47 blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts 48 preimagePrefix = "secure-key-" // preimagePrefix + hash -> preimage 49 50 txMetaSuffix = []byte{0x01} 51 receiptsPrefix = []byte("receipts-") 52 53 mipmapPre = []byte("mipmap-log-bloom-") 54 MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000} 55 56 configPrefix = []byte("ethereum-config-") // config prefix for the db 57 58 // used by old (non-sequential keys) db, now only used for conversion 59 oldBlockPrefix = []byte("block-") 60 oldHeaderSuffix = []byte("-header") 61 oldTdSuffix = []byte("-td") // headerPrefix + num (uint64 big endian) + hash + tdSuffix -> td 62 oldBodySuffix = []byte("-body") 63 oldBlockNumPrefix = []byte("block-num-") 64 oldBlockReceiptsPrefix = []byte("receipts-block-") 65 oldBlockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually] 66 67 ErrChainConfigNotFound = errors.New("ChainConfig not found") // general config not found error 68 69 mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms 70 71 preimageCounter = metrics.NewCounter("db/preimage/total") 72 preimageHitCounter = metrics.NewCounter("db/preimage/hits") 73 ) 74 75 // encodeBlockNumber encodes a block number as big endian uint64 76 func encodeBlockNumber(number uint64) []byte { 77 enc := make([]byte, 8) 78 binary.BigEndian.PutUint64(enc, number) 79 return enc 80 } 81 82 // GetCanonicalHash retrieves a hash assigned to a canonical block number. 83 func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash { 84 data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) 85 if len(data) == 0 { 86 data, _ = db.Get(append(oldBlockNumPrefix, big.NewInt(int64(number)).Bytes()...)) 87 if len(data) == 0 { 88 return common.Hash{} 89 } 90 } 91 return common.BytesToHash(data) 92 } 93 94 // missingNumber is returned by GetBlockNumber if no header with the 95 // given block hash has been stored in the database 96 const missingNumber = uint64(0xffffffffffffffff) 97 98 // GetBlockNumber returns the block number assigned to a block hash 99 // if the corresponding header is present in the database 100 func GetBlockNumber(db ethdb.Database, hash common.Hash) uint64 { 101 data, _ := db.Get(append(blockHashPrefix, hash.Bytes()...)) 102 if len(data) != 8 { 103 data, _ := db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldHeaderSuffix...)) 104 if len(data) == 0 { 105 return missingNumber 106 } 107 header := new(types.Header) 108 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 109 log.Crit("Failed to decode block header", "err", err) 110 } 111 return header.Number.Uint64() 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 ethdb.Database) 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 ethdb.Database) 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 ethdb.Database) 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 // GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil 151 // if the header's not found. 152 func GetHeaderRLP(db ethdb.Database, hash common.Hash, number uint64) rlp.RawValue { 153 data, _ := db.Get(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 154 if len(data) == 0 { 155 data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldHeaderSuffix...)) 156 } 157 return data 158 } 159 160 // GetHeader retrieves the block header corresponding to the hash, nil if none 161 // found. 162 func GetHeader(db ethdb.Database, hash common.Hash, number uint64) *types.Header { 163 data := GetHeaderRLP(db, hash, number) 164 if len(data) == 0 { 165 return nil 166 } 167 header := new(types.Header) 168 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 169 log.Error("Invalid block header RLP", "hash", hash, "err", err) 170 return nil 171 } 172 return header 173 } 174 175 // GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 176 func GetBodyRLP(db ethdb.Database, hash common.Hash, number uint64) rlp.RawValue { 177 data, _ := db.Get(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 178 if len(data) == 0 { 179 data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldBodySuffix...)) 180 } 181 return data 182 } 183 184 // GetBody retrieves the block body (transactons, uncles) corresponding to the 185 // hash, nil if none found. 186 func GetBody(db ethdb.Database, hash common.Hash, number uint64) *types.Body { 187 data := GetBodyRLP(db, hash, number) 188 if len(data) == 0 { 189 return nil 190 } 191 body := new(types.Body) 192 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 193 log.Error("Invalid block body RLP", "hash", hash, "err", err) 194 return nil 195 } 196 return body 197 } 198 199 // GetTd retrieves a block's total difficulty corresponding to the hash, nil if 200 // none found. 201 func GetTd(db ethdb.Database, hash common.Hash, number uint64) *big.Int { 202 data, _ := db.Get(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash[:]...), tdSuffix...)) 203 if len(data) == 0 { 204 data, _ = db.Get(append(append(oldBlockPrefix, hash.Bytes()...), oldTdSuffix...)) 205 if len(data) == 0 { 206 return nil 207 } 208 } 209 td := new(big.Int) 210 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 211 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 212 return nil 213 } 214 return td 215 } 216 217 // GetBlock retrieves an entire block corresponding to the hash, assembling it 218 // back from the stored header and body. If either the header or body could not 219 // be retrieved nil is returned. 220 // 221 // Note, due to concurrent download of header and block body the header and thus 222 // canonical hash can be stored in the database but the body data not (yet). 223 func GetBlock(db ethdb.Database, hash common.Hash, number uint64) *types.Block { 224 // Retrieve the block header and body contents 225 header := GetHeader(db, hash, number) 226 if header == nil { 227 return nil 228 } 229 body := GetBody(db, hash, number) 230 if body == nil { 231 return nil 232 } 233 // Reassemble the block and return 234 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 235 } 236 237 // GetBlockReceipts retrieves the receipts generated by the transactions included 238 // in a block given by its hash. 239 func GetBlockReceipts(db ethdb.Database, hash common.Hash, number uint64) types.Receipts { 240 data, _ := db.Get(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash[:]...)) 241 if len(data) == 0 { 242 data, _ = db.Get(append(oldBlockReceiptsPrefix, hash.Bytes()...)) 243 if len(data) == 0 { 244 return nil 245 } 246 } 247 storageReceipts := []*types.ReceiptForStorage{} 248 if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { 249 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 250 return nil 251 } 252 receipts := make(types.Receipts, len(storageReceipts)) 253 for i, receipt := range storageReceipts { 254 receipts[i] = (*types.Receipt)(receipt) 255 } 256 return receipts 257 } 258 259 // GetTransaction retrieves a specific transaction from the database, along with 260 // its added positional metadata. 261 func GetTransaction(db ethdb.Database, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { 262 // Retrieve the transaction itself from the database 263 data, _ := db.Get(hash.Bytes()) 264 if len(data) == 0 { 265 return nil, common.Hash{}, 0, 0 266 } 267 var tx types.Transaction 268 if err := rlp.DecodeBytes(data, &tx); err != nil { 269 return nil, common.Hash{}, 0, 0 270 } 271 // Retrieve the blockchain positional metadata 272 data, _ = db.Get(append(hash.Bytes(), txMetaSuffix...)) 273 if len(data) == 0 { 274 return nil, common.Hash{}, 0, 0 275 } 276 var meta struct { 277 BlockHash common.Hash 278 BlockIndex uint64 279 Index uint64 280 } 281 if err := rlp.DecodeBytes(data, &meta); err != nil { 282 return nil, common.Hash{}, 0, 0 283 } 284 return &tx, meta.BlockHash, meta.BlockIndex, meta.Index 285 } 286 287 // GetReceipt returns a receipt by hash 288 func GetReceipt(db ethdb.Database, hash common.Hash) *types.Receipt { 289 data, _ := db.Get(append(receiptsPrefix, hash[:]...)) 290 if len(data) == 0 { 291 return nil 292 } 293 var receipt types.ReceiptForStorage 294 err := rlp.DecodeBytes(data, &receipt) 295 if err != nil { 296 log.Error("Invalid receipt RLP", "hash", hash, "err", err) 297 } 298 return (*types.Receipt)(&receipt) 299 } 300 301 // WriteCanonicalHash stores the canonical hash for the given block number. 302 func WriteCanonicalHash(db ethdb.Database, hash common.Hash, number uint64) error { 303 key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...) 304 if err := db.Put(key, hash.Bytes()); err != nil { 305 log.Crit("Failed to store number to hash mapping", "err", err) 306 } 307 return nil 308 } 309 310 // WriteHeadHeaderHash stores the head header's hash. 311 func WriteHeadHeaderHash(db ethdb.Database, hash common.Hash) error { 312 if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { 313 log.Crit("Failed to store last header's hash", "err", err) 314 } 315 return nil 316 } 317 318 // WriteHeadBlockHash stores the head block's hash. 319 func WriteHeadBlockHash(db ethdb.Database, hash common.Hash) error { 320 if err := db.Put(headBlockKey, hash.Bytes()); err != nil { 321 log.Crit("Failed to store last block's hash", "err", err) 322 } 323 return nil 324 } 325 326 // WriteHeadFastBlockHash stores the fast head block's hash. 327 func WriteHeadFastBlockHash(db ethdb.Database, hash common.Hash) error { 328 if err := db.Put(headFastKey, hash.Bytes()); err != nil { 329 log.Crit("Failed to store last fast block's hash", "err", err) 330 } 331 return nil 332 } 333 334 // WriteHeader serializes a block header into the database. 335 func WriteHeader(db ethdb.Database, header *types.Header) error { 336 data, err := rlp.EncodeToBytes(header) 337 if err != nil { 338 return err 339 } 340 hash := header.Hash().Bytes() 341 num := header.Number.Uint64() 342 encNum := encodeBlockNumber(num) 343 key := append(blockHashPrefix, hash...) 344 if err := db.Put(key, encNum); err != nil { 345 log.Crit("Failed to store hash to number mapping", "err", err) 346 } 347 key = append(append(headerPrefix, encNum...), hash...) 348 if err := db.Put(key, data); err != nil { 349 log.Crit("Failed to store header", "err", err) 350 } 351 return nil 352 } 353 354 // WriteBody serializes the body of a block into the database. 355 func WriteBody(db ethdb.Database, hash common.Hash, number uint64, body *types.Body) error { 356 data, err := rlp.EncodeToBytes(body) 357 if err != nil { 358 return err 359 } 360 return WriteBodyRLP(db, hash, number, data) 361 } 362 363 // WriteBodyRLP writes a serialized body of a block into the database. 364 func WriteBodyRLP(db ethdb.Database, hash common.Hash, number uint64, rlp rlp.RawValue) error { 365 key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 366 if err := db.Put(key, rlp); err != nil { 367 log.Crit("Failed to store block body", "err", err) 368 } 369 return nil 370 } 371 372 // WriteTd serializes the total difficulty of a block into the database. 373 func WriteTd(db ethdb.Database, hash common.Hash, number uint64, td *big.Int) error { 374 data, err := rlp.EncodeToBytes(td) 375 if err != nil { 376 return err 377 } 378 key := append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...) 379 if err := db.Put(key, data); err != nil { 380 log.Crit("Failed to store block total difficulty", "err", err) 381 } 382 return nil 383 } 384 385 // WriteBlock serializes a block into the database, header and body separately. 386 func WriteBlock(db ethdb.Database, block *types.Block) error { 387 // Store the body first to retain database consistency 388 if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil { 389 return err 390 } 391 // Store the header too, signaling full block ownership 392 if err := WriteHeader(db, block.Header()); err != nil { 393 return err 394 } 395 return nil 396 } 397 398 // WriteBlockReceipts stores all the transaction receipts belonging to a block 399 // as a single receipt slice. This is used during chain reorganisations for 400 // rescheduling dropped transactions. 401 func WriteBlockReceipts(db ethdb.Database, hash common.Hash, number uint64, receipts types.Receipts) error { 402 // Convert the receipts into their storage form and serialize them 403 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 404 for i, receipt := range receipts { 405 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 406 } 407 bytes, err := rlp.EncodeToBytes(storageReceipts) 408 if err != nil { 409 return err 410 } 411 // Store the flattened receipt slice 412 key := append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) 413 if err := db.Put(key, bytes); err != nil { 414 log.Crit("Failed to store block receipts", "err", err) 415 } 416 return nil 417 } 418 419 // WriteTransactions stores the transactions associated with a specific block 420 // into the given database. Beside writing the transaction, the function also 421 // stores a metadata entry along with the transaction, detailing the position 422 // of this within the blockchain. 423 func WriteTransactions(db ethdb.Database, block *types.Block) error { 424 batch := db.NewBatch() 425 426 // Iterate over each transaction and encode it with its metadata 427 for i, tx := range block.Transactions() { 428 // Encode and queue up the transaction for storage 429 data, err := rlp.EncodeToBytes(tx) 430 if err != nil { 431 return err 432 } 433 if err = batch.Put(tx.Hash().Bytes(), data); err != nil { 434 return err 435 } 436 // Encode and queue up the transaction metadata for storage 437 meta := struct { 438 BlockHash common.Hash 439 BlockIndex uint64 440 Index uint64 441 }{ 442 BlockHash: block.Hash(), 443 BlockIndex: block.NumberU64(), 444 Index: uint64(i), 445 } 446 data, err = rlp.EncodeToBytes(meta) 447 if err != nil { 448 return err 449 } 450 if err := batch.Put(append(tx.Hash().Bytes(), txMetaSuffix...), data); err != nil { 451 return err 452 } 453 } 454 // Write the scheduled data into the database 455 if err := batch.Write(); err != nil { 456 log.Crit("Failed to store transactions", "err", err) 457 } 458 return nil 459 } 460 461 // WriteReceipt stores a single transaction receipt into the database. 462 func WriteReceipt(db ethdb.Database, receipt *types.Receipt) error { 463 storageReceipt := (*types.ReceiptForStorage)(receipt) 464 data, err := rlp.EncodeToBytes(storageReceipt) 465 if err != nil { 466 return err 467 } 468 return db.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data) 469 } 470 471 // WriteReceipts stores a batch of transaction receipts into the database. 472 func WriteReceipts(db ethdb.Database, receipts types.Receipts) error { 473 batch := db.NewBatch() 474 475 // Iterate over all the receipts and queue them for database injection 476 for _, receipt := range receipts { 477 storageReceipt := (*types.ReceiptForStorage)(receipt) 478 data, err := rlp.EncodeToBytes(storageReceipt) 479 if err != nil { 480 return err 481 } 482 if err := batch.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data); err != nil { 483 return err 484 } 485 } 486 // Write the scheduled data into the database 487 if err := batch.Write(); err != nil { 488 log.Crit("Failed to store receipts", "err", err) 489 } 490 return nil 491 } 492 493 // DeleteCanonicalHash removes the number to hash canonical mapping. 494 func DeleteCanonicalHash(db ethdb.Database, number uint64) { 495 db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)) 496 } 497 498 // DeleteHeader removes all block header data associated with a hash. 499 func DeleteHeader(db ethdb.Database, hash common.Hash, number uint64) { 500 db.Delete(append(blockHashPrefix, hash.Bytes()...)) 501 db.Delete(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 502 } 503 504 // DeleteBody removes all block body data associated with a hash. 505 func DeleteBody(db ethdb.Database, hash common.Hash, number uint64) { 506 db.Delete(append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 507 } 508 509 // DeleteTd removes all block total difficulty data associated with a hash. 510 func DeleteTd(db ethdb.Database, hash common.Hash, number uint64) { 511 db.Delete(append(append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...), tdSuffix...)) 512 } 513 514 // DeleteBlock removes all block data associated with a hash. 515 func DeleteBlock(db ethdb.Database, hash common.Hash, number uint64) { 516 DeleteBlockReceipts(db, hash, number) 517 DeleteHeader(db, hash, number) 518 DeleteBody(db, hash, number) 519 DeleteTd(db, hash, number) 520 } 521 522 // DeleteBlockReceipts removes all receipt data associated with a block hash. 523 func DeleteBlockReceipts(db ethdb.Database, hash common.Hash, number uint64) { 524 db.Delete(append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)) 525 } 526 527 // DeleteTransaction removes all transaction data associated with a hash. 528 func DeleteTransaction(db ethdb.Database, hash common.Hash) { 529 db.Delete(hash.Bytes()) 530 db.Delete(append(hash.Bytes(), txMetaSuffix...)) 531 } 532 533 // DeleteReceipt removes all receipt data associated with a transaction hash. 534 func DeleteReceipt(db ethdb.Database, hash common.Hash) { 535 db.Delete(append(receiptsPrefix, hash.Bytes()...)) 536 } 537 538 // returns a formatted MIP mapped key by adding prefix, canonical number and level 539 // 540 // ex. fn(98, 1000) = (prefix || 1000 || 0) 541 func mipmapKey(num, level uint64) []byte { 542 lkey := make([]byte, 8) 543 binary.BigEndian.PutUint64(lkey, level) 544 key := new(big.Int).SetUint64(num / level * level) 545 546 return append(mipmapPre, append(lkey, key.Bytes()...)...) 547 } 548 549 // WriteMipmapBloom writes each address included in the receipts' logs to the 550 // MIP bloom bin. 551 func WriteMipmapBloom(db ethdb.Database, number uint64, receipts types.Receipts) error { 552 mipmapBloomMu.Lock() 553 defer mipmapBloomMu.Unlock() 554 555 batch := db.NewBatch() 556 for _, level := range MIPMapLevels { 557 key := mipmapKey(number, level) 558 bloomDat, _ := db.Get(key) 559 bloom := types.BytesToBloom(bloomDat) 560 for _, receipt := range receipts { 561 for _, log := range receipt.Logs { 562 bloom.Add(log.Address.Big()) 563 } 564 } 565 batch.Put(key, bloom.Bytes()) 566 } 567 if err := batch.Write(); err != nil { 568 return fmt.Errorf("mipmap write fail for: %d: %v", number, err) 569 } 570 return nil 571 } 572 573 // GetMipmapBloom returns a bloom filter using the number and level as input 574 // parameters. For available levels see MIPMapLevels. 575 func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom { 576 bloomDat, _ := db.Get(mipmapKey(number, level)) 577 return types.BytesToBloom(bloomDat) 578 } 579 580 // PreimageTable returns a Database instance with the key prefix for preimage entries. 581 func PreimageTable(db ethdb.Database) ethdb.Database { 582 return ethdb.NewTable(db, preimagePrefix) 583 } 584 585 // WritePreimages writes the provided set of preimages to the database. `number` is the 586 // current block number, and is used for debug messages only. 587 func WritePreimages(db ethdb.Database, number uint64, preimages map[common.Hash][]byte) error { 588 table := PreimageTable(db) 589 batch := table.NewBatch() 590 hitCount := 0 591 for hash, preimage := range preimages { 592 if _, err := table.Get(hash.Bytes()); err != nil { 593 batch.Put(hash.Bytes(), preimage) 594 hitCount++ 595 } 596 } 597 preimageCounter.Inc(int64(len(preimages))) 598 preimageHitCounter.Inc(int64(hitCount)) 599 if hitCount > 0 { 600 if err := batch.Write(); err != nil { 601 return fmt.Errorf("preimage write fail for block %d: %v", number, err) 602 } 603 } 604 return nil 605 } 606 607 // GetBlockChainVersion reads the version number from db. 608 func GetBlockChainVersion(db ethdb.Database) int { 609 var vsn uint 610 enc, _ := db.Get([]byte("BlockchainVersion")) 611 rlp.DecodeBytes(enc, &vsn) 612 return int(vsn) 613 } 614 615 // WriteBlockChainVersion writes vsn as the version number to db. 616 func WriteBlockChainVersion(db ethdb.Database, vsn int) { 617 enc, _ := rlp.EncodeToBytes(uint(vsn)) 618 db.Put([]byte("BlockchainVersion"), enc) 619 } 620 621 // WriteChainConfig writes the chain config settings to the database. 622 func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *params.ChainConfig) error { 623 // short circuit and ignore if nil config. GetChainConfig 624 // will return a default. 625 if cfg == nil { 626 return nil 627 } 628 629 jsonChainConfig, err := json.Marshal(cfg) 630 if err != nil { 631 return err 632 } 633 634 return db.Put(append(configPrefix, hash[:]...), jsonChainConfig) 635 } 636 637 // GetChainConfig will fetch the network settings based on the given hash. 638 func GetChainConfig(db ethdb.Database, hash common.Hash) (*params.ChainConfig, error) { 639 jsonChainConfig, _ := db.Get(append(configPrefix, hash[:]...)) 640 if len(jsonChainConfig) == 0 { 641 return nil, ErrChainConfigNotFound 642 } 643 644 var config params.ChainConfig 645 if err := json.Unmarshal(jsonChainConfig, &config); err != nil { 646 return nil, err 647 } 648 649 return &config, nil 650 } 651 652 // FindCommonAncestor returns the last common ancestor of two block headers 653 func FindCommonAncestor(db ethdb.Database, a, b *types.Header) *types.Header { 654 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 655 a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) 656 if a == nil { 657 return nil 658 } 659 } 660 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 661 b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1) 662 if b == nil { 663 return nil 664 } 665 } 666 for a.Hash() != b.Hash() { 667 a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) 668 if a == nil { 669 return nil 670 } 671 b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1) 672 if b == nil { 673 return nil 674 } 675 } 676 return a 677 }