multi: Upstream parameter abstraction sync

Upstream commit a7b35d9f9e.

Also, the merge commit contains necessary decred-specific alterations.
It also has the side effect of correcting a couple of min reduction bugs
even though they can't currently ever be hit due to the min reduction
interval flag being disabled for all networks.
This commit is contained in:
Dave Collins 2016-11-16 19:33:34 -06:00
commit 60c812e735
No known key found for this signature in database
GPG Key ID: B8904D9D9C93D1F2
14 changed files with 155 additions and 137 deletions

View File

@ -108,10 +108,14 @@ func chainSetup(dbName string, params *chaincfg.Params) (*blockchain.BlockChain,
}
}
// Copy the chain params to ensure any modifications the tests do to
// the chain parameters do not affect the global instance.
paramsCopy := *params
// Create the main chain instance.
chain, err := blockchain.New(&blockchain.Config{
DB: db,
ChainParams: params,
ChainParams: &paramsCopy,
TimeSource: blockchain.NewMedianTime(),
})

View File

@ -175,11 +175,10 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32,
maxRetargetTimespan := int64(b.chainParams.TargetTimespan) *
b.chainParams.RetargetAdjustmentFactor
// The test network rules allow minimum difficulty blocks after more
// than twice the desired amount of time needed to generate a block has
// elapsed.
if b.chainParams.ResetMinDifficulty {
if durationVal > int64(b.chainParams.TimePerBlock)*2 {
// The test network rules allow minimum difficulty blocks once too much
// time has elapsed without mining a block.
if b.chainParams.ReduceMinDifficulty {
if durationVal > int64(b.chainParams.MinDiffReductionTime) {
return b.chainParams.PowLimitBits
}
}
@ -206,8 +205,7 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32,
// did not have the special testnet minimum difficulty rule applied.
//
// This function MUST be called with the chain state lock held (for writes).
func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32,
error) {
func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, error) {
// Search backwards through the chain for the last block without
// the special rule applied.
blocksPerRetarget := b.chainParams.WorkDiffWindowSize *
@ -259,23 +257,21 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode,
// We're not at a retarget point, return the oldDiff.
if (curNode.height+1)%b.chainParams.WorkDiffWindowSize != 0 {
// The test network rules allow minimum difficulty blocks after
// more than twice the desired amount of time needed to generate
// a block has elapsed.
if b.chainParams.ResetMinDifficulty {
// Return minimum difficulty when more than twice the
// desired amount of time needed to generate a block has
// elapsed.
allowMinTime := curNode.header.Timestamp.Add(
b.chainParams.TimePerBlock * b.chainParams.MinDiffResetTimeFactor)
// For networks that support it, allow special reduction of the
// required difficulty once too much time has elapsed without
// mining a block.
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)
// For every extra target timespan that passes, we halve the
// difficulty.
if newBlockTime.After(allowMinTime) {
timePassed := newBlockTime.Sub(curNode.header.Timestamp)
timePassed -= (b.chainParams.TimePerBlock *
b.chainParams.MinDiffResetTimeFactor)
shifts := uint((timePassed / b.chainParams.TimePerBlock) + 1)
timePassed -= b.chainParams.MinDiffReductionTime
shifts := uint((timePassed / b.chainParams.TargetTimePerBlock) + 1)
// Scale the difficulty with time passed.
oldTarget := CompactToBig(curNode.header.Bits)
@ -371,7 +367,11 @@ func (b *BlockChain) calcNextRequiredDifficulty(curNode *blockNode,
break // Exit for loop when we hit the end.
}
// Get the previous block node.
// Get the previous block node. This function is used over
// simply accessing firstNode.parent directly as it will
// dynamically create previous block nodes as needed. This
// helps allow only the pieces of the chain that are needed
// to remain in memory.
var err error
tempNode := oldNode
oldNode, err = b.getPrevNodeFromNode(oldNode)
@ -490,8 +490,7 @@ func mergeDifficulty(oldDiff int64, newDiff1 int64, newDiff2 int64) int64 {
// and then uses it to determine the next stake difficulty.
// TODO: You can combine the first and second for loops below for a speed up
// if you'd like, I'm not sure how much it matters.
func (b *BlockChain) calcNextRequiredStakeDifficulty(curNode *blockNode) (int64,
error) {
func (b *BlockChain) calcNextRequiredStakeDifficulty(curNode *blockNode) (int64, error) {
alpha := b.chainParams.StakeDiffAlpha
stakeDiffStartHeight := int64(b.chainParams.CoinbaseMaturity) +
1

View File

@ -277,7 +277,7 @@ func uniqueOpReturnScript() []byte {
// good tests which exercise that code, so it wouldn't make sense to use the
// same code to generate them.
func (g *testGenerator) calcFullSubsidy(blockHeight uint32) dcrutil.Amount {
iterations := int64(blockHeight) / g.params.ReductionInterval
iterations := int64(blockHeight) / g.params.SubsidyReductionInterval
subsidy := g.params.BaseSubsidy
for i := int64(0); i < iterations; i++ {
subsidy *= g.params.MulSubsidy

View File

@ -114,10 +114,10 @@ var simNetParams = &chaincfg.Params{
CurrentBlockVersion: 0,
PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff,
ResetMinDifficulty: false,
ReduceMinDifficulty: false,
GenerateSupported: true,
MaximumBlockSize: 1000000,
TimePerBlock: time.Second * 1,
TargetTimePerBlock: time.Second * 1,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 8,
WorkDiffWindows: 4,
@ -125,13 +125,13 @@ var simNetParams = &chaincfg.Params{
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: nil,

View File

@ -951,10 +951,10 @@ var simNetParams = &chaincfg.Params{
CurrentBlockVersion: 0,
PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff,
ResetMinDifficulty: false,
ReduceMinDifficulty: false,
GenerateSupported: true,
MaximumBlockSize: 1000000,
TimePerBlock: time.Second * 1,
TargetTimePerBlock: time.Second * 1,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 8,
WorkDiffWindows: 4,
@ -962,13 +962,13 @@ var simNetParams = &chaincfg.Params{
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: nil,

View File

@ -41,13 +41,13 @@ func NewSubsidyCache(height int64, params *chaincfg.Params) *SubsidyCache {
params: params,
}
iteration := uint64(height / params.ReductionInterval)
iteration := uint64(height / params.SubsidyReductionInterval)
if iteration < subsidyCacheInitWidth {
return &sc
}
for i := iteration - 4; i <= iteration; i++ {
sc.CalcBlockSubsidy(int64(iteration) * params.ReductionInterval)
sc.CalcBlockSubsidy(int64(iteration) * params.SubsidyReductionInterval)
}
return &sc
@ -59,7 +59,7 @@ func NewSubsidyCache(height int64, params *chaincfg.Params) *SubsidyCache {
// has the expected value.
//
// Subsidy calculation for exponential reductions:
// 0 for i in range (0, height / ReductionInterval):
// 0 for i in range (0, height / SubsidyReductionInterval):
// 1 subsidy *= MulSubsidy
// 2 subsidy /= DivSubsidy
//
@ -71,7 +71,7 @@ func (s *SubsidyCache) CalcBlockSubsidy(height int64) int64 {
return s.params.BlockOneSubsidy()
}
iteration := uint64(height / s.params.ReductionInterval)
iteration := uint64(height / s.params.SubsidyReductionInterval)
if iteration == 0 {
return s.params.BaseSubsidy

View File

@ -23,11 +23,11 @@ func TestBlockSubsidy(t *testing.T) {
continue
}
if i%mainnet.ReductionInterval == 0 {
numBlocks := mainnet.ReductionInterval
if i%mainnet.SubsidyReductionInterval == 0 {
numBlocks := mainnet.SubsidyReductionInterval
// First reduction internal, which is reduction interval - 2
// to skip the genesis block and block one.
if i == mainnet.ReductionInterval {
if i == mainnet.SubsidyReductionInterval {
numBlocks -= 2
}
height := i - numBlocks
@ -45,7 +45,7 @@ func TestBlockSubsidy(t *testing.T) {
// First reduction internal, subtract the stake subsidy for
// blocks before the staking system is enabled.
if i == mainnet.ReductionInterval {
if i == mainnet.SubsidyReductionInterval {
totalSubsidy -= stake * (mainnet.StakeValidationHeight - 2)
}
}

View File

@ -1135,6 +1135,9 @@ func (b *BlockChain) CheckBlockStakeSanity(stakeValidationHeight int64, node *bl
// amount, and verifying the signatures to prove the spender was the owner of
// the decred and therefore allowed to spend them. As it checks the inputs,
// it also calculates the total fees for the transaction and returns that value.
//
// NOTE: The transaction MUST have already been sanity checked with the
// CheckTransactionSanity function prior to calling this function.
func CheckTransactionInputs(subsidyCache *SubsidyCache, tx *dcrutil.Tx,
txHeight int64, utxoView *UtxoViewpoint, checkFraudProof bool,
chainParams *chaincfg.Params) (int64, error) {

View File

@ -2050,10 +2050,10 @@ var simNetParams = &chaincfg.Params{
CurrentBlockVersion: 0,
PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff,
ResetMinDifficulty: false,
ReduceMinDifficulty: false,
GenerateSupported: true,
MaximumBlockSize: 1000000,
TimePerBlock: time.Second * 1,
TargetTimePerBlock: time.Second * 1,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 8,
WorkDiffWindows: 4,
@ -2061,13 +2061,13 @@ var simNetParams = &chaincfg.Params{
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: nil,

View File

@ -80,33 +80,48 @@ type TokenPayout struct {
// used by Decred applications to differentiate networks as well as addresses
// and keys for one network from those intended for use on another network.
type Params struct {
Name string
Net wire.CurrencyNet
DefaultPort string
DNSSeeds []string
// Name defines a human-readable identifier for the network.
Name string
// Starting block for the network (block 0).
// Net defines the magic bytes used to identify the network.
Net wire.CurrencyNet
// DefaultPort defines the default peer-to-peer port for the network.
DefaultPort string
// DNSSeeds defines a list of DNS seeds for the network that are used
// as one method to discover peers.
DNSSeeds []string
// GenesisBlock defines the first block of the chain.
GenesisBlock *wire.MsgBlock
// Starting block hash.
// GenesisHash is the starting block hash.
GenesisHash *chainhash.Hash
// The version of the block that the majority of the network is currently
// on.
// CurrentBlockVersion is the version of the block that the majority of
// the network is currently on.
CurrentBlockVersion int32
// Maximum value for nbits (minimum Proof of Work) as a uint256.
// PowLimit defines the highest allowed proof of work value for a block
// as a uint256.
PowLimit *big.Int
// Maximum value for nbits (minimum Proof of Work) in compact form.
// PowLimitBits defines the highest allowed proof of work value for a
// block in compact form.
PowLimitBits uint32
// Testnet difficulty reset flag.
ResetMinDifficulty bool
// ReduceMinDifficulty defines whether the network should reduce the
// minimum required difficulty after a long enough period of time has
// passed without finding a block. This is really only useful for test
// networks and should not be set on a main network.
ReduceMinDifficulty bool
// MinDiffResetTimeFactor is the amount to multiply TimePerBlock by to
// reset the difficulty to the minimum network factor.
MinDiffResetTimeFactor time.Duration
// MinDiffReductionTime is the amount of time after which the minimum
// required difficulty should be reduced when a block hasn't been found.
//
// NOTE: This only applies if ReduceMinDifficulty is true.
MinDiffReductionTime time.Duration
// GenerateSupported specifies whether or not CPU mining is allowed.
GenerateSupported bool
@ -115,9 +130,9 @@ type Params struct {
// on the network.
MaximumBlockSize int
// TimePerBlock is the desired amount of time to generate each block in
// minutes.
TimePerBlock time.Duration
// TargetTimePerBlock is the desired amount of time to generate each
// block.
TargetTimePerBlock time.Duration
// WorkDiffAlpha is the stake difficulty EMA calculation alpha (smoothing)
// value. It is different from a normal EMA alpha. Closer to 1 --> smoother.
@ -131,10 +146,10 @@ type Params struct {
// of the exponentially weighted average.
WorkDiffWindows int64
// targetTimespan is the desired amount of time that should elapse
// before block difficulty requirement is examined to determine how
// TargetTimespan is the desired amount of time that should elapse
// before the block difficulty requirement is examined to determine how
// it should be changed in order to maintain the desired block
// generation rate. This value should correspond to the product of
// generation rate. This value should correspond to the product of
// WorkDiffWindowSize and TimePerBlock above.
TargetTimespan time.Duration
@ -146,7 +161,7 @@ type Params struct {
// Subsidy parameters.
//
// Subsidy calculation for exponential reductions:
// 0 for i in range (0, height / ReductionInterval):
// 0 for i in range (0, height / SubsidyReductionInterval):
// 1 subsidy *= MulSubsidy
// 2 subsidy /= DivSubsidy
//
@ -161,8 +176,8 @@ type Params struct {
// Subsidy reduction divisor.
DivSubsidy int64
// Reduction interval in blocks.
ReductionInterval int64
// SubsidyReductionInterval is the reduction interval in blocks.
SubsidyReductionInterval int64
// WorkRewardProportion is the comparative amount of the subsidy given for
// creating a block.
@ -223,7 +238,8 @@ type Params struct {
// be >= (StakeEnabledHeight + StakeValidationHeight).
TicketExpiry uint32
// Maturity for spending coinbase tx.
// CoinbaseMaturity is the number of blocks required before newly mined
// coins (coinbase transactions) can be spent.
CoinbaseMaturity uint16
// Maturity for spending SStx change outputs.
@ -300,11 +316,11 @@ var MainNetParams = Params{
CurrentBlockVersion: 2,
PowLimit: mainPowLimit,
PowLimitBits: 0x1d00ffff,
ResetMinDifficulty: false,
MinDiffResetTimeFactor: 0x7FFFFFFF,
ReduceMinDifficulty: false,
MinDiffReductionTime: 0, // Does not apply since ReduceMinDifficulty false
GenerateSupported: false,
MaximumBlockSize: 393216,
TimePerBlock: time.Minute * 5,
TargetTimePerBlock: time.Minute * 5,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 144,
WorkDiffWindows: 20,
@ -312,13 +328,13 @@ var MainNetParams = Params{
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 3119582664, // 21m
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 6144,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 3119582664, // 21m
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 6144,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: []Checkpoint{
@ -395,11 +411,11 @@ var TestNetParams = Params{
CurrentBlockVersion: 2,
PowLimit: testNetPowLimit,
PowLimitBits: 0x1e00ffff,
ResetMinDifficulty: false,
MinDiffResetTimeFactor: 0x7FFFFFFF,
ReduceMinDifficulty: false,
MinDiffReductionTime: 0, // Does not apply since ReduceMinDifficulty false
GenerateSupported: true,
MaximumBlockSize: 1000000,
TimePerBlock: time.Minute * 2,
TargetTimePerBlock: time.Minute * 2,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 144,
WorkDiffWindows: 20,
@ -407,13 +423,13 @@ var TestNetParams = Params{
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 2500000000, // 25 Coin
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 2048,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 2500000000, // 25 Coin
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 2048,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: []Checkpoint{
@ -492,25 +508,25 @@ var SimNetParams = Params{
CurrentBlockVersion: 2,
PowLimit: simNetPowLimit,
PowLimitBits: 0x207fffff,
ResetMinDifficulty: false,
MinDiffResetTimeFactor: 0x7FFFFFFF,
ReduceMinDifficulty: false,
MinDiffReductionTime: 0, // Does not apply since ReduceMinDifficulty false
GenerateSupported: true,
MaximumBlockSize: 1000000,
TimePerBlock: time.Second * 1,
TargetTimePerBlock: time.Second,
WorkDiffAlpha: 1,
WorkDiffWindowSize: 8,
WorkDiffWindows: 4,
TargetTimespan: time.Second * 1 * 8, // TimePerBlock * WindowSize
TargetTimespan: time.Second * 8, // TimePerBlock * WindowSize
RetargetAdjustmentFactor: 4,
// Subsidy parameters.
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
ReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
BaseSubsidy: 50000000000,
MulSubsidy: 100,
DivSubsidy: 101,
SubsidyReductionInterval: 128,
WorkRewardProportion: 6,
StakeRewardProportion: 3,
BlockTaxProportion: 1,
// Checkpoints ordered from oldest to newest.
Checkpoints: nil,

View File

@ -151,12 +151,12 @@ func (m *CPUMiner) submitBlock(block *dcrutil.Block) bool {
return false
}
// Occasionally errors are given out for timing errors with
// ResetMinDifficulty and high block works that is above
// ReduceMinDifficulty and high block works that is above
// the target. Feed these to debug.
if m.server.chainParams.ResetMinDifficulty &&
if m.server.chainParams.ReduceMinDifficulty &&
rErr.ErrorCode == blockchain.ErrHighHash {
minrLog.Debugf("Block submitted via CPU miner rejected "+
"because of ResetMinDifficulty time sync failure: %v",
"because of ReduceMinDifficulty time sync failure: %v",
err)
return false
}

View File

@ -1120,13 +1120,10 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew,
// Perform several checks on the transaction inputs using the invariant
// rules in chain for what transactions are allowed into blocks.
// Also returns the fees associated with the transaction which will be
// used later.
// used later. The fraud proof is not checked because it will be
// filled in by the miner.
txFee, err := blockchain.CheckTransactionInputs(mp.subsidyCache,
tx,
nextBlockHeight,
utxoView,
false, // Don't check fraud proof; filled in by miner
mp.cfg.ChainParams)
tx, nextBlockHeight, utxoView, false, mp.cfg.ChainParams)
if err != nil {
if cerr, ok := err.(blockchain.RuleError); ok {
return nil, chainRuleError(cerr)

View File

@ -792,7 +792,7 @@ func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache,
// If we're on testnet, the time since this last block
// listed as the parent must be taken into consideration.
if bm.server.chainParams.ResetMinDifficulty {
if bm.server.chainParams.ReduceMinDifficulty {
parentHash := cptCopy.Block.Header.PrevBlock
requiredDifficulty, err :=
@ -895,7 +895,7 @@ func handleTooFewVoters(subsidyCache *blockchain.SubsidyCache,
// If we're on testnet, the time since this last block
// listed as the parent must be taken into consideration.
if bm.server.chainParams.ResetMinDifficulty {
if bm.server.chainParams.ReduceMinDifficulty {
parentHash := topBlock.MsgBlock().Header.PrevBlock
requiredDifficulty, err :=
@ -1546,12 +1546,10 @@ mempoolLoop:
// Ensure the transaction inputs pass all of the necessary
// preconditions before allowing it to be added to the block.
_, err = blockchain.CheckTransactionInputs(subsidyCache,
tx,
nextBlockHeight,
blockUtxos,
false, // Don't check fraud proofs; missing ones are filled out below
server.chainParams)
// The fraud proof is not checked because it will be filled in
// by the miner.
_, err = blockchain.CheckTransactionInputs(subsidyCache, tx,
nextBlockHeight, blockUtxos, false, server.chainParams)
if err != nil {
minrLog.Tracef("Skipping tx %s due to error in "+
"CheckTransactionInputs: %v", tx.Hash(), err)
@ -2094,7 +2092,7 @@ func UpdateBlockTime(msgBlock *wire.MsgBlock, bManager *blockManager) error {
// If running on a network that requires recalculating the difficulty,
// do so now.
if activeNetParams.ResetMinDifficulty {
if activeNetParams.ReduceMinDifficulty {
difficulty, err := bManager.chain.CalcNextRequiredDifficulty(
newTimestamp)
if err != nil {

View File

@ -3504,15 +3504,16 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru
endHeight = best.Height
}
// Calculate the number of blocks per retarget interval based on the
// chain parameters.
blocksPerRetarget := int64(s.server.chainParams.TargetTimespan /
s.server.chainParams.TargetTimePerBlock)
// Calculate the starting block height based on the passed number of
// blocks. When the passed value is negative, use the last block the
// difficulty changed as the starting height. Also make sure the
// starting height is not before the beginning of the chain.
// Decred TODO: Make sure this blocksPerRetarget value is accurate
blocksPerRetarget := int64(s.server.chainParams.TargetTimespan /
s.server.chainParams.TimePerBlock)
numBlocks := int64(120)
if c.Blocks != nil {
numBlocks = int64(*c.Blocks)