database_util.go 19.5 KB
Newer Older
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 6 7 8
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
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 13 14
// GNU Lesser General Public License for more details.
//
// 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 18 19 20
package core

import (
	"bytes"
21 22
	"encoding/binary"
	"fmt"
23 24 25 26
	"math/big"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
27
	"github.com/ethereum/go-ethereum/ethdb"
28 29 30 31 32 33
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/logger/glog"
	"github.com/ethereum/go-ethereum/params"
	"github.com/ethereum/go-ethereum/rlp"
)

34
var (
35 36
	headHeaderKey = []byte("LastHeader")
	headBlockKey  = []byte("LastBlock")
37
	headFastKey   = []byte("LastFast")
38

39 40 41 42 43 44
	blockPrefix    = []byte("block-")
	blockNumPrefix = []byte("block-num-")

	headerSuffix = []byte("-header")
	bodySuffix   = []byte("-body")
	tdSuffix     = []byte("-td")
45

46 47 48
	txMetaSuffix        = []byte{0x01}
	receiptsPrefix      = []byte("receipts-")
	blockReceiptsPrefix = []byte("receipts-block-")
49 50 51

	mipmapPre    = []byte("mipmap-log-bloom-")
	MIPMapLevels = []uint64{1000000, 500000, 100000, 50000, 1000}
52 53 54

	ExpDiffPeriod   = big.NewInt(100000)
	blockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
55 56
)

57 58 59
// CalcDifficulty is the difficulty adjustment algorithm. It returns
// the difficulty that a new block b should have when created at time
// given the parent block's time and difficulty.
60
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
61 62
	diff := new(big.Int)
	adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
63 64 65 66 67 68 69
	bigTime := new(big.Int)
	bigParentTime := new(big.Int)

	bigTime.SetUint64(time)
	bigParentTime.SetUint64(parentTime)

	if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
70 71 72 73 74
		diff.Add(parentDiff, adjust)
	} else {
		diff.Sub(parentDiff, adjust)
	}
	if diff.Cmp(params.MinimumDifficulty) < 0 {
75
		diff = params.MinimumDifficulty
76
	}
77 78

	periodCount := new(big.Int).Add(parentNumber, common.Big1)
79
	periodCount.Div(periodCount, ExpDiffPeriod)
80 81 82 83 84 85 86 87
	if periodCount.Cmp(common.Big1) > 0 {
		// diff = diff + 2^(periodCount - 2)
		expDiff := periodCount.Sub(periodCount, common.Big2)
		expDiff.Exp(common.Big2, expDiff, nil)
		diff.Add(diff, expDiff)
		diff = common.BigMax(diff, params.MinimumDifficulty)
	}

88 89 90 91 92
	return diff
}

// CalcGasLimit computes the gas limit of the next block after parent.
// The result may be modified by the caller.
93
// This is miner strategy, not consensus protocol.
94
func CalcGasLimit(parent *types.Block) *big.Int {
95
	// contrib = (parentGasUsed * 3 / 2) / 1024
96 97 98 99
	contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
	contrib = contrib.Div(contrib, big.NewInt(2))
	contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)

100 101 102 103 104 105 106 107 108 109 110
	// decay = parentGasLimit / 1024 -1
	decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
	decay.Sub(decay, big.NewInt(1))

	/*
		strategy: gasLimit of block-to-mine is set based on parent's
		gasUsed value.  if parentGasUsed > parentGasLimit * (2/3) then we
		increase it, otherwise lower it (or leave it unchanged if it's right
		at that usage) the amount increased/decreased depends on how far away
		from parentGasLimit * (2/3) parentGasUsed is.
	*/
111 112 113 114
	gl := new(big.Int).Sub(parent.GasLimit(), decay)
	gl = gl.Add(gl, contrib)
	gl.Set(common.BigMax(gl, params.MinGasLimit))

115 116
	// however, if we're now below the target (GenesisGasLimit) we increase the
	// limit as much as we can (parentGasLimit / 1024 -1)
117 118 119 120 121 122 123
	if gl.Cmp(params.GenesisGasLimit) < 0 {
		gl.Add(parent.GasLimit(), decay)
		gl.Set(common.BigMin(gl, params.GenesisGasLimit))
	}
	return gl
}

124
// GetCanonicalHash retrieves a hash assigned to a canonical block number.
125
func GetCanonicalHash(db ethdb.Database, number uint64) common.Hash {
126 127 128 129 130
	data, _ := db.Get(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
131 132
}

133 134 135 136
// GetHeadHeaderHash retrieves the hash of the current canonical head block's
// header. The difference between this and GetHeadBlockHash is that whereas the
// last block hash is only updated upon a full block import, the last header
// hash is updated already at header import, allowing head tracking for the
137
// light synchronization mechanism.
138
func GetHeadHeaderHash(db ethdb.Database) common.Hash {
139
	data, _ := db.Get(headHeaderKey)
140 141 142 143 144 145
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
}

146
// GetHeadBlockHash retrieves the hash of the current canonical head block.
147
func GetHeadBlockHash(db ethdb.Database) common.Hash {
148
	data, _ := db.Get(headBlockKey)
149 150 151 152 153 154
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
}

155 156 157 158 159 160 161 162 163 164 165 166
// GetHeadFastBlockHash retrieves the hash of the current canonical head block during
// fast synchronization. The difference between this and GetHeadBlockHash is that
// whereas the last block hash is only updated upon a full block import, the last
// fast hash is updated when importing pre-processed blocks.
func GetHeadFastBlockHash(db ethdb.Database) common.Hash {
	data, _ := db.Get(headFastKey)
	if len(data) == 0 {
		return common.Hash{}
	}
	return common.BytesToHash(data)
}

167 168
// GetHeaderRLP retrieves a block header in its raw RLP database encoding, or nil
// if the header's not found.
169
func GetHeaderRLP(db ethdb.Database, hash common.Hash) rlp.RawValue {
170
	data, _ := db.Get(append(append(blockPrefix, hash[:]...), headerSuffix...))
171 172 173
	return data
}

174 175
// GetHeader retrieves the block header corresponding to the hash, nil if none
// found.
176
func GetHeader(db ethdb.Database, hash common.Hash) *types.Header {
177
	data := GetHeaderRLP(db, hash)
178 179 180
	if len(data) == 0 {
		return nil
	}
181 182 183
	header := new(types.Header)
	if err := rlp.Decode(bytes.NewReader(data), header); err != nil {
		glog.V(logger.Error).Infof("invalid block header RLP for hash %x: %v", hash, err)
184 185
		return nil
	}
186
	return header
187 188
}

189
// GetBodyRLP retrieves the block body (transactions and uncles) in RLP encoding.
190
func GetBodyRLP(db ethdb.Database, hash common.Hash) rlp.RawValue {
191 192
	data, _ := db.Get(append(append(blockPrefix, hash[:]...), bodySuffix...))
	return data
193 194
}

195 196
// GetBody retrieves the block body (transactons, uncles) corresponding to the
// hash, nil if none found.
197
func GetBody(db ethdb.Database, hash common.Hash) *types.Body {
198 199 200
	data := GetBodyRLP(db, hash)
	if len(data) == 0 {
		return nil
201
	}
202
	body := new(types.Body)
203 204
	if err := rlp.Decode(bytes.NewReader(data), body); err != nil {
		glog.V(logger.Error).Infof("invalid block body RLP for hash %x: %v", hash, err)
205
		return nil
206
	}
207
	return body
208 209
}

210 211
// GetTd retrieves a block's total difficulty corresponding to the hash, nil if
// none found.
212
func GetTd(db ethdb.Database, hash common.Hash) *big.Int {
213 214
	data, _ := db.Get(append(append(blockPrefix, hash.Bytes()...), tdSuffix...))
	if len(data) == 0 {
215 216
		return nil
	}
217 218 219
	td := new(big.Int)
	if err := rlp.Decode(bytes.NewReader(data), td); err != nil {
		glog.V(logger.Error).Infof("invalid block total difficulty RLP for hash %x: %v", hash, err)
220 221
		return nil
	}
222
	return td
223 224
}

225 226
// GetBlock retrieves an entire block corresponding to the hash, assembling it
// back from the stored header and body.
227
func GetBlock(db ethdb.Database, hash common.Hash) *types.Block {
228 229 230 231 232 233 234
	// Retrieve the block header and body contents
	header := GetHeader(db, hash)
	if header == nil {
		return nil
	}
	body := GetBody(db, hash)
	if body == nil {
235 236
		return nil
	}
237 238
	// Reassemble the block and return
	return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
239 240
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
// GetBlockReceipts retrieves the receipts generated by the transactions included
// in a block given by its hash.
func GetBlockReceipts(db ethdb.Database, hash common.Hash) types.Receipts {
	data, _ := db.Get(append(blockReceiptsPrefix, hash[:]...))
	if len(data) == 0 {
		return nil
	}
	storageReceipts := []*types.ReceiptForStorage{}
	if err := rlp.DecodeBytes(data, &storageReceipts); err != nil {
		glog.V(logger.Error).Infof("invalid receipt array RLP for hash %x: %v", hash, err)
		return nil
	}
	receipts := make(types.Receipts, len(storageReceipts))
	for i, receipt := range storageReceipts {
		receipts[i] = (*types.Receipt)(receipt)
	}
	return receipts
}

// GetTransaction retrieves a specific transaction from the database, along with
// its added positional metadata.
func GetTransaction(db ethdb.Database, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
	// Retrieve the transaction itself from the database
	data, _ := db.Get(hash.Bytes())
	if len(data) == 0 {
		return nil, common.Hash{}, 0, 0
	}
	var tx types.Transaction
	if err := rlp.DecodeBytes(data, &tx); err != nil {
		return nil, common.Hash{}, 0, 0
	}
	// Retrieve the blockchain positional metadata
	data, _ = db.Get(append(hash.Bytes(), txMetaSuffix...))
	if len(data) == 0 {
		return nil, common.Hash{}, 0, 0
	}
	var meta struct {
		BlockHash  common.Hash
		BlockIndex uint64
		Index      uint64
	}
	if err := rlp.DecodeBytes(data, &meta); err != nil {
		return nil, common.Hash{}, 0, 0
	}
	return &tx, meta.BlockHash, meta.BlockIndex, meta.Index
}

// GetReceipt returns a receipt by hash
func GetReceipt(db ethdb.Database, txHash common.Hash) *types.Receipt {
	data, _ := db.Get(append(receiptsPrefix, txHash[:]...))
	if len(data) == 0 {
		return nil
	}
	var receipt types.ReceiptForStorage
	err := rlp.DecodeBytes(data, &receipt)
	if err != nil {
		glog.V(logger.Core).Infoln("GetReceipt err:", err)
	}
	return (*types.Receipt)(&receipt)
}

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(blockNumPrefix, big.NewInt(int64(number)).Bytes()...)
305 306
	if err := db.Put(key, hash.Bytes()); err != nil {
		glog.Fatalf("failed to store number to hash mapping into database: %v", err)
307 308
		return err
	}
309 310 311
	return nil
}

312
// WriteHeadHeaderHash stores the head header's hash.
313
func WriteHeadHeaderHash(db ethdb.Database, hash common.Hash) error {
314 315
	if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
		glog.Fatalf("failed to store last header's hash into database: %v", err)
316 317
		return err
	}
318 319 320 321
	return nil
}

// WriteHeadBlockHash stores the head block's hash.
322
func WriteHeadBlockHash(db ethdb.Database, hash common.Hash) error {
323 324
	if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
		glog.Fatalf("failed to store last block's hash into database: %v", err)
325 326 327 328
		return err
	}
	return nil
}
329

330 331 332 333 334 335 336 337 338
// WriteHeadFastBlockHash stores the fast head block's hash.
func WriteHeadFastBlockHash(db ethdb.Database, hash common.Hash) error {
	if err := db.Put(headFastKey, hash.Bytes()); err != nil {
		glog.Fatalf("failed to store last fast block's hash into database: %v", err)
		return err
	}
	return nil
}

339
// WriteHeader serializes a block header into the database.
340
func WriteHeader(db ethdb.Database, header *types.Header) error {
341
	data, err := rlp.EncodeToBytes(header)
342 343 344
	if err != nil {
		return err
	}
345
	key := append(append(blockPrefix, header.Hash().Bytes()...), headerSuffix...)
346 347 348 349 350 351 352
	if err := db.Put(key, data); err != nil {
		glog.Fatalf("failed to store header into database: %v", err)
		return err
	}
	glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, header.Hash().Bytes()[:4])
	return nil
}
353

354
// WriteBody serializes the body of a block into the database.
355
func WriteBody(db ethdb.Database, hash common.Hash, body *types.Body) error {
356
	data, err := rlp.EncodeToBytes(body)
357 358 359
	if err != nil {
		return err
	}
360 361 362 363 364 365 366 367 368 369
	key := append(append(blockPrefix, hash.Bytes()...), bodySuffix...)
	if err := db.Put(key, data); err != nil {
		glog.Fatalf("failed to store block body into database: %v", err)
		return err
	}
	glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4])
	return nil
}

// WriteTd serializes the total difficulty of a block into the database.
370
func WriteTd(db ethdb.Database, hash common.Hash, td *big.Int) error {
371
	data, err := rlp.EncodeToBytes(td)
372 373
	if err != nil {
		return err
374
	}
375 376 377
	key := append(append(blockPrefix, hash.Bytes()...), tdSuffix...)
	if err := db.Put(key, data); err != nil {
		glog.Fatalf("failed to store block total difficulty into database: %v", err)
378 379
		return err
	}
380
	glog.V(logger.Debug).Infof("stored block total difficulty [%x…]: %v", hash.Bytes()[:4], td)
381 382
	return nil
}
383

384
// WriteBlock serializes a block into the database, header and body separately.
385
func WriteBlock(db ethdb.Database, block *types.Block) error {
386
	// Store the body first to retain database consistency
387
	if err := WriteBody(db, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil {
388 389 390 391 392 393
		return err
	}
	// Store the header too, signaling full block ownership
	if err := WriteHeader(db, block.Header()); err != nil {
		return err
	}
394 395
	return nil
}
396

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
// WriteBlockReceipts stores all the transaction receipts belonging to a block
// as a single receipt slice. This is used during chain reorganisations for
// rescheduling dropped transactions.
func WriteBlockReceipts(db ethdb.Database, hash common.Hash, receipts types.Receipts) error {
	// Convert the receipts into their storage form and serialize them
	storageReceipts := make([]*types.ReceiptForStorage, len(receipts))
	for i, receipt := range receipts {
		storageReceipts[i] = (*types.ReceiptForStorage)(receipt)
	}
	bytes, err := rlp.EncodeToBytes(storageReceipts)
	if err != nil {
		return err
	}
	// Store the flattened receipt slice
	if err := db.Put(append(blockReceiptsPrefix, hash.Bytes()...), bytes); err != nil {
		glog.Fatalf("failed to store block receipts into database: %v", err)
		return err
	}
	glog.V(logger.Debug).Infof("stored block receipts [%x…]", hash.Bytes()[:4])
	return nil
}

// WriteTransactions stores the transactions associated with a specific block
// into the given database. Beside writing the transaction, the function also
// stores a metadata entry along with the transaction, detailing the position
// of this within the blockchain.
func WriteTransactions(db ethdb.Database, block *types.Block) error {
	batch := db.NewBatch()

	// Iterate over each transaction and encode it with its metadata
	for i, tx := range block.Transactions() {
		// Encode and queue up the transaction for storage
		data, err := rlp.EncodeToBytes(tx)
		if err != nil {
			return err
		}
		if err := batch.Put(tx.Hash().Bytes(), data); err != nil {
			return err
		}
		// Encode and queue up the transaction metadata for storage
		meta := struct {
			BlockHash  common.Hash
			BlockIndex uint64
			Index      uint64
		}{
			BlockHash:  block.Hash(),
			BlockIndex: block.NumberU64(),
			Index:      uint64(i),
		}
		data, err = rlp.EncodeToBytes(meta)
		if err != nil {
			return err
		}
		if err := batch.Put(append(tx.Hash().Bytes(), txMetaSuffix...), data); err != nil {
			return err
		}
	}
	// Write the scheduled data into the database
	if err := batch.Write(); err != nil {
		glog.Fatalf("failed to store transactions into database: %v", err)
		return err
	}
	return nil
}

// WriteReceipts stores a batch of transaction receipts into the database.
func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
	batch := db.NewBatch()

	// Iterate over all the receipts and queue them for database injection
	for _, receipt := range receipts {
		storageReceipt := (*types.ReceiptForStorage)(receipt)
		data, err := rlp.EncodeToBytes(storageReceipt)
		if err != nil {
			return err
		}
		if err := batch.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data); err != nil {
			return err
		}
	}
	// Write the scheduled data into the database
	if err := batch.Write(); err != nil {
		glog.Fatalf("failed to store receipts into database: %v", err)
		return err
	}
	return nil
}

485
// DeleteCanonicalHash removes the number to hash canonical mapping.
486
func DeleteCanonicalHash(db ethdb.Database, number uint64) {
487 488 489
	db.Delete(append(blockNumPrefix, big.NewInt(int64(number)).Bytes()...))
}

490
// DeleteHeader removes all block header data associated with a hash.
491
func DeleteHeader(db ethdb.Database, hash common.Hash) {
492
	db.Delete(append(append(blockPrefix, hash.Bytes()...), headerSuffix...))
493 494 495
}

// DeleteBody removes all block body data associated with a hash.
496
func DeleteBody(db ethdb.Database, hash common.Hash) {
497 498 499 500
	db.Delete(append(append(blockPrefix, hash.Bytes()...), bodySuffix...))
}

// DeleteTd removes all block total difficulty data associated with a hash.
501
func DeleteTd(db ethdb.Database, hash common.Hash) {
502
	db.Delete(append(append(blockPrefix, hash.Bytes()...), tdSuffix...))
503 504 505
}

// DeleteBlock removes all block data associated with a hash.
506
func DeleteBlock(db ethdb.Database, hash common.Hash) {
507
	DeleteBlockReceipts(db, hash)
508 509
	DeleteHeader(db, hash)
	DeleteBody(db, hash)
510
	DeleteTd(db, hash)
511 512
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
// DeleteBlockReceipts removes all receipt data associated with a block hash.
func DeleteBlockReceipts(db ethdb.Database, hash common.Hash) {
	db.Delete(append(blockReceiptsPrefix, hash.Bytes()...))
}

// DeleteTransaction removes all transaction data associated with a hash.
func DeleteTransaction(db ethdb.Database, hash common.Hash) {
	db.Delete(hash.Bytes())
	db.Delete(append(hash.Bytes(), txMetaSuffix...))
}

// DeleteReceipt removes all receipt data associated with a transaction hash.
func DeleteReceipt(db ethdb.Database, hash common.Hash) {
	db.Delete(append(receiptsPrefix, hash.Bytes()...))
}

// [deprecated by the header/block split, remove eventually]
530 531 532 533
// GetBlockByHashOld returns the old combined block corresponding to the hash
// or nil if not found. This method is only used by the upgrade mechanism to
// access the old combined block representation. It will be dropped after the
// network transitions to eth/63.
534
func GetBlockByHashOld(db ethdb.Database, hash common.Hash) *types.Block {
535
	data, _ := db.Get(append(blockHashPrefix, hash[:]...))
536 537 538 539 540 541 542 543 544 545
	if len(data) == 0 {
		return nil
	}
	var block types.StorageBlock
	if err := rlp.Decode(bytes.NewReader(data), &block); err != nil {
		glog.V(logger.Error).Infof("invalid block RLP for hash %x: %v", hash, err)
		return nil
	}
	return (*types.Block)(&block)
}
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566

// returns a formatted MIP mapped key by adding prefix, canonical number and level
//
// ex. fn(98, 1000) = (prefix || 1000 || 0)
func mipmapKey(num, level uint64) []byte {
	lkey := make([]byte, 8)
	binary.BigEndian.PutUint64(lkey, level)
	key := new(big.Int).SetUint64(num / level * level)

	return append(mipmapPre, append(lkey, key.Bytes()...)...)
}

// WriteMapmapBloom writes each address included in the receipts' logs to the
// MIP bloom bin.
func WriteMipmapBloom(db ethdb.Database, number uint64, receipts types.Receipts) error {
	batch := db.NewBatch()
	for _, level := range MIPMapLevels {
		key := mipmapKey(number, level)
		bloomDat, _ := db.Get(key)
		bloom := types.BytesToBloom(bloomDat)
		for _, receipt := range receipts {
567
			for _, log := range receipt.Logs {
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
				bloom.Add(log.Address.Big())
			}
		}
		batch.Put(key, bloom.Bytes())
	}
	if err := batch.Write(); err != nil {
		return fmt.Errorf("mipmap write fail for: %d: %v", number, err)
	}
	return nil
}

// GetMipmapBloom returns a bloom filter using the number and level as input
// parameters. For available levels see MIPMapLevels.
func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
	bloomDat, _ := db.Get(mipmapKey(number, level))
	return types.BytesToBloom(bloomDat)
}