blockchain: Add median time to state snapshot.
This adds a new field to the best chain state snapshot for the calculated past median time as returned by the calcPastMedianTime function. This is useful since it provides fast access to it without having to acquire the chain lock which is needed to recalculate it. This will ultimately allow the associated exported function to be removed since it only exists to be able to calculate this exact value, however this commit only introduces the new field in order to keep the changes minimal.
This commit is contained in:
parent
bfe2ba4191
commit
c57c18c8e2
2 changed files with 43 additions and 19 deletions
|
@ -128,23 +128,25 @@ func removeChildNode(children []*blockNode, node *blockNode) []*blockNode {
|
|||
// However, the returned snapshot must be treated as immutable since it is
|
||||
// shared by all callers.
|
||||
type BestState struct {
|
||||
Hash *chainhash.Hash // The hash of the block.
|
||||
Height int32 // The height of the block.
|
||||
Bits uint32 // The difficulty bits of the block.
|
||||
BlockSize uint64 // The size of the block.
|
||||
NumTxns uint64 // The number of txns in the block.
|
||||
TotalTxns uint64 // The total number of txns in the chain.
|
||||
Hash *chainhash.Hash // The hash of the block.
|
||||
Height int32 // The height of the block.
|
||||
Bits uint32 // The difficulty bits of the block.
|
||||
BlockSize uint64 // The size of the block.
|
||||
NumTxns uint64 // The number of txns in the block.
|
||||
TotalTxns uint64 // The total number of txns in the chain.
|
||||
MedianTime time.Time // Median time as per CalcPastMedianTime.
|
||||
}
|
||||
|
||||
// newBestState returns a new best stats instance for the given parameters.
|
||||
func newBestState(node *blockNode, blockSize, numTxns, totalTxns uint64) *BestState {
|
||||
func newBestState(node *blockNode, blockSize, numTxns, totalTxns uint64, medianTime time.Time) *BestState {
|
||||
return &BestState{
|
||||
Hash: node.hash,
|
||||
Height: node.height,
|
||||
Bits: node.bits,
|
||||
BlockSize: blockSize,
|
||||
NumTxns: numTxns,
|
||||
TotalTxns: totalTxns,
|
||||
Hash: node.hash,
|
||||
Height: node.height,
|
||||
Bits: node.bits,
|
||||
BlockSize: blockSize,
|
||||
NumTxns: numTxns,
|
||||
TotalTxns: totalTxns,
|
||||
MedianTime: medianTime,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,6 +781,12 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U
|
|||
"spent transaction out information")
|
||||
}
|
||||
|
||||
// Calculate the median time for the block.
|
||||
medianTime, err := b.calcPastMedianTime(node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate a new best state snapshot that will be used to update the
|
||||
// database and later memory if all database updates are successful.
|
||||
b.stateLock.RLock()
|
||||
|
@ -786,10 +794,11 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U
|
|||
b.stateLock.RUnlock()
|
||||
numTxns := uint64(len(block.MsgBlock().Transactions))
|
||||
blockSize := uint64(block.MsgBlock().SerializeSize())
|
||||
state := newBestState(node, blockSize, numTxns, curTotalTxns+numTxns)
|
||||
state := newBestState(node, blockSize, numTxns, curTotalTxns+numTxns,
|
||||
medianTime)
|
||||
|
||||
// Atomically insert info into the database.
|
||||
err := b.db.Update(func(dbTx database.Tx) error {
|
||||
err = b.db.Update(func(dbTx database.Tx) error {
|
||||
// Update best block state.
|
||||
err := dbPutBestState(dbTx, state, node.workSum)
|
||||
if err != nil {
|
||||
|
@ -892,6 +901,12 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view
|
|||
return err
|
||||
}
|
||||
|
||||
// Calculate the median time for the previous block.
|
||||
medianTime, err := b.calcPastMedianTime(prevNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the previous block since some details for it are needed below.
|
||||
var prevBlock *btcutil.Block
|
||||
err = b.db.View(func(dbTx database.Tx) error {
|
||||
|
@ -911,7 +926,8 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view
|
|||
numTxns := uint64(len(prevBlock.MsgBlock().Transactions))
|
||||
blockSize := uint64(prevBlock.MsgBlock().SerializeSize())
|
||||
newTotalTxns := curTotalTxns - uint64(len(block.MsgBlock().Transactions))
|
||||
state := newBestState(prevNode, blockSize, numTxns, newTotalTxns)
|
||||
state := newBestState(prevNode, blockSize, numTxns, newTotalTxns,
|
||||
medianTime)
|
||||
|
||||
err = b.db.Update(func(dbTx database.Tx) error {
|
||||
// Update best block state.
|
||||
|
|
|
@ -1058,10 +1058,12 @@ func (b *BlockChain) createChainState() error {
|
|||
// Add the new node to the index which is used for faster lookups.
|
||||
b.index[*node.hash] = node
|
||||
|
||||
// Initialize the state related to the best block.
|
||||
// Initialize the state related to the best block. Since it is the
|
||||
// genesis block, use its timestamp for the median time.
|
||||
numTxns := uint64(len(genesisBlock.MsgBlock().Transactions))
|
||||
blockSize := uint64(genesisBlock.MsgBlock().SerializeSize())
|
||||
b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns, numTxns)
|
||||
b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns, numTxns,
|
||||
b.bestNode.timestamp)
|
||||
|
||||
// Create the initial the database chain state including creating the
|
||||
// necessary index buckets and inserting the genesis block.
|
||||
|
@ -1159,11 +1161,17 @@ func (b *BlockChain) initChainState() error {
|
|||
b.index[*node.hash] = node
|
||||
b.depNodes[*prevHash] = append(b.depNodes[*prevHash], node)
|
||||
|
||||
// Calculate the median time for the block.
|
||||
medianTime, err := b.calcPastMedianTime(node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize the state related to the best block.
|
||||
blockSize := uint64(len(blockBytes))
|
||||
numTxns := uint64(len(block.Transactions))
|
||||
b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns,
|
||||
state.totalTxns)
|
||||
state.totalTxns, medianTime)
|
||||
|
||||
isStateInitialized = true
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue