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