Implement testnet specific rules.
This commit adds support for testnet specific rules when a new BlockChain is created against testnet.
This commit is contained in:
parent
1deeb05627
commit
9787f46f6a
3 changed files with 88 additions and 16 deletions
|
@ -114,7 +114,6 @@ intentionally causes an error by attempting to process a duplicate block.
|
|||
## TODO
|
||||
|
||||
- Increase test coverage
|
||||
- Add testnet specific rules
|
||||
- Profile and optimize
|
||||
- Expose some APIs for block verification (without actually inserting it) and
|
||||
transaction input lookups
|
||||
|
|
|
@ -190,7 +190,17 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration)
|
|||
// Choose the correct proof of work limit for the active network.
|
||||
powLimit := b.netParams().powLimit
|
||||
|
||||
// TODO(davec): Testnet has special rules.
|
||||
// The test network rules allow minimum difficulty blocks after more
|
||||
// than twice the desired amount of time needed to generate a block has
|
||||
// elapsed.
|
||||
switch b.btcnet {
|
||||
case btcwire.TestNet:
|
||||
fallthrough
|
||||
case btcwire.TestNet3:
|
||||
if durationVal > int64(targetSpacing)*2 {
|
||||
return BigToCompact(powLimit)
|
||||
}
|
||||
}
|
||||
|
||||
// Since easier difficulty equates to higher numbers, the easiest
|
||||
// difficulty for a given duration is the largest value possible given
|
||||
|
@ -210,6 +220,36 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration)
|
|||
return BigToCompact(newTarget)
|
||||
}
|
||||
|
||||
// findPrevTestNetDifficulty returns the difficulty of the previous block which
|
||||
// did not have the special testnet minimum difficulty rule applied.
|
||||
func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) (uint32, error) {
|
||||
// Search backwards through the chain for the last block without
|
||||
// the special rule applied.
|
||||
powLimitBits := BigToCompact(b.netParams().powLimit)
|
||||
iterNode := startNode
|
||||
for iterNode != nil && iterNode.height%blocksPerRetarget != 0 && iterNode.bits == powLimitBits {
|
||||
// Get the previous block node. This function is used over
|
||||
// simply accessing iterNode.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
|
||||
iterNode, err = b.getPrevNodeFromNode(iterNode)
|
||||
if err != nil {
|
||||
log.Errorf("getPrevNodeFromNode: %v", err)
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// Return the found difficulty or the minimum difficulty if no
|
||||
// appropriate block was found.
|
||||
lastBits := powLimitBits
|
||||
if iterNode != nil {
|
||||
lastBits = iterNode.bits
|
||||
}
|
||||
return lastBits, nil
|
||||
}
|
||||
|
||||
// calcNextRequiredDifficulty calculates the required difficulty for the block
|
||||
// after the passed previous block node based on the difficulty retarget rules.
|
||||
func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, block *btcutil.Block) (uint32, error) {
|
||||
|
@ -224,8 +264,40 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, block *btcu
|
|||
// Return the previous block's difficulty requirements if this block
|
||||
// is not at a difficulty retarget interval.
|
||||
if (lastNode.height+1)%blocksPerRetarget != 0 {
|
||||
// TODO(davec): Testnet has special rules.
|
||||
return lastNode.bits, nil
|
||||
// The difficulty rules differ between networks.
|
||||
switch b.btcnet {
|
||||
// The test network rules allow minimum difficulty blocks after
|
||||
// more than twice the desired amount of time needed to generate
|
||||
// a block has elapsed.
|
||||
case btcwire.TestNet:
|
||||
fallthrough
|
||||
case btcwire.TestNet3:
|
||||
// Return minimum difficulty when more than twice the
|
||||
// desired amount of time needed to generate a block has
|
||||
// elapsed.
|
||||
newBlockTime := block.MsgBlock().Header.Timestamp
|
||||
allowMinTime := lastNode.timestamp.Add(targetSpacing * 2)
|
||||
if newBlockTime.After(allowMinTime) {
|
||||
return BigToCompact(powLimit), nil
|
||||
}
|
||||
|
||||
// The block was mined within the desired timeframe, so
|
||||
// return the difficulty for the last block which did
|
||||
// not have the special minimum difficulty rule applied.
|
||||
prevBits, err := b.findPrevTestNetDifficulty(lastNode)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return prevBits, nil
|
||||
|
||||
// For the main network (or any unrecognized networks), simply
|
||||
// return the previous block's difficulty.
|
||||
case btcwire.MainNet:
|
||||
fallthrough
|
||||
default:
|
||||
// Return the previous block's difficulty requirements.
|
||||
return lastNode.bits, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get the block node at the previous retarget (targetTimespan days
|
||||
|
|
|
@ -2,33 +2,33 @@
|
|||
github.com/conformal/btcchain/chain.go BlockChain.removeOrphanBlock 100.00% (12/12)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.getOrphanRoot 100.00% (7/7)
|
||||
github.com/conformal/btcchain/checkpoints.go init 100.00% (6/6)
|
||||
github.com/conformal/btcchain/difficulty.go ShaHashToBig 100.00% (5/5)
|
||||
github.com/conformal/btcchain/merkle.go hashMerkleBranches 100.00% (5/5)
|
||||
github.com/conformal/btcchain/merkle.go nextPowerOfTwo 100.00% (4/4)
|
||||
github.com/conformal/btcchain/difficulty.go ShaHashToBig 100.00% (5/5)
|
||||
github.com/conformal/btcchain/chain.go newBlockNode 100.00% (4/4)
|
||||
github.com/conformal/btcchain/merkle.go nextPowerOfTwo 100.00% (4/4)
|
||||
github.com/conformal/btcchain/difficulty.go calcWork 100.00% (3/3)
|
||||
github.com/conformal/btcchain/process.go BlockChain.blockExists 100.00% (3/3)
|
||||
github.com/conformal/btcchain/chain.go New 100.00% (2/2)
|
||||
github.com/conformal/btcchain/checkpoints.go newShaHashFromStr 100.00% (2/2)
|
||||
github.com/conformal/btcchain/timesorter.go timeSorter.Less 100.00% (1/1)
|
||||
github.com/conformal/btcchain/validate.go calcBlockSubsidy 100.00% (1/1)
|
||||
github.com/conformal/btcchain/timesorter.go timeSorter.Swap 100.00% (1/1)
|
||||
github.com/conformal/btcchain/checkpoints.go BlockChain.DisableCheckpoints 100.00% (1/1)
|
||||
github.com/conformal/btcchain/timesorter.go timeSorter.Less 100.00% (1/1)
|
||||
github.com/conformal/btcchain/timesorter.go timeSorter.Len 100.00% (1/1)
|
||||
github.com/conformal/btcchain/log.go init 100.00% (1/1)
|
||||
github.com/conformal/btcchain/log.go DisableLog 100.00% (1/1)
|
||||
github.com/conformal/btcchain/log.go init 100.00% (1/1)
|
||||
github.com/conformal/btcchain/merkle.go BuildMerkleTreeStore 94.12% (16/17)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.getReorganizeNodes 92.86% (13/14)
|
||||
github.com/conformal/btcchain/process.go BlockChain.processOrphans 91.67% (11/12)
|
||||
github.com/conformal/btcchain/txlookup.go disconnectTransactions 90.91% (10/11)
|
||||
github.com/conformal/btcchain/txlookup.go BlockChain.fetchTxList 88.57% (31/35)
|
||||
github.com/conformal/btcchain/scriptval.go validateAllTxIn 87.88% (29/33)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.calcPastMedianTime 87.50% (14/16)
|
||||
github.com/conformal/btcchain/scriptval.go checkBlockScripts 87.50% (7/8)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.connectBestChain 86.96% (20/23)
|
||||
github.com/conformal/btcchain/validate.go countSigOps 86.67% (13/15)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.connectBlock 83.33% (10/12)
|
||||
github.com/conformal/btcchain/validate.go isCoinBase 83.33% (5/6)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.calcPastMedianTime 82.35% (14/17)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.reorganizeChain 80.77% (21/26)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.isMajorityVersion 80.00% (8/10)
|
||||
github.com/conformal/btcchain/txlookup.go BlockChain.fetchInputTransactions 78.26% (18/23)
|
||||
|
@ -51,17 +51,18 @@ github.com/conformal/btcchain/validate.go BlockChain.checkBIP0030 57.14% (8/1
|
|||
github.com/conformal/btcchain/chain.go BlockChain.loadBlockNode 50.00% (11/22)
|
||||
github.com/conformal/btcchain/checkpoints.go BlockChain.LatestCheckpoint 50.00% (2/4)
|
||||
github.com/conformal/btcchain/notifications.go BlockChain.sendNotification 50.00% (2/4)
|
||||
github.com/conformal/btcchain/accept.go BlockChain.maybeAcceptBlock 49.23% (32/65)
|
||||
github.com/conformal/btcchain/accept.go BlockChain.maybeAcceptBlock 46.38% (32/69)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.getPrevNodeFromNode 33.33% (4/12)
|
||||
github.com/conformal/btcchain/checkpoints.go BlockChain.verifyCheckpoint 33.33% (2/6)
|
||||
github.com/conformal/btcchain/validate.go isFinalizedTransaction 23.08% (3/13)
|
||||
github.com/conformal/btcchain/checkpoints.go BlockChain.findLatestKnownCheckpoint 18.18% (2/11)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 13.79% (4/29)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 15.00% (6/40)
|
||||
github.com/conformal/btcchain/checkpoints.go BlockChain.IsCheckpointCandidate 0.00% (0/32)
|
||||
github.com/conformal/btcchain/validate.go countP2SHSigOps 0.00% (0/26)
|
||||
github.com/conformal/btcchain/difficulty.go BigToCompact 0.00% (0/16)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcEasiestDifficulty 0.00% (0/14)
|
||||
github.com/conformal/btcchain/validate.go checkSerializedHeight 0.00% (0/12)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcEasiestDifficulty 0.00% (0/10)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.findPrevTestNetDifficulty 0.00% (0/12)
|
||||
github.com/conformal/btcchain/chain.go removeChildNode 0.00% (0/8)
|
||||
github.com/conformal/btcchain/log.go SetLogWriter 0.00% (0/7)
|
||||
github.com/conformal/btcchain/checkpoints.go isNonstandardTransaction 0.00% (0/5)
|
||||
|
@ -69,10 +70,10 @@ github.com/conformal/btcchain/checkpoints.go BlockChain.checkpointData 0.00%
|
|||
github.com/conformal/btcchain/validate.go isTransactionSpent 0.00% (0/4)
|
||||
github.com/conformal/btcchain/notifications.go NotificationType.String 0.00% (0/3)
|
||||
github.com/conformal/btcchain/chain.go addChildrenWork 0.00% (0/3)
|
||||
github.com/conformal/btcchain/log.go UseLogger 0.00% (0/1)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.DisableVerify 0.00% (0/1)
|
||||
github.com/conformal/btcchain/process.go RuleError.Error 0.00% (0/1)
|
||||
github.com/conformal/btcchain/log.go newLogClosure 0.00% (0/1)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.DisableVerify 0.00% (0/1)
|
||||
github.com/conformal/btcchain/log.go UseLogger 0.00% (0/1)
|
||||
github.com/conformal/btcchain/log.go logClosure.String 0.00% (0/1)
|
||||
github.com/conformal/btcchain ------------------------------------- 59.26% (576/972)
|
||||
github.com/conformal/btcchain/log.go newLogClosure 0.00% (0/1)
|
||||
github.com/conformal/btcchain ------------------------------------- 57.57% (578/1004)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue