Add support for params based on active network.
This commit modifies the code to use params based on the active network which paves the way for supporting the special rules and different genesis blocks used by the test networks.
This commit is contained in:
parent
3c4292fae3
commit
f219ed5baf
9 changed files with 117 additions and 28 deletions
|
@ -32,7 +32,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block) error {
|
|||
// calculated difficulty based on the previous block and difficulty
|
||||
// retarget rules.
|
||||
blockHeader := block.MsgBlock().Header
|
||||
expectedDifficulty, err := b.calcNextRequiredDifficulty(prevNode)
|
||||
expectedDifficulty, err := b.calcNextRequiredDifficulty(prevNode, block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
4
chain.go
4
chain.go
|
@ -339,7 +339,7 @@ func (b *BlockChain) getPrevNodeFromNode(node *blockNode) (*blockNode, error) {
|
|||
}
|
||||
|
||||
// Genesis block.
|
||||
if node.hash.IsEqual(&btcwire.GenesisHash) {
|
||||
if node.hash.IsEqual(b.netParams().genesisHash) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ func (b *BlockChain) isMajorityVersion(minVer uint32, startNode *blockNode, numR
|
|||
func (b *BlockChain) calcPastMedianTime(startNode *blockNode) (time.Time, error) {
|
||||
// Genesis block.
|
||||
if startNode == nil {
|
||||
return btcwire.GenesisBlock.Header.Timestamp, nil
|
||||
return b.netParams().genesisBlock.Header.Timestamp, nil
|
||||
}
|
||||
|
||||
// Create a slice of the previous few block timestamps used to calculate
|
||||
|
|
|
@ -6,6 +6,7 @@ package btcchain
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
"math/big"
|
||||
"time"
|
||||
|
@ -50,10 +51,6 @@ var (
|
|||
// oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid
|
||||
// the overhead of creating it multiple times.
|
||||
oneLsh256 = new(big.Int).Lsh(bigOne, 256)
|
||||
|
||||
// powLimit is the highest proof of work value a bitcoin block can have.
|
||||
// It is the value 2^224 - 1.
|
||||
powLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne)
|
||||
)
|
||||
|
||||
// ShaHashToBig converts a btcwire.ShaHash into a big.Int that can be used to
|
||||
|
@ -185,11 +182,14 @@ func calcWork(bits uint32) *big.Rat {
|
|||
// can have given starting difficulty bits and a duration. It is mainly used to
|
||||
// verify that claimed proof of work by a block is sane as compared to a
|
||||
// known good checkpoint.
|
||||
func calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
||||
func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
||||
// Convert types used in the calculations below.
|
||||
durationVal := int64(duration)
|
||||
adjustmentFactor := big.NewInt(retargetAdjustmentFactor)
|
||||
|
||||
// Choose the correct proof of work limit for the active network.
|
||||
powLimit := b.netParams().powLimit
|
||||
|
||||
// TODO(davec): Testnet has special rules.
|
||||
|
||||
// Since easier difficulty equates to higher numbers, the easiest
|
||||
|
@ -212,7 +212,10 @@ func calcEasiestDifficulty(bits uint32, duration time.Duration) uint32 {
|
|||
|
||||
// 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) (uint32, error) {
|
||||
func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, block *btcutil.Block) (uint32, error) {
|
||||
// Choose the correct proof of work limit for the active network.
|
||||
powLimit := b.netParams().powLimit
|
||||
|
||||
// Genesis block.
|
||||
if lastNode == nil {
|
||||
return BigToCompact(powLimit), nil
|
||||
|
|
|
@ -18,8 +18,8 @@ import (
|
|||
|
||||
// TstCheckBlockSanity makes the internal checkBlockSanity function available to
|
||||
// the test package.
|
||||
func TstCheckBlockSanity(block *btcutil.Block) error {
|
||||
return checkBlockSanity(block)
|
||||
func (b *BlockChain) TstCheckBlockSanity(block *btcutil.Block) error {
|
||||
return b.checkBlockSanity(block)
|
||||
}
|
||||
|
||||
// TstSetCoinbaseMaturity makes the ability to set the coinbase maturity
|
||||
|
|
68
params.go
Normal file
68
params.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) 2013 Conformal Systems LLC.
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package btcchain
|
||||
|
||||
import (
|
||||
"github.com/conformal/btcwire"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// params is used to group parameters for various networks such as the main
|
||||
// network and test networks.
|
||||
type params struct {
|
||||
genesisBlock *btcwire.MsgBlock
|
||||
genesisHash *btcwire.ShaHash
|
||||
powLimit *big.Int
|
||||
}
|
||||
|
||||
// mainNetParams contains parameters specific to the main network
|
||||
// (btcwire.MainNet).
|
||||
var mainNetParams = params{
|
||||
genesisBlock: &btcwire.GenesisBlock,
|
||||
genesisHash: &btcwire.GenesisHash,
|
||||
|
||||
// powLimit is the highest proof of work value a bitcoin block can have.
|
||||
// It is the value 2^224 - 1 for the main network.
|
||||
powLimit: new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne),
|
||||
}
|
||||
|
||||
// regressionParams contains parameters specific to the regression test network
|
||||
// (btcwire.TestNet).
|
||||
var regressionParams = params{
|
||||
genesisBlock: &btcwire.TestNetGenesisBlock,
|
||||
genesisHash: &btcwire.TestNetGenesisHash,
|
||||
|
||||
// powLimit is the highest proof of work value a bitcoin block can have.
|
||||
// It is the value 2^256 - 1 for the regression test network.
|
||||
powLimit: new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne),
|
||||
}
|
||||
|
||||
// testNet3Params contains parameters specific to the test network (version 3)
|
||||
// (btcwire.TestNet3).
|
||||
var testNet3Params = params{
|
||||
genesisBlock: &btcwire.TestNet3GenesisBlock,
|
||||
genesisHash: &btcwire.TestNet3GenesisHash,
|
||||
|
||||
// powLimit is the highest proof of work value a bitcoin block can have.
|
||||
// It is the value 2^224 - 1 for the test network (version 3).
|
||||
powLimit: new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne),
|
||||
}
|
||||
|
||||
// netParams returns parameters specific to the passed bitcoin network.
|
||||
func (b *BlockChain) netParams() *params {
|
||||
switch b.btcnet {
|
||||
case btcwire.TestNet:
|
||||
return ®ressionParams
|
||||
|
||||
case btcwire.TestNet3:
|
||||
return &testNet3Params
|
||||
|
||||
// Return main net by default.
|
||||
case btcwire.MainNet:
|
||||
fallthrough
|
||||
default:
|
||||
return &mainNetParams
|
||||
}
|
||||
}
|
|
@ -95,7 +95,7 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block) error {
|
|||
}
|
||||
|
||||
// Perform preliminary sanity checks on the block and its transactions.
|
||||
err = checkBlockSanity(block)
|
||||
err = b.checkBlockSanity(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block) error {
|
|||
// expected based on elapsed time since the last checkpoint and
|
||||
// maximum adjustment allowed by the retarget rules.
|
||||
duration := blockHeader.Timestamp.Sub(checkpointTime)
|
||||
requiredTarget := CompactToBig(calcEasiestDifficulty(
|
||||
requiredTarget := CompactToBig(b.calcEasiestDifficulty(
|
||||
checkpointHeader.Bits, duration))
|
||||
currentTarget := CompactToBig(blockHeader.Bits)
|
||||
if currentTarget.Cmp(requiredTarget) > 0 {
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
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/merkle.go hashMerkleBranches 100.00% (5/5)
|
||||
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/chain.go newBlockNode 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/log.go DisableLog 100.00% (1/1)
|
||||
github.com/conformal/btcchain/validate.go calcBlockSubsidy 100.00% (1/1)
|
||||
github.com/conformal/btcchain/timesorter.go timeSorter.Less 100.00% (1/1)
|
||||
github.com/conformal/btcchain/log.go init 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/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)
|
||||
|
@ -37,30 +37,31 @@ github.com/conformal/btcchain/chain.go BlockChain.disconnectBlock 76.92% (10
|
|||
github.com/conformal/btcchain/chain.go BlockChain.addOrphanBlock 75.00% (12/16)
|
||||
github.com/conformal/btcchain/difficulty.go CompactToBig 75.00% (9/12)
|
||||
github.com/conformal/btcchain/validate.go BlockChain.checkConnectBlock 68.52% (37/54)
|
||||
github.com/conformal/btcchain/validate.go checkBlockSanity 66.67% (30/45)
|
||||
github.com/conformal/btcchain/validate.go BlockChain.checkBlockSanity 66.67% (30/45)
|
||||
github.com/conformal/btcchain/validate.go isNullOutpoint 66.67% (2/3)
|
||||
github.com/conformal/btcchain/scriptval.go validateTxIn 64.71% (11/17)
|
||||
github.com/conformal/btcchain/validate.go checkTransactionInputs 63.64% (28/44)
|
||||
github.com/conformal/btcchain/validate.go checkTransactionSanity 62.16% (23/37)
|
||||
github.com/conformal/btcchain/txlookup.go connectTransactions 60.00% (9/15)
|
||||
github.com/conformal/btcchain/validate.go isBIP0030Node 60.00% (3/5)
|
||||
github.com/conformal/btcchain/params.go BlockChain.netParams 60.00% (3/5)
|
||||
github.com/conformal/btcchain/process.go BlockChain.ProcessBlock 59.09% (26/44)
|
||||
github.com/conformal/btcchain/validate.go BlockChain.checkProofOfWork 58.82% (10/17)
|
||||
github.com/conformal/btcchain/validate.go BlockChain.checkBIP0030 57.14% (8/14)
|
||||
github.com/conformal/btcchain/validate.go checkProofOfWork 56.25% (9/16)
|
||||
github.com/conformal/btcchain/chain.go BlockChain.loadBlockNode 50.00% (11/22)
|
||||
github.com/conformal/btcchain/notifications.go BlockChain.sendNotification 50.00% (2/4)
|
||||
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/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 10.71% (3/28)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 13.79% (4/29)
|
||||
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/validate.go checkSerializedHeight 0.00% (0/12)
|
||||
github.com/conformal/btcchain/difficulty.go calcEasiestDifficulty 0.00% (0/9)
|
||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcEasiestDifficulty 0.00% (0/10)
|
||||
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)
|
||||
|
@ -70,8 +71,8 @@ github.com/conformal/btcchain/notifications.go NotificationType.String 0.00%
|
|||
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/log.go logClosure.String 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 ------------------------------------- 59.23% (571/964)
|
||||
github.com/conformal/btcchain/log.go logClosure.String 0.00% (0/1)
|
||||
github.com/conformal/btcchain ------------------------------------- 59.26% (576/972)
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ func checkTransactionSanity(tx *btcwire.MsgTx) error {
|
|||
// checkProofOfWork ensures the block header bits which indicate the target
|
||||
// difficulty is in min/max range and that the block hash is less than the
|
||||
// target difficulty as claimed.
|
||||
func checkProofOfWork(block *btcutil.Block) error {
|
||||
func (b *BlockChain) checkProofOfWork(block *btcutil.Block) error {
|
||||
// The target difficulty must be larger than zero.
|
||||
header := block.MsgBlock().Header
|
||||
target := CompactToBig(header.Bits)
|
||||
|
@ -278,6 +278,7 @@ func checkProofOfWork(block *btcutil.Block) error {
|
|||
}
|
||||
|
||||
// The target difficulty must be less than the maximum allowed.
|
||||
powLimit := b.netParams().powLimit
|
||||
if target.Cmp(powLimit) > 0 {
|
||||
str := fmt.Sprintf("block target difficulty of %064x is "+
|
||||
"higher than max of %064x", target, powLimit)
|
||||
|
@ -407,7 +408,7 @@ func countP2SHSigOps(msgTx *btcwire.MsgTx, isCoinBaseTx bool, txStore map[btcwir
|
|||
|
||||
// checkBlockSanity performs some preliminary checks on a block to ensure it is
|
||||
// sane before continuing with block processing. These checks are context free.
|
||||
func checkBlockSanity(block *btcutil.Block) error {
|
||||
func (b *BlockChain) checkBlockSanity(block *btcutil.Block) error {
|
||||
// NOTE: bitcoind does size limits checking here, but the size limits
|
||||
// have already been checked by btcwire for incoming blocks. Also,
|
||||
// btcwire checks the size limits on send too, so there is no need
|
||||
|
@ -416,7 +417,7 @@ func checkBlockSanity(block *btcutil.Block) error {
|
|||
// Ensure the proof of work bits in the block header is in min/max range
|
||||
// and the block hash is less than the target value described by the
|
||||
// bits.
|
||||
err := checkProofOfWork(block)
|
||||
err := b.checkProofOfWork(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -6,15 +6,31 @@ package btcchain_test
|
|||
|
||||
import (
|
||||
"github.com/conformal/btcchain"
|
||||
"github.com/conformal/btcdb"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCheckBlockSanity(t *testing.T) {
|
||||
// Create a new test database.
|
||||
dbName := "cbsanitytest.db"
|
||||
_ = os.Remove(dbName)
|
||||
db, err := btcdb.CreateDB("sqlite", dbName)
|
||||
if err != nil {
|
||||
t.Errorf("Error creating db: %v\n", err)
|
||||
}
|
||||
defer os.Remove(dbName)
|
||||
defer db.Close()
|
||||
|
||||
// Create a new BlockChain instance using the underlying database for
|
||||
// the main bitcoin network and ignore notifications.
|
||||
chain := btcchain.New(db, btcwire.MainNet, nil)
|
||||
|
||||
block := btcutil.NewBlock(&Block100000, btcwire.ProtocolVersion)
|
||||
err := btcchain.TstCheckBlockSanity(block)
|
||||
err = chain.TstCheckBlockSanity(block)
|
||||
if err != nil {
|
||||
t.Errorf("CheckBlockSanity: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue