mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-08-23 17:47:24 +00:00
chaincfg/blockchain: Parameterize more chain consts. (#732)
This moves several of the chain constants to the Params struct in the chaincfg package which is intended for that purpose. This is mostly a backport of the same modifications made in Decred along with a few additional things cleaned up. The following is an overview of the changes: - Comment all fields in the Params struct definition - Add locals to BlockChain instance for the calculated values based on the provided chain params - Rename the following param fields: - SubsidyHalvingInterval -> SubsidyReductionInterval - ResetMinDifficulty -> ReduceMinDifficulty - Add new Param fields: - CoinbaseMaturity - TargetTimePerBlock - TargetTimespan - BlocksPerRetarget - RetargetAdjustmentFactor - MinDiffReductionTime
This commit is contained in:
parent
bd4e64d1d4
commit
a7b35d9f9e
11 changed files with 183 additions and 123 deletions
|
@ -24,12 +24,6 @@ const (
|
||||||
// maxOrphanBlocks is the maximum number of orphan blocks that can be
|
// maxOrphanBlocks is the maximum number of orphan blocks that can be
|
||||||
// queued.
|
// queued.
|
||||||
maxOrphanBlocks = 100
|
maxOrphanBlocks = 100
|
||||||
|
|
||||||
// minMemoryNodes is the minimum number of consecutive nodes needed
|
|
||||||
// in memory in order to perform all necessary validation. It is used
|
|
||||||
// to determine when it's safe to prune nodes from memory without
|
|
||||||
// causing constant dynamic reloading.
|
|
||||||
minMemoryNodes = BlocksPerRetarget
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// blockNode represents a block within the block chain and is primarily used to
|
// blockNode represents a block within the block chain and is primarily used to
|
||||||
|
@ -170,6 +164,22 @@ type BlockChain struct {
|
||||||
sigCache *txscript.SigCache
|
sigCache *txscript.SigCache
|
||||||
indexManager IndexManager
|
indexManager IndexManager
|
||||||
|
|
||||||
|
// The following fields are calculated based upon the provided chain
|
||||||
|
// parameters. They are also set when the instance is created and
|
||||||
|
// can't be changed afterwards, so there is no need to protect them with
|
||||||
|
// a separate mutex.
|
||||||
|
//
|
||||||
|
// minMemoryNodes is the minimum number of consecutive nodes needed
|
||||||
|
// in memory in order to perform all necessary validation. It is used
|
||||||
|
// to determine when it's safe to prune nodes from memory without
|
||||||
|
// causing constant dynamic reloading. This is typically the same value
|
||||||
|
// as blocksPerRetarget, but it is separated here for tweakability and
|
||||||
|
// testability.
|
||||||
|
minRetargetTimespan int64 // target timespan / adjustment factor
|
||||||
|
maxRetargetTimespan int64 // target timespan * adjustment factor
|
||||||
|
blocksPerRetarget int32 // target timespan / target time per block
|
||||||
|
minMemoryNodes int32
|
||||||
|
|
||||||
// chainLock protects concurrent access to the vast majority of the
|
// chainLock protects concurrent access to the vast majority of the
|
||||||
// fields in this struct below this point.
|
// fields in this struct below this point.
|
||||||
chainLock sync.RWMutex
|
chainLock sync.RWMutex
|
||||||
|
@ -553,7 +563,7 @@ func (b *BlockChain) pruneBlockNodes() error {
|
||||||
// the latter loads the node and the goal is to find nodes still in
|
// the latter loads the node and the goal is to find nodes still in
|
||||||
// memory that can be pruned.
|
// memory that can be pruned.
|
||||||
newRootNode := b.bestNode
|
newRootNode := b.bestNode
|
||||||
for i := int32(0); i < minMemoryNodes-1 && newRootNode != nil; i++ {
|
for i := int32(0); i < b.minMemoryNodes-1 && newRootNode != nil; i++ {
|
||||||
newRootNode = newRootNode.parent
|
newRootNode = newRootNode.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1464,9 @@ func New(config *Config) (*BlockChain, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetTimespan := int64(params.TargetTimespan)
|
||||||
|
targetTimePerBlock := int64(params.TargetTimePerBlock)
|
||||||
|
adjustmentFactor := params.RetargetAdjustmentFactor
|
||||||
b := BlockChain{
|
b := BlockChain{
|
||||||
checkpointsByHeight: checkpointsByHeight,
|
checkpointsByHeight: checkpointsByHeight,
|
||||||
db: config.DB,
|
db: config.DB,
|
||||||
|
@ -1462,6 +1475,10 @@ func New(config *Config) (*BlockChain, error) {
|
||||||
notifications: config.Notifications,
|
notifications: config.Notifications,
|
||||||
sigCache: config.SigCache,
|
sigCache: config.SigCache,
|
||||||
indexManager: config.IndexManager,
|
indexManager: config.IndexManager,
|
||||||
|
minRetargetTimespan: targetTimespan / adjustmentFactor,
|
||||||
|
maxRetargetTimespan: targetTimespan * adjustmentFactor,
|
||||||
|
blocksPerRetarget: int32(targetTimespan / targetTimePerBlock),
|
||||||
|
minMemoryNodes: int32(targetTimespan / targetTimePerBlock),
|
||||||
bestNode: nil,
|
bestNode: nil,
|
||||||
index: make(map[chainhash.Hash]*blockNode),
|
index: make(map[chainhash.Hash]*blockNode),
|
||||||
depNodes: make(map[chainhash.Hash][]*blockNode),
|
depNodes: make(map[chainhash.Hash][]*blockNode),
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestHaveBlock(t *testing.T) {
|
||||||
// Since we're not dealing with the real block chain, disable
|
// Since we're not dealing with the real block chain, disable
|
||||||
// checkpoints and set the coinbase maturity to 1.
|
// checkpoints and set the coinbase maturity to 1.
|
||||||
chain.DisableCheckpoints(true)
|
chain.DisableCheckpoints(true)
|
||||||
blockchain.TstSetCoinbaseMaturity(1)
|
chain.TstSetCoinbaseMaturity(1)
|
||||||
|
|
||||||
for i := 1; i < len(blocks); i++ {
|
for i := 1; i < len(blocks); i++ {
|
||||||
isOrphan, err := chain.ProcessBlock(blocks[i], blockchain.BFNone)
|
isOrphan, err := chain.ProcessBlock(blocks[i], blockchain.BFNone)
|
||||||
|
|
|
@ -107,10 +107,14 @@ func chainSetup(dbName string) (*blockchain.BlockChain, func(), error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the chain params to ensure any modifications the tests do to
|
||||||
|
// the chain parameters do not affect the global instance.
|
||||||
|
mainNetParams := chaincfg.MainNetParams
|
||||||
|
|
||||||
// Create the main chain instance.
|
// Create the main chain instance.
|
||||||
chain, err := blockchain.New(&blockchain.Config{
|
chain, err := blockchain.New(&blockchain.Config{
|
||||||
DB: db,
|
DB: db,
|
||||||
ChainParams: &chaincfg.MainNetParams,
|
ChainParams: &mainNetParams,
|
||||||
TimeSource: blockchain.NewMedianTime(),
|
TimeSource: blockchain.NewMedianTime(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,37 +11,6 @@ import (
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// targetTimespan is the desired amount of time that should elapse
|
|
||||||
// before block difficulty requirement is examined to determine how
|
|
||||||
// it should be changed in order to maintain the desired block
|
|
||||||
// generation rate.
|
|
||||||
targetTimespan = time.Hour * 24 * 14
|
|
||||||
|
|
||||||
// targetSpacing is the desired amount of time to generate each block.
|
|
||||||
targetSpacing = time.Minute * 10
|
|
||||||
|
|
||||||
// BlocksPerRetarget is the number of blocks between each difficulty
|
|
||||||
// retarget. It is calculated based on the desired block generation
|
|
||||||
// rate.
|
|
||||||
BlocksPerRetarget = int32(targetTimespan / targetSpacing)
|
|
||||||
|
|
||||||
// retargetAdjustmentFactor is the adjustment factor used to limit
|
|
||||||
// the minimum and maximum amount of adjustment that can occur between
|
|
||||||
// difficulty retargets.
|
|
||||||
retargetAdjustmentFactor = 4
|
|
||||||
|
|
||||||
// minRetargetTimespan is the minimum amount of adjustment that can
|
|
||||||
// occur between difficulty retargets. It equates to 25% of the
|
|
||||||
// previous difficulty.
|
|
||||||
minRetargetTimespan = int64(targetTimespan / retargetAdjustmentFactor)
|
|
||||||
|
|
||||||
// maxRetargetTimespan is the maximum amount of adjustment that can
|
|
||||||
// occur between difficulty retargets. It equates to 400% of the
|
|
||||||
// previous difficulty.
|
|
||||||
maxRetargetTimespan = int64(targetTimespan * retargetAdjustmentFactor)
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// bigOne is 1 represented as a big.Int. It is defined here to avoid
|
// bigOne is 1 represented as a big.Int. It is defined here to avoid
|
||||||
// the overhead of creating it multiple times.
|
// the overhead of creating it multiple times.
|
||||||
|
@ -190,13 +159,13 @@ func CalcWork(bits uint32) *big.Int {
|
||||||
func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
||||||
// Convert types used in the calculations below.
|
// Convert types used in the calculations below.
|
||||||
durationVal := int64(duration)
|
durationVal := int64(duration)
|
||||||
adjustmentFactor := big.NewInt(retargetAdjustmentFactor)
|
adjustmentFactor := big.NewInt(b.chainParams.RetargetAdjustmentFactor)
|
||||||
|
|
||||||
// The test network rules allow minimum difficulty blocks after more
|
// The test network rules allow minimum difficulty blocks after more
|
||||||
// than twice the desired amount of time needed to generate a block has
|
// than twice the desired amount of time needed to generate a block has
|
||||||
// elapsed.
|
// elapsed.
|
||||||
if b.chainParams.ResetMinDifficulty {
|
if b.chainParams.ReduceMinDifficulty {
|
||||||
if durationVal > int64(targetSpacing)*2 {
|
if durationVal > int64(b.chainParams.MinDiffReductionTime) {
|
||||||
return b.chainParams.PowLimitBits
|
return b.chainParams.PowLimitBits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +177,7 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration)
|
||||||
newTarget := CompactToBig(bits)
|
newTarget := CompactToBig(bits)
|
||||||
for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 {
|
for durationVal > 0 && newTarget.Cmp(b.chainParams.PowLimit) < 0 {
|
||||||
newTarget.Mul(newTarget, adjustmentFactor)
|
newTarget.Mul(newTarget, adjustmentFactor)
|
||||||
durationVal -= maxRetargetTimespan
|
durationVal -= b.maxRetargetTimespan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit new value to the proof of work limit.
|
// Limit new value to the proof of work limit.
|
||||||
|
@ -227,7 +196,7 @@ func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, er
|
||||||
// Search backwards through the chain for the last block without
|
// Search backwards through the chain for the last block without
|
||||||
// the special rule applied.
|
// the special rule applied.
|
||||||
iterNode := startNode
|
iterNode := startNode
|
||||||
for iterNode != nil && iterNode.height%BlocksPerRetarget != 0 &&
|
for iterNode != nil && iterNode.height%b.blocksPerRetarget != 0 &&
|
||||||
iterNode.bits == b.chainParams.PowLimitBits {
|
iterNode.bits == b.chainParams.PowLimitBits {
|
||||||
|
|
||||||
// Get the previous block node. This function is used over
|
// Get the previous block node. This function is used over
|
||||||
|
@ -267,15 +236,15 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
|
|
||||||
// Return the previous block's difficulty requirements if this block
|
// Return the previous block's difficulty requirements if this block
|
||||||
// is not at a difficulty retarget interval.
|
// is not at a difficulty retarget interval.
|
||||||
if (lastNode.height+1)%BlocksPerRetarget != 0 {
|
if (lastNode.height+1)%b.blocksPerRetarget != 0 {
|
||||||
// The test network rules allow minimum difficulty blocks after
|
// For networks that support it, allow special reduction of the
|
||||||
// more than twice the desired amount of time needed to generate
|
// required difficulty once too much time has elapsed without
|
||||||
// a block has elapsed.
|
// mining a block.
|
||||||
if b.chainParams.ResetMinDifficulty {
|
if b.chainParams.ReduceMinDifficulty {
|
||||||
// Return minimum difficulty when more than twice the
|
// Return minimum difficulty when more than the desired
|
||||||
// desired amount of time needed to generate a block has
|
// amount of time has elapsed without mining a block.
|
||||||
// elapsed.
|
reductionTime := b.chainParams.MinDiffReductionTime
|
||||||
allowMinTime := lastNode.timestamp.Add(targetSpacing * 2)
|
allowMinTime := lastNode.timestamp.Add(reductionTime)
|
||||||
if newBlockTime.After(allowMinTime) {
|
if newBlockTime.After(allowMinTime) {
|
||||||
return b.chainParams.PowLimitBits, nil
|
return b.chainParams.PowLimitBits, nil
|
||||||
}
|
}
|
||||||
|
@ -298,7 +267,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
// Get the block node at the previous retarget (targetTimespan days
|
// Get the block node at the previous retarget (targetTimespan days
|
||||||
// worth of blocks).
|
// worth of blocks).
|
||||||
firstNode := lastNode
|
firstNode := lastNode
|
||||||
for i := int32(0); i < BlocksPerRetarget-1 && firstNode != nil; i++ {
|
for i := int32(0); i < b.blocksPerRetarget-1 && firstNode != nil; i++ {
|
||||||
// Get the previous block node. This function is used over
|
// Get the previous block node. This function is used over
|
||||||
// simply accessing firstNode.parent directly as it will
|
// simply accessing firstNode.parent directly as it will
|
||||||
// dynamically create previous block nodes as needed. This
|
// dynamically create previous block nodes as needed. This
|
||||||
|
@ -319,10 +288,10 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
// difficulty.
|
// difficulty.
|
||||||
actualTimespan := lastNode.timestamp.UnixNano() - firstNode.timestamp.UnixNano()
|
actualTimespan := lastNode.timestamp.UnixNano() - firstNode.timestamp.UnixNano()
|
||||||
adjustedTimespan := actualTimespan
|
adjustedTimespan := actualTimespan
|
||||||
if actualTimespan < minRetargetTimespan {
|
if actualTimespan < b.minRetargetTimespan {
|
||||||
adjustedTimespan = minRetargetTimespan
|
adjustedTimespan = b.minRetargetTimespan
|
||||||
} else if actualTimespan > maxRetargetTimespan {
|
} else if actualTimespan > b.maxRetargetTimespan {
|
||||||
adjustedTimespan = maxRetargetTimespan
|
adjustedTimespan = b.maxRetargetTimespan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate new target difficulty as:
|
// Calculate new target difficulty as:
|
||||||
|
@ -332,7 +301,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
// result.
|
// result.
|
||||||
oldTarget := CompactToBig(lastNode.bits)
|
oldTarget := CompactToBig(lastNode.bits)
|
||||||
newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan))
|
newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan))
|
||||||
newTarget.Div(newTarget, big.NewInt(int64(targetTimespan)))
|
newTarget.Div(newTarget, big.NewInt(int64(b.chainParams.TargetTimespan)))
|
||||||
|
|
||||||
// Limit new value to the proof of work limit.
|
// Limit new value to the proof of work limit.
|
||||||
if newTarget.Cmp(b.chainParams.PowLimit) > 0 {
|
if newTarget.Cmp(b.chainParams.PowLimit) > 0 {
|
||||||
|
@ -349,7 +318,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim
|
||||||
log.Debugf("New target %08x (%064x)", newTargetBits, CompactToBig(newTargetBits))
|
log.Debugf("New target %08x (%064x)", newTargetBits, CompactToBig(newTargetBits))
|
||||||
log.Debugf("Actual timespan %v, adjusted timespan %v, target timespan %v",
|
log.Debugf("Actual timespan %v, adjusted timespan %v, target timespan %v",
|
||||||
time.Duration(actualTimespan), time.Duration(adjustedTimespan),
|
time.Duration(actualTimespan), time.Duration(adjustedTimespan),
|
||||||
targetTimespan)
|
b.chainParams.TargetTimespan)
|
||||||
|
|
||||||
return newTargetBits, nil
|
return newTargetBits, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import (
|
||||||
|
|
||||||
// TstSetCoinbaseMaturity makes the ability to set the coinbase maturity
|
// TstSetCoinbaseMaturity makes the ability to set the coinbase maturity
|
||||||
// available to the test package.
|
// available to the test package.
|
||||||
func TstSetCoinbaseMaturity(maturity int32) {
|
func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) {
|
||||||
coinbaseMaturity = maturity
|
b.chainParams.CoinbaseMaturity = maturity
|
||||||
}
|
}
|
||||||
|
|
||||||
// TstTimeSorter makes the internal timeSorter type available to the test
|
// TstTimeSorter makes the internal timeSorter type available to the test
|
||||||
|
|
|
@ -56,7 +56,7 @@ func TestReorganization(t *testing.T) {
|
||||||
// Since we're not dealing with the real block chain, disable
|
// Since we're not dealing with the real block chain, disable
|
||||||
// checkpoints and set the coinbase maturity to 1.
|
// checkpoints and set the coinbase maturity to 1.
|
||||||
chain.DisableCheckpoints(true)
|
chain.DisableCheckpoints(true)
|
||||||
blockchain.TstSetCoinbaseMaturity(1)
|
chain.TstSetCoinbaseMaturity(1)
|
||||||
|
|
||||||
expectedOrphans := map[int]struct{}{5: {}, 6: {}}
|
expectedOrphans := map[int]struct{}{5: {}, 6: {}}
|
||||||
for i := 1; i < len(blocks); i++ {
|
for i := 1; i < len(blocks); i++ {
|
||||||
|
|
|
@ -45,18 +45,9 @@ const (
|
||||||
// baseSubsidy is the starting subsidy amount for mined blocks. This
|
// baseSubsidy is the starting subsidy amount for mined blocks. This
|
||||||
// value is halved every SubsidyHalvingInterval blocks.
|
// value is halved every SubsidyHalvingInterval blocks.
|
||||||
baseSubsidy = 50 * btcutil.SatoshiPerBitcoin
|
baseSubsidy = 50 * btcutil.SatoshiPerBitcoin
|
||||||
|
|
||||||
// CoinbaseMaturity is the number of blocks required before newly
|
|
||||||
// mined bitcoins (coinbase transactions) can be spent.
|
|
||||||
CoinbaseMaturity = 100
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// coinbaseMaturity is the internal variable used for validating the
|
|
||||||
// spending of coinbase outputs. A variable rather than the exported
|
|
||||||
// constant is used because the tests need the ability to modify it.
|
|
||||||
coinbaseMaturity = int32(CoinbaseMaturity)
|
|
||||||
|
|
||||||
// zeroHash is the zero value for a chainhash.Hash and is defined as
|
// zeroHash is the zero value for a chainhash.Hash and is defined as
|
||||||
// a package level variable to avoid the need to create a new instance
|
// a package level variable to avoid the need to create a new instance
|
||||||
// every time a check is needed.
|
// every time a check is needed.
|
||||||
|
@ -182,18 +173,18 @@ func isBIP0030Node(node *blockNode) bool {
|
||||||
// newly generated blocks awards as well as validating the coinbase for blocks
|
// newly generated blocks awards as well as validating the coinbase for blocks
|
||||||
// has the expected value.
|
// has the expected value.
|
||||||
//
|
//
|
||||||
// The subsidy is halved every SubsidyHalvingInterval blocks. Mathematically
|
// The subsidy is halved every SubsidyReductionInterval blocks. Mathematically
|
||||||
// this is: baseSubsidy / 2^(height/subsidyHalvingInterval)
|
// this is: baseSubsidy / 2^(height/SubsidyReductionInterval)
|
||||||
//
|
//
|
||||||
// At the target block generation rate for the main network, this is
|
// At the target block generation rate for the main network, this is
|
||||||
// approximately every 4 years.
|
// approximately every 4 years.
|
||||||
func CalcBlockSubsidy(height int32, chainParams *chaincfg.Params) int64 {
|
func CalcBlockSubsidy(height int32, chainParams *chaincfg.Params) int64 {
|
||||||
if chainParams.SubsidyHalvingInterval == 0 {
|
if chainParams.SubsidyReductionInterval == 0 {
|
||||||
return baseSubsidy
|
return baseSubsidy
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equivalent to: baseSubsidy / 2^(height/subsidyHalvingInterval)
|
// Equivalent to: baseSubsidy / 2^(height/subsidyHalvingInterval)
|
||||||
return baseSubsidy >> uint(height/chainParams.SubsidyHalvingInterval)
|
return baseSubsidy >> uint(height/chainParams.SubsidyReductionInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckTransactionSanity performs some preliminary checks on a transaction to
|
// CheckTransactionSanity performs some preliminary checks on a transaction to
|
||||||
|
@ -833,7 +824,7 @@ func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *U
|
||||||
//
|
//
|
||||||
// NOTE: The transaction MUST have already been sanity checked with the
|
// NOTE: The transaction MUST have already been sanity checked with the
|
||||||
// CheckTransactionSanity function prior to calling this function.
|
// CheckTransactionSanity function prior to calling this function.
|
||||||
func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpoint) (int64, error) {
|
func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpoint, chainParams *chaincfg.Params) (int64, error) {
|
||||||
// Coinbase transactions have no inputs.
|
// Coinbase transactions have no inputs.
|
||||||
if IsCoinBase(tx) {
|
if IsCoinBase(tx) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
@ -857,6 +848,7 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo
|
||||||
if utxoEntry.IsCoinBase() {
|
if utxoEntry.IsCoinBase() {
|
||||||
originHeight := int32(utxoEntry.BlockHeight())
|
originHeight := int32(utxoEntry.BlockHeight())
|
||||||
blocksSincePrev := txHeight - originHeight
|
blocksSincePrev := txHeight - originHeight
|
||||||
|
coinbaseMaturity := int32(chainParams.CoinbaseMaturity)
|
||||||
if blocksSincePrev < coinbaseMaturity {
|
if blocksSincePrev < coinbaseMaturity {
|
||||||
str := fmt.Sprintf("tried to spend coinbase "+
|
str := fmt.Sprintf("tried to spend coinbase "+
|
||||||
"transaction %v from height %v at "+
|
"transaction %v from height %v at "+
|
||||||
|
@ -1050,7 +1042,8 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi
|
||||||
// bounds.
|
// bounds.
|
||||||
var totalFees int64
|
var totalFees int64
|
||||||
for _, tx := range transactions {
|
for _, tx := range transactions {
|
||||||
txFee, err := CheckTransactionInputs(tx, node.height, view)
|
txFee, err := CheckTransactionInputs(tx, node.height, view,
|
||||||
|
b.chainParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package chaincfg
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
@ -53,18 +54,69 @@ type Checkpoint struct {
|
||||||
// used by Bitcoin applications to differentiate networks as well as addresses
|
// used by Bitcoin applications to differentiate networks as well as addresses
|
||||||
// and keys for one network from those intended for use on another network.
|
// and keys for one network from those intended for use on another network.
|
||||||
type Params struct {
|
type Params struct {
|
||||||
|
// Name defines a human-readable identifier for the network.
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
|
// Net defines the magic bytes used to identify the network.
|
||||||
Net wire.BitcoinNet
|
Net wire.BitcoinNet
|
||||||
|
|
||||||
|
// DefaultPort defines the default peer-to-peer port for the network.
|
||||||
DefaultPort string
|
DefaultPort string
|
||||||
|
|
||||||
|
// DNSSeeds defines a list of DNS seeds for the network that are used
|
||||||
|
// as one method to discover peers.
|
||||||
DNSSeeds []string
|
DNSSeeds []string
|
||||||
|
|
||||||
// Chain parameters
|
// GenesisBlock defines the first block of the chain.
|
||||||
GenesisBlock *wire.MsgBlock
|
GenesisBlock *wire.MsgBlock
|
||||||
|
|
||||||
|
// GenesisHash is the starting block hash.
|
||||||
GenesisHash *chainhash.Hash
|
GenesisHash *chainhash.Hash
|
||||||
|
|
||||||
|
// PowLimit defines the highest allowed proof of work value for a block
|
||||||
|
// as a uint256.
|
||||||
PowLimit *big.Int
|
PowLimit *big.Int
|
||||||
|
|
||||||
|
// PowLimitBits defines the highest allowed proof of work value for a
|
||||||
|
// block in compact form.
|
||||||
PowLimitBits uint32
|
PowLimitBits uint32
|
||||||
SubsidyHalvingInterval int32
|
|
||||||
ResetMinDifficulty bool
|
// CoinbaseMaturity is the number of blocks required before newly mined
|
||||||
|
// coins (coinbase transactions) can be spent.
|
||||||
|
CoinbaseMaturity uint16
|
||||||
|
|
||||||
|
// SubsidyReductionInterval is the interval of blocks before the subsidy
|
||||||
|
// is reduced.
|
||||||
|
SubsidyReductionInterval int32
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
TargetTimespan time.Duration
|
||||||
|
|
||||||
|
// TargetTimePerBlock is the desired amount of time to generate each
|
||||||
|
// block.
|
||||||
|
TargetTimePerBlock time.Duration
|
||||||
|
|
||||||
|
// RetargetAdjustmentFactor is the adjustment factor used to limit
|
||||||
|
// the minimum and maximum amount of adjustment that can occur between
|
||||||
|
// difficulty retargets.
|
||||||
|
RetargetAdjustmentFactor int64
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// 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
|
GenerateSupported bool
|
||||||
|
|
||||||
// Checkpoints ordered from oldest to newest.
|
// Checkpoints ordered from oldest to newest.
|
||||||
|
@ -118,8 +170,13 @@ var MainNetParams = Params{
|
||||||
GenesisHash: &genesisHash,
|
GenesisHash: &genesisHash,
|
||||||
PowLimit: mainPowLimit,
|
PowLimit: mainPowLimit,
|
||||||
PowLimitBits: 0x1d00ffff,
|
PowLimitBits: 0x1d00ffff,
|
||||||
SubsidyHalvingInterval: 210000,
|
CoinbaseMaturity: 100,
|
||||||
ResetMinDifficulty: false,
|
SubsidyReductionInterval: 210000,
|
||||||
|
TargetTimespan: time.Hour * 24 * 14, // 14 days
|
||||||
|
TargetTimePerBlock: time.Minute * 10, // 10 minutes
|
||||||
|
RetargetAdjustmentFactor: 4, // 25% less, 400% more
|
||||||
|
ReduceMinDifficulty: false,
|
||||||
|
MinDiffReductionTime: 0,
|
||||||
GenerateSupported: false,
|
GenerateSupported: false,
|
||||||
|
|
||||||
// Checkpoints ordered from oldest to newest.
|
// Checkpoints ordered from oldest to newest.
|
||||||
|
@ -185,8 +242,13 @@ var RegressionNetParams = Params{
|
||||||
GenesisHash: ®TestGenesisHash,
|
GenesisHash: ®TestGenesisHash,
|
||||||
PowLimit: regressionPowLimit,
|
PowLimit: regressionPowLimit,
|
||||||
PowLimitBits: 0x207fffff,
|
PowLimitBits: 0x207fffff,
|
||||||
SubsidyHalvingInterval: 150,
|
CoinbaseMaturity: 100,
|
||||||
ResetMinDifficulty: true,
|
SubsidyReductionInterval: 150,
|
||||||
|
TargetTimespan: time.Hour * 24 * 14, // 14 days
|
||||||
|
TargetTimePerBlock: time.Minute * 10, // 10 minutes
|
||||||
|
RetargetAdjustmentFactor: 4, // 25% less, 400% more
|
||||||
|
ReduceMinDifficulty: true,
|
||||||
|
MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2
|
||||||
GenerateSupported: true,
|
GenerateSupported: true,
|
||||||
|
|
||||||
// Checkpoints ordered from oldest to newest.
|
// Checkpoints ordered from oldest to newest.
|
||||||
|
@ -237,8 +299,13 @@ var TestNet3Params = Params{
|
||||||
GenesisHash: &testNet3GenesisHash,
|
GenesisHash: &testNet3GenesisHash,
|
||||||
PowLimit: testNet3PowLimit,
|
PowLimit: testNet3PowLimit,
|
||||||
PowLimitBits: 0x1d00ffff,
|
PowLimitBits: 0x1d00ffff,
|
||||||
SubsidyHalvingInterval: 210000,
|
CoinbaseMaturity: 100,
|
||||||
ResetMinDifficulty: true,
|
SubsidyReductionInterval: 210000,
|
||||||
|
TargetTimespan: time.Hour * 24 * 14, // 14 days
|
||||||
|
TargetTimePerBlock: time.Minute * 10, // 10 minutes
|
||||||
|
RetargetAdjustmentFactor: 4, // 25% less, 400% more
|
||||||
|
ReduceMinDifficulty: true,
|
||||||
|
MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2
|
||||||
GenerateSupported: false,
|
GenerateSupported: false,
|
||||||
|
|
||||||
// Checkpoints ordered from oldest to newest.
|
// Checkpoints ordered from oldest to newest.
|
||||||
|
@ -291,8 +358,13 @@ var SimNetParams = Params{
|
||||||
GenesisHash: &simNetGenesisHash,
|
GenesisHash: &simNetGenesisHash,
|
||||||
PowLimit: simNetPowLimit,
|
PowLimit: simNetPowLimit,
|
||||||
PowLimitBits: 0x207fffff,
|
PowLimitBits: 0x207fffff,
|
||||||
SubsidyHalvingInterval: 210000,
|
CoinbaseMaturity: 100,
|
||||||
ResetMinDifficulty: true,
|
SubsidyReductionInterval: 210000,
|
||||||
|
TargetTimespan: time.Hour * 24 * 14, // 14 days
|
||||||
|
TargetTimePerBlock: time.Minute * 10, // 10 minutes
|
||||||
|
RetargetAdjustmentFactor: 4, // 25% less, 400% more
|
||||||
|
ReduceMinDifficulty: true,
|
||||||
|
MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2
|
||||||
GenerateSupported: true,
|
GenerateSupported: true,
|
||||||
|
|
||||||
// Checkpoints ordered from oldest to newest.
|
// Checkpoints ordered from oldest to newest.
|
||||||
|
|
|
@ -596,7 +596,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
|
||||||
// Also returns the fees associated with the transaction which will be
|
// Also returns the fees associated with the transaction which will be
|
||||||
// used later.
|
// used later.
|
||||||
txFee, err := blockchain.CheckTransactionInputs(tx, nextBlockHeight,
|
txFee, err := blockchain.CheckTransactionInputs(tx, nextBlockHeight,
|
||||||
utxoView)
|
utxoView, activeNetParams.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cerr, ok := err.(blockchain.RuleError); ok {
|
if cerr, ok := err.(blockchain.RuleError); ok {
|
||||||
return nil, chainRuleError(cerr)
|
return nil, chainRuleError(cerr)
|
||||||
|
|
|
@ -651,7 +651,7 @@ mempoolLoop:
|
||||||
// Ensure the transaction inputs pass all of the necessary
|
// Ensure the transaction inputs pass all of the necessary
|
||||||
// preconditions before allowing it to be added to the block.
|
// preconditions before allowing it to be added to the block.
|
||||||
_, err = blockchain.CheckTransactionInputs(tx, nextBlockHeight,
|
_, err = blockchain.CheckTransactionInputs(tx, nextBlockHeight,
|
||||||
blockUtxos)
|
blockUtxos, activeNetParams.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
minrLog.Tracef("Skipping tx %s due to error in "+
|
minrLog.Tracef("Skipping tx %s due to error in "+
|
||||||
"CheckTransactionInputs: %v", tx.Hash(), err)
|
"CheckTransactionInputs: %v", tx.Hash(), err)
|
||||||
|
@ -781,7 +781,7 @@ func UpdateBlockTime(msgBlock *wire.MsgBlock, bManager *blockManager) error {
|
||||||
|
|
||||||
// If running on a network that requires recalculating the difficulty,
|
// If running on a network that requires recalculating the difficulty,
|
||||||
// do so now.
|
// do so now.
|
||||||
if activeNetParams.ResetMinDifficulty {
|
if activeNetParams.ReduceMinDifficulty {
|
||||||
difficulty, err := bManager.chain.CalcNextRequiredDifficulty(
|
difficulty, err := bManager.chain.CalcNextRequiredDifficulty(
|
||||||
newTimestamp)
|
newTimestamp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2104,6 +2104,11 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru
|
||||||
endHeight = best.Height
|
endHeight = best.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the number of blocks per retarget interval based on the
|
||||||
|
// chain parameters.
|
||||||
|
blocksPerRetarget := int32(s.server.chainParams.TargetTimespan /
|
||||||
|
s.server.chainParams.TargetTimePerBlock)
|
||||||
|
|
||||||
// Calculate the starting block height based on the passed number of
|
// Calculate the starting block height based on the passed number of
|
||||||
// blocks. When the passed value is negative, use the last block the
|
// blocks. When the passed value is negative, use the last block the
|
||||||
// difficulty changed as the starting height. Also make sure the
|
// difficulty changed as the starting height. Also make sure the
|
||||||
|
@ -2114,7 +2119,7 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru
|
||||||
}
|
}
|
||||||
var startHeight int32
|
var startHeight int32
|
||||||
if numBlocks <= 0 {
|
if numBlocks <= 0 {
|
||||||
startHeight = endHeight - ((endHeight % blockchain.BlocksPerRetarget) + 1)
|
startHeight = endHeight - ((endHeight % blocksPerRetarget) + 1)
|
||||||
} else {
|
} else {
|
||||||
startHeight = endHeight - numBlocks
|
startHeight = endHeight - numBlocks
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue