Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blockchain: update BestState. #1416

Merged
merged 1 commit into from
Aug 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 69 additions & 38 deletions blockchain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,46 @@ type orphanBlock struct {
// 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 int64 // 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.
TotalSubsidy int64 // The total subsidy for the chain.
Hash chainhash.Hash // The hash of the block.
PrevHash chainhash.Hash // The previous block hash.
Height int64 // The height of the block.
Bits uint32 // The difficulty bits of the block.
NextPoolSize uint32 // The ticket pool size.
NextStakeDiff int64 // The next stake difficulty.
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.
TotalSubsidy int64 // The total subsidy for the chain.
NextWinningTickets []chainhash.Hash // The eligible tickets to vote on the next block.
MissedTickets []chainhash.Hash // The missed tickets set to be revoked.
NextFinalState [6]byte // The calculated state of the lottery for the next block.
}

// newBestState returns a new best stats instance for the given parameters.
func newBestState(node *blockNode, blockSize, numTxns, totalTxns uint64, medianTime time.Time, totalSubsidy int64) *BestState {
func newBestState(node *blockNode, blockSize, numTxns, totalTxns uint64,
medianTime time.Time, totalSubsidy int64, nextPoolSize uint32,
nextStakeDiff int64, nextWinners, missed []chainhash.Hash,
nextFinalState [6]byte) *BestState {
prevHash := *zeroHash
if node.parent != nil {
prevHash = node.parent.hash
}
return &BestState{
Hash: node.hash,
Height: node.height,
Bits: node.bits,
BlockSize: blockSize,
NumTxns: numTxns,
TotalTxns: totalTxns,
MedianTime: medianTime,
TotalSubsidy: totalSubsidy,
Hash: node.hash,
PrevHash: prevHash,
Height: node.height,
Bits: node.bits,
NextPoolSize: nextPoolSize,
NextStakeDiff: nextStakeDiff,
BlockSize: blockSize,
NumTxns: numTxns,
TotalTxns: totalTxns,
MedianTime: medianTime,
TotalSubsidy: totalSubsidy,
NextWinningTickets: nextWinners,
MissedTickets: missed,
NextFinalState: nextFinalState,
}
}

Expand Down Expand Up @@ -747,6 +766,15 @@ func (b *BlockChain) connectBlock(node *blockNode, block, parent *dcrutil.Block,
return err
}

// Get the stake node for this node, filling in any data that
// may have yet to have been filled in. In all cases this
// should simply give a pointer to data already prepared, but
// run this anyway to be safe.
stakeNode, err := b.fetchStakeNode(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()
Expand All @@ -761,19 +789,19 @@ func (b *BlockChain) connectBlock(node *blockNode, block, parent *dcrutil.Block,
// Calculate the exact subsidy produced by adding the block.
subsidy := CalculateAddedSubsidy(block, parent)

blockSize := uint64(block.MsgBlock().Header.Size)
state := newBestState(node, blockSize, numTxns, curTotalTxns+numTxns,
node.CalcPastMedianTime(), curTotalSubsidy+subsidy)

// Get the stake node for this node, filling in any data that
// may have yet to have been filled in. In all cases this
// should simply give a pointer to data already prepared, but
// run this anyway to be safe.
stakeNode, err := b.fetchStakeNode(node)
// Calcultate the next stake difficulty.
nextStakeDiff, err := b.calcNextRequiredStakeDifficulty(node)
if err != nil {
return err
}

blockSize := uint64(block.MsgBlock().Header.Size)
state := newBestState(node, blockSize, numTxns, curTotalTxns+numTxns,
node.CalcPastMedianTime(), curTotalSubsidy+subsidy,
uint32(node.stakeNode.PoolSize()), nextStakeDiff,
node.stakeNode.Winners(), node.stakeNode.MissedTickets(),
node.stakeNode.FinalState())

// Atomically insert info into the database.
err = b.db.Update(func(dbTx database.Tx) error {
// Update best block state.
Expand Down Expand Up @@ -917,6 +945,17 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block, parent *dcrutil.Blo
return err
}

// Prepare the information required to update the stake database
// contents.
childStakeNode, err := b.fetchStakeNode(node)
if err != nil {
return err
}
parentStakeNode, err := b.fetchStakeNode(node.parent)
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()
Expand All @@ -936,18 +975,10 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block, parent *dcrutil.Blo

prevNode := node.parent
state := newBestState(prevNode, parentBlockSize, numTxns, newTotalTxns,
prevNode.CalcPastMedianTime(), newTotalSubsidy)

// Prepare the information required to update the stake database
// contents.
childStakeNode, err := b.fetchStakeNode(node)
if err != nil {
return err
}
parentStakeNode, err := b.fetchStakeNode(node.parent)
if err != nil {
return err
}
prevNode.CalcPastMedianTime(), newTotalSubsidy,
uint32(node.stakeNode.PoolSize()), node.sbits,
prevNode.stakeNode.Winners(), prevNode.stakeNode.MissedTickets(),
prevNode.stakeNode.FinalState())

err = b.db.Update(func(dbTx database.Tx) error {
// Update best block state.
Expand Down
14 changes: 12 additions & 2 deletions blockchain/chainio.go
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,8 @@ func (b *BlockChain) createChainState() error {
numTxns := uint64(len(genesisBlock.MsgBlock().Transactions))
blockSize := uint64(genesisBlock.MsgBlock().SerializeSize())
stateSnapshot := newBestState(node, blockSize, numTxns, numTxns,
time.Unix(node.timestamp, 0), 0)
time.Unix(node.timestamp, 0), 0, 0, b.chainParams.MinimumStakeDiff,
nil, nil, earlyFinalState)

// Create the initial the database chain state including creating the
// necessary index buckets and inserting the genesis block.
Expand Down Expand Up @@ -1770,9 +1771,18 @@ func (b *BlockChain) initChainState(interrupt <-chan struct{}) error {
block := utilBlock.MsgBlock()
blockSize := uint64(block.SerializeSize())
numTxns := uint64(len(block.Transactions))

// Calculate the next stake difficulty.
nextStakeDiff, err := b.calcNextRequiredStakeDifficulty(tip)
if err != nil {
return err
}

b.stateSnapshot = newBestState(tip, blockSize, numTxns,
state.totalTxns, tip.CalcPastMedianTime(),
state.totalSubsidy)
state.totalSubsidy, uint32(tip.stakeNode.PoolSize()),
nextStakeDiff, tip.stakeNode.Winners(),
tip.stakeNode.MissedTickets(), tip.stakeNode.FinalState())

return nil
})
Expand Down