mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
blockchain: Don't store full header in block node.
This modifies the block node structure to include only the specifically used fields, some of which in a more compact format, as opposed to copying the entire header and updates all code and tests accordingly. Not only is this a more efficient approach that helps pave the way for future optimizations, it is also consistent with the upstream code which helps minimize the differences to facilitate easier syncs due to less merge conflicts. In particular, since the merkle and stake roots, number of revocations, size, nonce, and extradata fields aren't used currently, they are no longer copied into the block node. Also, the block node already had a height field, which is also in the header, so this change also removes that duplication. Another change is that the block node now stores the timestamp as an int64 unix-style timestamp which is only 8 bytes versus the old timestamp that was in the header which is a time.Time and thus 24 bytes. It should be noted that future optimizations will very likely end up adding most of the omitted header fields back to the block node as individual fields so the headers can be efficiently reconstructed from memory, however, these changes are still beneficial due to the ability to decouple the block node storage format from the header struct which allows more compact representations and reording of the fields for optimal struct packing. Ultimately, the need for the parent hash can also be removed, which will save an additional 32 bytes which would not be possible without this decoupling.
This commit is contained in:
parent
b486cada60
commit
9d6cf805f4
@ -63,9 +63,15 @@ type blockNode struct {
|
||||
// is when the best chain selection algorithm is used.
|
||||
children []*blockNode
|
||||
|
||||
// hash is the double sha 256 of the block.
|
||||
// hash is the hash of the block this node represents.
|
||||
hash chainhash.Hash
|
||||
|
||||
// parentHash is the hash of the parent block of the block this node
|
||||
// represents. This is kept here over simply relying on parent.hash
|
||||
// directly since block nodes are sparse and the parent node might not be
|
||||
// in memory when its hash is needed.
|
||||
parentHash chainhash.Hash
|
||||
|
||||
// height is the position in the block chain.
|
||||
height int64
|
||||
|
||||
@ -78,8 +84,18 @@ type blockNode struct {
|
||||
// ancestor when switching chains.
|
||||
inMainChain bool
|
||||
|
||||
// header is the full block header.
|
||||
header wire.BlockHeader
|
||||
// Some fields from block headers to aid in best chain selection and
|
||||
// validation.
|
||||
blockVersion int32
|
||||
voteBits uint16
|
||||
finalState [6]byte
|
||||
voters uint16
|
||||
freshStake uint8
|
||||
poolSize uint32
|
||||
bits uint32
|
||||
sbits int64
|
||||
timestamp int64
|
||||
stakeVersion uint32
|
||||
|
||||
// stakeNode contains all the consensus information required for the
|
||||
// staking system. The node also caches information required to add or
|
||||
@ -118,9 +134,19 @@ func newBlockNode(blockHeader *wire.BlockHeader, spentTickets *stake.SpentTicket
|
||||
// collected.
|
||||
node := blockNode{
|
||||
hash: blockHeader.BlockHash(),
|
||||
parentHash: blockHeader.PrevBlock,
|
||||
workSum: CalcWork(blockHeader.Bits),
|
||||
height: int64(blockHeader.Height),
|
||||
header: *blockHeader,
|
||||
blockVersion: blockHeader.Version,
|
||||
voteBits: blockHeader.VoteBits,
|
||||
finalState: blockHeader.FinalState,
|
||||
voters: blockHeader.Voters,
|
||||
freshStake: blockHeader.FreshStake,
|
||||
poolSize: blockHeader.PoolSize,
|
||||
bits: blockHeader.Bits,
|
||||
sbits: blockHeader.SBits,
|
||||
timestamp: blockHeader.Timestamp.Unix(),
|
||||
stakeVersion: blockHeader.StakeVersion,
|
||||
lotteryIV: stake.CalcHash256PRNGIV(hB),
|
||||
ticketsSpent: spentTickets.VotedTickets,
|
||||
ticketsRevoked: spentTickets.RevokedTickets,
|
||||
@ -186,7 +212,7 @@ func newBestState(node *blockNode, blockSize, numTxns, totalTxns uint64, medianT
|
||||
return &BestState{
|
||||
Hash: &node.hash,
|
||||
Height: node.height,
|
||||
Bits: node.header.Bits,
|
||||
Bits: node.bits,
|
||||
BlockSize: blockSize,
|
||||
NumTxns: numTxns,
|
||||
TotalTxns: totalTxns,
|
||||
@ -349,8 +375,8 @@ func (b *BlockChain) GetStakeVersions(hash *chainhash.Hash, count int32) ([]Stak
|
||||
sv := StakeVersions{
|
||||
Hash: prevNode.hash,
|
||||
Height: prevNode.height,
|
||||
BlockVersion: prevNode.header.Version,
|
||||
StakeVersion: prevNode.header.StakeVersion,
|
||||
BlockVersion: prevNode.blockVersion,
|
||||
StakeVersion: prevNode.stakeVersion,
|
||||
Votes: prevNode.votes,
|
||||
}
|
||||
|
||||
@ -666,7 +692,7 @@ func (b *BlockChain) loadBlockNode(dbTx database.Tx, hash *chainhash.Hash) (*blo
|
||||
// further down the line in the blockchain to which the block
|
||||
// could be attached, for example if the node had been pruned from
|
||||
// the index.
|
||||
foundParent, err := b.findNode(&node.header.PrevBlock, maxSearchDepth)
|
||||
foundParent, err := b.findNode(&node.parentHash, maxSearchDepth)
|
||||
if err == nil {
|
||||
node.workSum = node.workSum.Add(foundParent.workSum, node.workSum)
|
||||
foundParent.children = append(foundParent.children, node)
|
||||
@ -711,7 +737,7 @@ func (b *BlockChain) findNode(nodeHash *chainhash.Hash, searchDepth int) (*block
|
||||
break
|
||||
}
|
||||
|
||||
last := foundPrev.header.PrevBlock
|
||||
last := foundPrev.parentHash
|
||||
foundPrev = foundPrev.parent
|
||||
if foundPrev == nil {
|
||||
parent, err := b.loadBlockNode(dbTx, &last)
|
||||
@ -794,7 +820,7 @@ func (b *BlockChain) getPrevNodeFromNode(node *blockNode) (*blockNode, error) {
|
||||
var prevBlockNode *blockNode
|
||||
err := b.db.View(func(dbTx database.Tx) error {
|
||||
var err error
|
||||
prevBlockNode, err = b.loadBlockNode(dbTx, &node.header.PrevBlock)
|
||||
prevBlockNode, err = b.loadBlockNode(dbTx, &node.parentHash)
|
||||
return err
|
||||
})
|
||||
return prevBlockNode, err
|
||||
@ -942,7 +968,7 @@ func (b *BlockChain) BestPrevHash() chainhash.Hash {
|
||||
b.chainLock.Lock()
|
||||
defer b.chainLock.Unlock()
|
||||
|
||||
return b.bestNode.header.PrevBlock
|
||||
return b.bestNode.parentHash
|
||||
}
|
||||
|
||||
// isMajorityVersion determines if a previous number of blocks in the chain
|
||||
@ -955,7 +981,7 @@ func (b *BlockChain) isMajorityVersion(minVer int32, startNode *blockNode, numRe
|
||||
for i := uint64(0); i < b.chainParams.BlockUpgradeNumToCheck &&
|
||||
numFound < numRequired && iterNode != nil; i++ {
|
||||
// This node has a version that is at least the minimum version.
|
||||
if iterNode.header.Version >= minVer {
|
||||
if iterNode.blockVersion >= minVer {
|
||||
numFound++
|
||||
}
|
||||
|
||||
@ -987,11 +1013,11 @@ func (b *BlockChain) calcPastMedianTime(startNode *blockNode) (time.Time, error)
|
||||
|
||||
// Create a slice of the previous few block timestamps used to calculate
|
||||
// the median per the number defined by the constant medianTimeBlocks.
|
||||
timestamps := make([]time.Time, medianTimeBlocks)
|
||||
timestamps := make([]int64, medianTimeBlocks)
|
||||
numNodes := 0
|
||||
iterNode := startNode
|
||||
for i := 0; i < medianTimeBlocks && iterNode != nil; i++ {
|
||||
timestamps[i] = iterNode.header.Timestamp
|
||||
timestamps[i] = iterNode.timestamp
|
||||
numNodes++
|
||||
|
||||
// Get the previous block node. This function is used over
|
||||
@ -1026,7 +1052,7 @@ func (b *BlockChain) calcPastMedianTime(startNode *blockNode) (time.Time, error)
|
||||
// however, be aware that should the medianTimeBlocks constant ever be
|
||||
// changed to an even number, this code will be wrong.
|
||||
medianTimestamp := timestamps[numNodes/2]
|
||||
return medianTimestamp, nil
|
||||
return time.Unix(medianTimestamp, 0), nil
|
||||
}
|
||||
|
||||
// getReorganizeNodes finds the fork point between the main chain and the passed
|
||||
@ -1075,7 +1101,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List
|
||||
|
||||
if n.parent == nil {
|
||||
var err error
|
||||
n.parent, err = b.findNode(&n.header.PrevBlock, maxSearchDepth)
|
||||
n.parent, err = b.findNode(&n.parentHash, maxSearchDepth)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -1564,7 +1590,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parent, err = b.fetchBlockFromHash(&n.header.PrevBlock)
|
||||
parent, err = b.fetchBlockFromHash(&n.parentHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1664,7 +1690,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags
|
||||
for i, e := 0, detachNodes.Front(); e != nil; i, e = i+1, e.Next() {
|
||||
n := e.Value.(*blockNode)
|
||||
block := detachBlocks[i]
|
||||
parent, err := b.fetchBlockFromHash(&n.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&n.parentHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1698,7 +1724,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags
|
||||
block := b.blockCache[n.hash]
|
||||
b.blockCacheLock.RUnlock()
|
||||
|
||||
parent, err := b.fetchBlockFromHash(&n.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&n.parentHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1778,7 +1804,7 @@ func (b *BlockChain) forceHeadReorganization(formerBest chainhash.Hash, newBest
|
||||
|
||||
// Check to make sure our forced-in node validates correctly.
|
||||
view := NewUtxoViewpoint()
|
||||
view.SetBestHash(&b.bestNode.header.PrevBlock)
|
||||
view.SetBestHash(&b.bestNode.parentHash)
|
||||
view.SetStakeViewpoint(ViewpointPrevValidInitial)
|
||||
|
||||
formerBestBlock, err := b.fetchBlockFromHash(&formerBest)
|
||||
@ -1862,12 +1888,12 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *dcrutil.Block, fla
|
||||
|
||||
// We are extending the main (best) chain with a new block. This is the
|
||||
// most common case.
|
||||
if node.header.PrevBlock == b.bestNode.hash {
|
||||
if node.parentHash == b.bestNode.hash {
|
||||
// Perform several checks to verify the block can be connected
|
||||
// to the main chain without violating any rules and without
|
||||
// actually connecting the block.
|
||||
view := NewUtxoViewpoint()
|
||||
view.SetBestHash(&node.header.PrevBlock)
|
||||
view.SetBestHash(&node.parentHash)
|
||||
view.SetStakeViewpoint(ViewpointPrevValidInitial)
|
||||
var stxos []spentTxOut
|
||||
if !fastAdd {
|
||||
@ -1887,7 +1913,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *dcrutil.Block, fla
|
||||
// utxos, spend them, and add the new utxos being created by
|
||||
// this block.
|
||||
if fastAdd {
|
||||
parent, err := b.fetchBlockFromHash(&node.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&node.parentHash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -1913,7 +1939,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *dcrutil.Block, fla
|
||||
}
|
||||
|
||||
validateStr := "validating"
|
||||
txTreeRegularValid := dcrutil.IsFlagSet16(node.header.VoteBits,
|
||||
txTreeRegularValid := dcrutil.IsFlagSet16(node.voteBits,
|
||||
dcrutil.BlockValid)
|
||||
if !txTreeRegularValid {
|
||||
validateStr = "invalidating"
|
||||
@ -2048,8 +2074,8 @@ func (b *BlockChain) isCurrent() bool {
|
||||
//
|
||||
// The chain appears to be current if none of the checks reported
|
||||
// otherwise.
|
||||
minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour)
|
||||
return !b.bestNode.header.Timestamp.Before(minus24Hours)
|
||||
minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix()
|
||||
return b.bestNode.timestamp >= minus24Hours
|
||||
}
|
||||
|
||||
// IsCurrent returns whether or not the chain believes it is current. Several
|
||||
|
||||
@ -1285,7 +1285,7 @@ func (b *BlockChain) createChainState() error {
|
||||
numTxns := uint64(len(genesisBlock.MsgBlock().Transactions))
|
||||
blockSize := uint64(genesisBlock.MsgBlock().SerializeSize())
|
||||
b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns, numTxns,
|
||||
b.bestNode.header.Timestamp, 0)
|
||||
time.Unix(b.bestNode.timestamp, 0), 0)
|
||||
|
||||
// Create the initial the database chain state including creating the
|
||||
// necessary index buckets and inserting the genesis block.
|
||||
@ -1445,7 +1445,7 @@ func (b *BlockChain) initChainState() error {
|
||||
// set.
|
||||
if dbInfo.version >= 2 {
|
||||
node.stakeNode, err = stake.LoadBestNode(dbTx, uint32(node.height),
|
||||
node.hash, node.header, b.chainParams)
|
||||
node.hash, *header, b.chainParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1456,9 +1456,9 @@ func (b *BlockChain) initChainState() error {
|
||||
b.bestNode = node
|
||||
|
||||
// Add the new node to the indices for faster lookups.
|
||||
prevHash := node.header.PrevBlock
|
||||
prevHash := &node.parentHash
|
||||
b.index[node.hash] = node
|
||||
b.depNodes[prevHash] = append(b.depNodes[prevHash], node)
|
||||
b.depNodes[*prevHash] = append(b.depNodes[*prevHash], node)
|
||||
|
||||
// Calculate the median time for the block.
|
||||
medianTime, err := b.calcPastMedianTime(node)
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/chaincfg"
|
||||
"github.com/decred/dcrd/chaincfg/chainhash"
|
||||
"github.com/decred/dcrd/wire"
|
||||
@ -212,7 +213,7 @@ func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, er
|
||||
b.chainParams.WorkDiffWindows
|
||||
iterNode := startNode
|
||||
for iterNode != nil && iterNode.height%blocksPerRetarget != 0 &&
|
||||
iterNode.header.Bits == b.chainParams.PowLimitBits {
|
||||
iterNode.bits == b.chainParams.PowLimitBits {
|
||||
|
||||
// Get the previous block node. This function is used over
|
||||
// simply accessing iterNode.parent directly as it will
|
||||
@ -231,7 +232,7 @@ func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, er
|
||||
// appropriate block was found.
|
||||
lastBits := b.chainParams.PowLimitBits
|
||||
if iterNode != nil {
|
||||
lastBits = iterNode.header.Bits
|
||||
lastBits = iterNode.bits
|
||||
}
|
||||
return lastBits, nil
|
||||
}
|
||||
@ -251,8 +252,8 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode, newBlockTime
|
||||
|
||||
// Get the old difficulty; if we aren't at a block height where it changes,
|
||||
// just return this.
|
||||
oldDiff := curNode.header.Bits
|
||||
oldDiffBig := CompactToBig(curNode.header.Bits)
|
||||
oldDiff := curNode.bits
|
||||
oldDiffBig := CompactToBig(curNode.bits)
|
||||
|
||||
// We're not at a retarget point, return the oldDiff.
|
||||
if (curNode.height+1)%b.chainParams.WorkDiffWindowSize != 0 {
|
||||
@ -262,18 +263,20 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode, newBlockTime
|
||||
if b.chainParams.ReduceMinDifficulty {
|
||||
// Return minimum difficulty when more than the desired
|
||||
// amount of time has elapsed without mining a block.
|
||||
reductionTime := b.chainParams.MinDiffReductionTime
|
||||
allowMinTime := curNode.header.Timestamp.Add(reductionTime)
|
||||
reductionTime := int64(b.chainParams.MinDiffReductionTime /
|
||||
time.Second)
|
||||
allowMinTime := curNode.timestamp + reductionTime
|
||||
|
||||
// For every extra target timespan that passes, we halve the
|
||||
// difficulty.
|
||||
if newBlockTime.After(allowMinTime) {
|
||||
timePassed := newBlockTime.Sub(curNode.header.Timestamp)
|
||||
timePassed -= b.chainParams.MinDiffReductionTime
|
||||
shifts := uint((timePassed / b.chainParams.TargetTimePerBlock) + 1)
|
||||
if newBlockTime.Unix() > allowMinTime {
|
||||
timePassed := newBlockTime.Unix() - curNode.timestamp
|
||||
timePassed -= reductionTime
|
||||
shifts := uint((timePassed / int64(b.chainParams.TargetTimePerBlock/
|
||||
time.Second)) + 1)
|
||||
|
||||
// Scale the difficulty with time passed.
|
||||
oldTarget := CompactToBig(curNode.header.Bits)
|
||||
oldTarget := CompactToBig(curNode.bits)
|
||||
newTarget := new(big.Int)
|
||||
if shifts < maxShift {
|
||||
newTarget.Lsh(oldTarget, shifts)
|
||||
@ -304,9 +307,9 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode, newBlockTime
|
||||
|
||||
// Declare some useful variables.
|
||||
RAFBig := big.NewInt(b.chainParams.RetargetAdjustmentFactor)
|
||||
nextDiffBigMin := CompactToBig(curNode.header.Bits)
|
||||
nextDiffBigMin := CompactToBig(curNode.bits)
|
||||
nextDiffBigMin.Div(nextDiffBigMin, RAFBig)
|
||||
nextDiffBigMax := CompactToBig(curNode.header.Bits)
|
||||
nextDiffBigMax := CompactToBig(curNode.bits)
|
||||
nextDiffBigMax.Mul(nextDiffBigMax, RAFBig)
|
||||
|
||||
alpha := b.chainParams.WorkDiffAlpha
|
||||
@ -324,23 +327,25 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode, newBlockTime
|
||||
var olderTime, windowPeriod int64
|
||||
var weights uint64
|
||||
oldNode := curNode
|
||||
recentTime := curNode.header.Timestamp.UnixNano()
|
||||
recentTime := curNode.timestamp
|
||||
|
||||
for i := int64(0); ; i++ {
|
||||
// Store and reset after reaching the end of every window period.
|
||||
if i%b.chainParams.WorkDiffWindowSize == 0 && i != 0 {
|
||||
olderTime = oldNode.header.Timestamp.UnixNano()
|
||||
olderTime = oldNode.timestamp
|
||||
timeDifference := recentTime - olderTime
|
||||
|
||||
// Just assume we're at the target (no change) if we've
|
||||
// gone all the way back to the genesis block.
|
||||
if oldNode.height == 0 {
|
||||
timeDifference = int64(b.chainParams.TargetTimespan)
|
||||
timeDifference = int64(b.chainParams.TargetTimespan /
|
||||
time.Second)
|
||||
}
|
||||
|
||||
timeDifBig := big.NewInt(timeDifference)
|
||||
timeDifBig.Lsh(timeDifBig, 32) // Add padding
|
||||
targetTemp := big.NewInt(int64(b.chainParams.TargetTimespan))
|
||||
targetTemp := big.NewInt(int64(b.chainParams.TargetTimespan /
|
||||
time.Second))
|
||||
|
||||
windowAdjusted := targetTemp.Div(timeDifBig, targetTemp)
|
||||
|
||||
@ -424,7 +429,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode, newBlockTime
|
||||
// precision.
|
||||
nextDiffBits := BigToCompact(nextDiffBig)
|
||||
log.Debugf("Difficulty retarget at block height %d", curNode.height+1)
|
||||
log.Debugf("Old target %08x (%064x)", curNode.header.Bits, oldDiffBig)
|
||||
log.Debugf("Old target %08x (%064x)", curNode.bits, oldDiffBig)
|
||||
log.Debugf("New target %08x (%064x)", nextDiffBits, CompactToBig(nextDiffBits))
|
||||
|
||||
return nextDiffBits, nil
|
||||
@ -516,7 +521,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV1(curNode *blockNode) (int6
|
||||
|
||||
// Get the old difficulty; if we aren't at a block height where it changes,
|
||||
// just return this.
|
||||
oldDiff := curNode.header.SBits
|
||||
oldDiff := curNode.sbits
|
||||
if (curNode.height+1)%b.chainParams.StakeDiffWindowSize != 0 {
|
||||
return oldDiff, nil
|
||||
}
|
||||
@ -543,7 +548,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV1(curNode *blockNode) (int6
|
||||
// First adjust based on ticketPoolSize. Skew the difference
|
||||
// in ticketPoolSize by max adjustment factor to help
|
||||
// weight ticket pool size versus tickets per block.
|
||||
poolSizeSkew := (int64(oldNode.header.PoolSize)-
|
||||
poolSizeSkew := (int64(oldNode.poolSize)-
|
||||
targetForTicketPool)*TicketPoolWeight + targetForTicketPool
|
||||
|
||||
// Don't let this be negative or zero.
|
||||
@ -636,7 +641,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV1(curNode *blockNode) (int6
|
||||
|
||||
for i := int64(0); ; i++ {
|
||||
// Add the fresh stake into the store for this window period.
|
||||
windowFreshStake += int64(oldNode.header.FreshStake)
|
||||
windowFreshStake += int64(oldNode.freshStake)
|
||||
|
||||
// Store and reset after reaching the end of every window period.
|
||||
if (i+1)%b.chainParams.StakeDiffWindowSize == 0 {
|
||||
@ -790,7 +795,7 @@ func (b *BlockChain) sumPurchasedTickets(startNode *blockNode, numToSum int64) (
|
||||
for node, numTraversed := startNode, int64(0); node != nil &&
|
||||
numTraversed < numToSum; numTraversed++ {
|
||||
|
||||
numPurchased += int64(node.header.FreshStake)
|
||||
numPurchased += int64(node.freshStake)
|
||||
|
||||
// Get the previous block node. This function is used over
|
||||
// simply accessing iterNode.parent directly as it will
|
||||
@ -902,7 +907,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV2(curNode *blockNode) (int6
|
||||
// Return the previous block's difficulty requirements if the next block
|
||||
// is not at a difficulty retarget interval.
|
||||
intervalSize := b.chainParams.StakeDiffWindowSize
|
||||
curDiff := curNode.header.SBits
|
||||
curDiff := curNode.sbits
|
||||
if nextHeight%intervalSize != 0 {
|
||||
return curDiff, nil
|
||||
}
|
||||
@ -922,7 +927,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV2(curNode *blockNode) (int6
|
||||
return 0, err
|
||||
}
|
||||
if prevRetargetNode != nil {
|
||||
prevPoolSize = int64(prevRetargetNode.header.PoolSize)
|
||||
prevPoolSize = int64(prevRetargetNode.poolSize)
|
||||
}
|
||||
ticketMaturity := int64(b.chainParams.TicketMaturity)
|
||||
prevImmatureTickets, err := b.sumPurchasedTickets(prevRetargetNode,
|
||||
@ -945,7 +950,7 @@ func (b *BlockChain) calcNextRequiredStakeDifficultyV2(curNode *blockNode) (int6
|
||||
}
|
||||
|
||||
// Calculate and return the final next required difficulty.
|
||||
curPoolSizeAll := int64(curNode.header.PoolSize) + immatureTickets
|
||||
curPoolSizeAll := int64(curNode.poolSize) + immatureTickets
|
||||
return calcNextStakeDiffV2(b.chainParams, nextHeight, curDiff,
|
||||
prevPoolSizeAll, curPoolSizeAll), nil
|
||||
}
|
||||
@ -1033,7 +1038,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV1(curNode *blockNode, ticketsIn
|
||||
// Create a fake blockchain on top of the current best node with
|
||||
// the number of freshly purchased tickets as indicated by the
|
||||
// user.
|
||||
oldDiff := curNode.header.SBits
|
||||
oldDiff := curNode.sbits
|
||||
topNode := curNode
|
||||
if (curNode.height+1)%b.chainParams.StakeDiffWindowSize != 0 {
|
||||
nextAdjHeight := ((curNode.height /
|
||||
@ -1060,13 +1065,13 @@ func (b *BlockChain) estimateNextStakeDifficultyV1(curNode *blockNode, ticketsIn
|
||||
// used to calculate the next difficulty below.
|
||||
ticketsToInsert := ticketsInWindow
|
||||
for i := curNode.height + 1; i < nextAdjHeight; i++ {
|
||||
emptyHeader := new(wire.BlockHeader)
|
||||
var emptyHeader wire.BlockHeader
|
||||
emptyHeader.Height = uint32(i)
|
||||
|
||||
// User a constant pool size for estimate, since
|
||||
// this has much less fluctuation than freshStake.
|
||||
// TODO Use a better pool size estimate?
|
||||
emptyHeader.PoolSize = curNode.header.PoolSize
|
||||
emptyHeader.PoolSize = curNode.poolSize
|
||||
|
||||
// Insert the fake fresh stake into each block,
|
||||
// decrementing the amount we need to use each
|
||||
@ -1083,17 +1088,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV1(curNode *blockNode, ticketsIn
|
||||
// Connect the header.
|
||||
emptyHeader.PrevBlock = topNode.hash
|
||||
|
||||
// Make up a node hash.
|
||||
hB, err := emptyHeader.Bytes()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
emptyHeaderHash := chainhash.HashH(hB)
|
||||
|
||||
thisNode := new(blockNode)
|
||||
thisNode.header = *emptyHeader
|
||||
thisNode.hash = emptyHeaderHash
|
||||
thisNode.height = i
|
||||
thisNode := newBlockNode(&emptyHeader, &stake.SpentTicketsInBlock{})
|
||||
thisNode.parent = topNode
|
||||
topNode = thisNode
|
||||
}
|
||||
@ -1121,7 +1116,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV1(curNode *blockNode, ticketsIn
|
||||
// First adjust based on ticketPoolSize. Skew the difference
|
||||
// in ticketPoolSize by max adjustment factor to help
|
||||
// weight ticket pool size versus tickets per block.
|
||||
poolSizeSkew := (int64(oldNode.header.PoolSize)-
|
||||
poolSizeSkew := (int64(oldNode.poolSize)-
|
||||
targetForTicketPool)*TicketPoolWeight + targetForTicketPool
|
||||
|
||||
// Don't let this be negative or zero.
|
||||
@ -1214,7 +1209,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV1(curNode *blockNode, ticketsIn
|
||||
|
||||
for i := int64(0); ; i++ {
|
||||
// Add the fresh stake into the store for this window period.
|
||||
windowFreshStake += int64(oldNode.header.FreshStake)
|
||||
windowFreshStake += int64(oldNode.freshStake)
|
||||
|
||||
// Store and reset after reaching the end of every window period.
|
||||
if (i+1)%b.chainParams.StakeDiffWindowSize == 0 {
|
||||
@ -1390,7 +1385,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV2(curNode *blockNode, newTicket
|
||||
return 0, err
|
||||
}
|
||||
if prevRetargetNode != nil {
|
||||
prevPoolSize = int64(prevRetargetNode.header.PoolSize)
|
||||
prevPoolSize = int64(prevRetargetNode.poolSize)
|
||||
}
|
||||
prevImmatureTickets, err := b.sumPurchasedTickets(prevRetargetNode,
|
||||
ticketMaturity)
|
||||
@ -1400,7 +1395,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV2(curNode *blockNode, newTicket
|
||||
|
||||
// Return the existing ticket price for the first few intervals to avoid
|
||||
// division by zero and encourage initial pool population.
|
||||
curDiff := curNode.header.SBits
|
||||
curDiff := curNode.sbits
|
||||
prevPoolSizeAll := prevPoolSize + prevImmatureTickets
|
||||
if prevPoolSizeAll == 0 {
|
||||
return curDiff, nil
|
||||
@ -1447,7 +1442,7 @@ func (b *BlockChain) estimateNextStakeDifficultyV2(curNode *blockNode, newTicket
|
||||
}
|
||||
|
||||
// Calculate what the pool size would be as of the next interval.
|
||||
curPoolSize := int64(curNode.header.PoolSize)
|
||||
curPoolSize := int64(curNode.poolSize)
|
||||
estimatedPoolSize := curPoolSize + maturingTickets - pendingVotes
|
||||
estimatedImmatureTickets := remainingImmatureTickets + newTickets
|
||||
estimatedPoolSizeAll := estimatedPoolSize + estimatedImmatureTickets
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2017 The Decred developers
|
||||
// Copyright (c) 2015-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -421,7 +421,7 @@ nextTest:
|
||||
|
||||
for i := uint32(0); i < ticketInfo.numNodes; i++ {
|
||||
// Make up a header.
|
||||
nextHeight := bc.bestNode.header.Height + 1
|
||||
nextHeight := uint32(bc.bestNode.height) + 1
|
||||
header := &wire.BlockHeader{
|
||||
Version: 4,
|
||||
SBits: ticketInfo.stakeDiff,
|
||||
@ -723,7 +723,7 @@ nextTest:
|
||||
|
||||
for i := uint32(0); i < ticketInfo.numNodes; i++ {
|
||||
// Make up a header.
|
||||
nextHeight := bc.bestNode.header.Height + 1
|
||||
nextHeight := uint32(bc.bestNode.height) + 1
|
||||
header := &wire.BlockHeader{
|
||||
Version: 4,
|
||||
SBits: ticketInfo.stakeDiff,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred developers
|
||||
// Copyright (c) 2015-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -15,7 +15,6 @@ package blockchain
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/decred/dcrd/blockchain/stake"
|
||||
"github.com/decred/dcrd/wire"
|
||||
@ -23,7 +22,7 @@ import (
|
||||
|
||||
// TstTimeSorter makes the internal timeSorter type available to the test
|
||||
// package.
|
||||
func TstTimeSorter(times []time.Time) sort.Interface {
|
||||
func TstTimeSorter(times []int64) sort.Interface {
|
||||
return timeSorter(times)
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 The Decred developers
|
||||
// Copyright (c) 2017-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -37,7 +37,7 @@ func TestCalcSequenceLock(t *testing.T) {
|
||||
params := &chaincfg.SimNetParams
|
||||
bc := newFakeChain(params)
|
||||
node := bc.bestNode
|
||||
blockTime := node.header.Timestamp
|
||||
blockTime := time.Unix(node.timestamp, 0)
|
||||
for i := uint32(0); i < numBlocks; i++ {
|
||||
blockTime = blockTime.Add(time.Second)
|
||||
node = newFakeNode(node, 1, 1, 0, blockTime)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016 The Decred developers
|
||||
// Copyright (c) 2016-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -170,7 +170,7 @@ func (b *BlockChain) isStakeMajorityVersion(minVer uint32, prevNode *blockNode)
|
||||
versionCount := int32(0)
|
||||
iterNode := node
|
||||
for i := int64(0); i < b.chainParams.StakeVersionInterval && iterNode != nil; i++ {
|
||||
if iterNode.header.StakeVersion >= minVer {
|
||||
if iterNode.stakeVersion >= minVer {
|
||||
versionCount += 1
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ func (b *BlockChain) calcPriorStakeVersion(prevNode *blockNode) (uint32, error)
|
||||
versions := make(map[uint32]int32) // [version][count]
|
||||
iterNode := node
|
||||
for i := int64(0); i < b.chainParams.StakeVersionInterval && iterNode != nil; i++ {
|
||||
versions[iterNode.header.StakeVersion]++
|
||||
versions[iterNode.stakeVersion]++
|
||||
|
||||
var err error
|
||||
iterNode, err = b.getPrevNodeFromNode(iterNode)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016 The Decred developers
|
||||
// Copyright (c) 2016-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -350,8 +350,8 @@ func TestCalcStakeVersionByNode(t *testing.T) {
|
||||
set: func(node *blockNode) {
|
||||
if int64(node.height) > svh {
|
||||
appendFakeVotes(node, tpb, 3, 0)
|
||||
node.header.StakeVersion = 2
|
||||
node.header.Version = 3
|
||||
node.stakeVersion = 2
|
||||
node.blockVersion = 3
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -362,8 +362,8 @@ func TestCalcStakeVersionByNode(t *testing.T) {
|
||||
set: func(node *blockNode) {
|
||||
if int64(node.height) > svh {
|
||||
appendFakeVotes(node, tpb, 2, 0)
|
||||
node.header.StakeVersion = 3
|
||||
node.header.Version = 3
|
||||
node.stakeVersion = 3
|
||||
node.blockVersion = 3
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -705,7 +705,7 @@ func TestIsStakeMajorityVersion(t *testing.T) {
|
||||
// Create new BlockChain in order to blow away cache.
|
||||
bc := newFakeChain(params)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = test.startStakeVersion
|
||||
node.stakeVersion = test.startStakeVersion
|
||||
|
||||
ticketCount = 0
|
||||
|
||||
@ -778,7 +778,7 @@ func TestLarge(t *testing.T) {
|
||||
// Create new BlockChain in order to blow away cache.
|
||||
bc := newFakeChain(params)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = test.startStakeVersion
|
||||
node.stakeVersion = test.startStakeVersion
|
||||
|
||||
for i := int64(1); i <= test.numNodes; i++ {
|
||||
node = newFakeNode(node, test.blockVersion,
|
||||
|
||||
@ -282,7 +282,7 @@ func BlockOneCoinbasePaysTokens(tx *dcrutil.Tx, params *chaincfg.Params) error {
|
||||
|
||||
// CoinbasePaysTax checks to see if a given block's coinbase correctly pays
|
||||
// tax to the developer organization.
|
||||
func CoinbasePaysTax(subsidyCache *SubsidyCache, tx *dcrutil.Tx, height uint32, voters uint16, params *chaincfg.Params) error {
|
||||
func CoinbasePaysTax(subsidyCache *SubsidyCache, tx *dcrutil.Tx, height int64, voters uint16, params *chaincfg.Params) error {
|
||||
// Taxes only apply from block 2 onwards.
|
||||
if height <= 1 {
|
||||
return nil
|
||||
@ -311,7 +311,7 @@ func CoinbasePaysTax(subsidyCache *SubsidyCache, tx *dcrutil.Tx, height uint32,
|
||||
|
||||
// Get the amount of subsidy that should have been paid out to
|
||||
// the organization, then check it.
|
||||
orgSubsidy := CalcBlockTaxSubsidy(subsidyCache, int64(height), voters, params)
|
||||
orgSubsidy := CalcBlockTaxSubsidy(subsidyCache, height, voters, params)
|
||||
if orgSubsidy != taxOutput.Value {
|
||||
errStr := fmt.Sprintf("amount in output 0 has non matching org "+
|
||||
"calculated amount; got %v, want %v", taxOutput.Value,
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred developers
|
||||
// Copyright (c) 2015-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// timeSorter implements sort.Interface to allow a slice of timestamps to
|
||||
// be sorted.
|
||||
type timeSorter []time.Time
|
||||
type timeSorter []int64
|
||||
|
||||
// Len returns the number of timestamps in the slice. It is part of the
|
||||
// sort.Interface implementation.
|
||||
@ -28,5 +24,5 @@ func (s timeSorter) Swap(i, j int) {
|
||||
// Less returns whether the timstamp with index i should sort before the
|
||||
// timestamp with index j. It is part of the sort.Interface implementation.
|
||||
func (s timeSorter) Less(i, j int) bool {
|
||||
return s[i].Before(s[j])
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred developers
|
||||
// Copyright (c) 2015-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/decred/dcrd/blockchain"
|
||||
)
|
||||
@ -17,31 +16,29 @@ import (
|
||||
// TestTimeSorter tests the timeSorter implementation.
|
||||
func TestTimeSorter(t *testing.T) {
|
||||
tests := []struct {
|
||||
in []time.Time
|
||||
want []time.Time
|
||||
in []int64
|
||||
want []int64
|
||||
}{
|
||||
{
|
||||
in: []time.Time{
|
||||
time.Unix(1351228575, 0), // Fri Oct 26 05:16:15 UTC 2012 (Block #205000)
|
||||
time.Unix(1351228575, 1), // Fri Oct 26 05:16:15 UTC 2012 (+1 nanosecond)
|
||||
time.Unix(1348310759, 0), // Sat Sep 22 10:45:59 UTC 2012 (Block #200000)
|
||||
time.Unix(1305758502, 0), // Wed May 18 22:41:42 UTC 2011 (Block #125000)
|
||||
time.Unix(1347777156, 0), // Sun Sep 16 06:32:36 UTC 2012 (Block #199000)
|
||||
time.Unix(1349492104, 0), // Sat Oct 6 02:55:04 UTC 2012 (Block #202000)
|
||||
in: []int64{
|
||||
1351228575, // Fri Oct 26 05:16:15 UTC 2012 (Block #205000)
|
||||
1348310759, // Sat Sep 22 10:45:59 UTC 2012 (Block #200000)
|
||||
1305758502, // Wed May 18 22:41:42 UTC 2011 (Block #125000)
|
||||
1347777156, // Sun Sep 16 06:32:36 UTC 2012 (Block #199000)
|
||||
1349492104, // Sat Oct 6 02:55:04 UTC 2012 (Block #202000)
|
||||
},
|
||||
want: []time.Time{
|
||||
time.Unix(1305758502, 0), // Wed May 18 22:41:42 UTC 2011 (Block #125000)
|
||||
time.Unix(1347777156, 0), // Sun Sep 16 06:32:36 UTC 2012 (Block #199000)
|
||||
time.Unix(1348310759, 0), // Sat Sep 22 10:45:59 UTC 2012 (Block #200000)
|
||||
time.Unix(1349492104, 0), // Sat Oct 6 02:55:04 UTC 2012 (Block #202000)
|
||||
time.Unix(1351228575, 0), // Fri Oct 26 05:16:15 UTC 2012 (Block #205000)
|
||||
time.Unix(1351228575, 1), // Fri Oct 26 05:16:15 UTC 2012 (+1 nanosecond)
|
||||
want: []int64{
|
||||
1305758502, // Wed May 18 22:41:42 UTC 2011 (Block #125000)
|
||||
1347777156, // Sun Sep 16 06:32:36 UTC 2012 (Block #199000)
|
||||
1348310759, // Sat Sep 22 10:45:59 UTC 2012 (Block #200000)
|
||||
1349492104, // Sat Oct 6 02:55:04 UTC 2012 (Block #202000)
|
||||
1351228575, // Fri Oct 26 05:16:15 UTC 2012 (Block #205000)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
result := make([]time.Time, len(test.in))
|
||||
result := make([]int64, len(test.in))
|
||||
copy(result, test.in)
|
||||
sort.Sort(blockchain.TstTimeSorter(result))
|
||||
if !reflect.DeepEqual(result, test.want) {
|
||||
|
||||
@ -1093,7 +1093,7 @@ func (b *BlockChain) FetchUtxoView(tx *dcrutil.Tx, treeValid bool) (*UtxoViewpoi
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parent, err := b.fetchBlockFromHash(&b.bestNode.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&b.bestNode.parentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Copyright (c) 2015-2017 The Decred developers
|
||||
// Copyright (c) 2015-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -852,7 +852,7 @@ func (b *BlockChain) CheckBlockStakeSanity(stakeValidationHeight int64, node *bl
|
||||
blockHash := block.Hash()
|
||||
prevBlockHash := &msgBlock.Header.PrevBlock
|
||||
poolSize := int(msgBlock.Header.PoolSize)
|
||||
finalState := node.header.FinalState
|
||||
finalState := msgBlock.Header.FinalState
|
||||
|
||||
ticketsPerBlock := int(b.chainParams.TicketsPerBlock)
|
||||
|
||||
@ -2226,7 +2226,7 @@ func (b *BlockChain) checkTransactionsAndConnect(subsidyCache *SubsidyCache, inp
|
||||
if txTree { //TxTreeRegular
|
||||
// Apply penalty to fees if we're at stake validation height.
|
||||
if node.height >= b.chainParams.StakeValidationHeight {
|
||||
totalFees *= int64(node.header.Voters)
|
||||
totalFees *= int64(node.voters)
|
||||
totalFees /= int64(b.chainParams.TicketsPerBlock)
|
||||
}
|
||||
|
||||
@ -2241,9 +2241,9 @@ func (b *BlockChain) checkTransactionsAndConnect(subsidyCache *SubsidyCache, inp
|
||||
expAtomOut = subsidyCache.CalcBlockSubsidy(node.height)
|
||||
} else {
|
||||
subsidyWork := CalcBlockWorkSubsidy(subsidyCache,
|
||||
node.height, node.header.Voters, b.chainParams)
|
||||
node.height, node.voters, b.chainParams)
|
||||
subsidyTax := CalcBlockTaxSubsidy(subsidyCache,
|
||||
node.height, node.header.Voters, b.chainParams)
|
||||
node.height, node.voters, b.chainParams)
|
||||
expAtomOut = subsidyWork + subsidyTax + totalFees
|
||||
}
|
||||
|
||||
@ -2294,7 +2294,7 @@ func (b *BlockChain) checkTransactionsAndConnect(subsidyCache *SubsidyCache, inp
|
||||
// with the height of the current block.
|
||||
expAtomOut = CalcStakeVoteSubsidy(subsidyCache,
|
||||
node.height-1, b.chainParams) *
|
||||
int64(node.header.Voters)
|
||||
int64(node.voters)
|
||||
} else {
|
||||
expAtomOut = totalFees
|
||||
}
|
||||
@ -2360,7 +2360,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *dcrutil.Block, ut
|
||||
// allowed a block that is no longer valid. However, since the
|
||||
// implementation only currently uses memory for the side chain blocks,
|
||||
// it isn't currently necessary.
|
||||
parentBlock, err := b.fetchBlockFromHash(&node.header.PrevBlock)
|
||||
parentBlock, err := b.fetchBlockFromHash(&node.parentHash)
|
||||
if err != nil {
|
||||
return ruleError(ErrMissingParent, err.Error())
|
||||
}
|
||||
@ -2373,16 +2373,16 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *dcrutil.Block, ut
|
||||
}
|
||||
|
||||
// Ensure the view is for the node being checked.
|
||||
if !utxoView.BestHash().IsEqual(&node.header.PrevBlock) {
|
||||
if !utxoView.BestHash().IsEqual(&node.parentHash) {
|
||||
return AssertError(fmt.Sprintf("inconsistent view when "+
|
||||
"checking block connection: best hash is %v instead "+
|
||||
"of expected %v", utxoView.BestHash(),
|
||||
node.header.PrevBlock))
|
||||
node.parentHash))
|
||||
}
|
||||
|
||||
// Check that the coinbase pays the tax, if applicable.
|
||||
err = CoinbasePaysTax(b.subsidyCache, block.Transactions()[0],
|
||||
node.header.Height, node.header.Voters, b.chainParams)
|
||||
err = CoinbasePaysTax(b.subsidyCache, block.Transactions()[0], node.height,
|
||||
node.voters, b.chainParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2422,7 +2422,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *dcrutil.Block, ut
|
||||
// signature operations in each of the input transaction public key
|
||||
// scripts.
|
||||
// Do this for all TxTrees.
|
||||
regularTxTreeValid := dcrutil.IsFlagSet16(node.header.VoteBits,
|
||||
regularTxTreeValid := dcrutil.IsFlagSet16(node.voteBits,
|
||||
dcrutil.BlockValid)
|
||||
thisNodeStakeViewpoint := ViewpointPrevInvalidStake
|
||||
thisNodeRegularViewpoint := ViewpointPrevInvalidRegular
|
||||
@ -2657,7 +2657,7 @@ func (b *BlockChain) CheckConnectBlock(block *dcrutil.Block) error {
|
||||
return err
|
||||
}
|
||||
|
||||
parent, err := b.fetchBlockFromHash(&n.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&n.parentHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -2701,7 +2701,7 @@ func (b *BlockChain) CheckConnectBlock(block *dcrutil.Block) error {
|
||||
n.hash)
|
||||
}
|
||||
|
||||
parent, err := b.fetchBlockFromHash(&n.header.PrevBlock)
|
||||
parent, err := b.fetchBlockFromHash(&n.parentHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 The decred developers
|
||||
// Copyright (c) 2017-2018 The Decred developers
|
||||
// Copyright (c) 2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 The Decred developers
|
||||
// Copyright (c) 2017-2018 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -161,7 +161,7 @@ func TestNoQuorum(t *testing.T) {
|
||||
params := defaultParams(pedro)
|
||||
bc := newFakeChain(¶ms)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = posVersion
|
||||
node.stakeVersion = posVersion
|
||||
|
||||
// get to svi
|
||||
curTimestamp := time.Now()
|
||||
@ -317,7 +317,7 @@ func TestYesQuorum(t *testing.T) {
|
||||
params := defaultParams(pedro)
|
||||
bc := newFakeChain(¶ms)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = posVersion
|
||||
node.stakeVersion = posVersion
|
||||
|
||||
// get to svi
|
||||
curTimestamp := time.Now()
|
||||
@ -1493,7 +1493,7 @@ func TestVoting(t *testing.T) {
|
||||
// We have to reset the cache for every test.
|
||||
bc := newFakeChain(¶ms)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = test.startStakeVersion
|
||||
node.stakeVersion = test.startStakeVersion
|
||||
|
||||
t.Logf("running: %v", test.name)
|
||||
|
||||
@ -1526,8 +1526,7 @@ func TestVoting(t *testing.T) {
|
||||
}
|
||||
t.Logf("Height %v, Start time %v, curTime %v, delta %v",
|
||||
node.height, params.Deployments[4][0].StartTime,
|
||||
node.header.Timestamp.Unix(),
|
||||
node.header.Timestamp.Unix()-
|
||||
node.timestamp, node.timestamp-
|
||||
int64(params.Deployments[4][0].StartTime))
|
||||
ts, err := bc.ThresholdState(&node.hash, posVersion,
|
||||
test.vote.Id)
|
||||
@ -1738,7 +1737,7 @@ func TestParallelVoting(t *testing.T) {
|
||||
// We have to reset the cache for every test.
|
||||
bc := newFakeChain(¶ms)
|
||||
node := bc.bestNode
|
||||
node.header.StakeVersion = test.startStakeVersion
|
||||
node.stakeVersion = test.startStakeVersion
|
||||
|
||||
curTimestamp := time.Now()
|
||||
for k := range test.expectedState[0] {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user