Initial pass at updating to btcnet.

This change modifies the params struct to embed a *btcnet.Params,
removing the old parameter fields that are handled by the btcnet
package.

Hardcoded network checks have also been removed in favor of modifying
behavior based on the current active net's parameters.

Not all library packages, notable btcutil and btcchain, have been
updated to use btcnet yet, but with this change, each package can be
updated one at a time since the active net's btcnet.Params are
available at each callsite.

ok @davecgh
This commit is contained in:
Josh Rickmar 2014-05-22 23:14:36 -05:00
parent 342d0a536f
commit bcc78565fd
9 changed files with 67 additions and 88 deletions

View file

@ -1487,14 +1487,14 @@ func loadBlockDB() (btcdb.Db, error) {
// Insert the appropriate genesis block for the bitcoin network being // Insert the appropriate genesis block for the bitcoin network being
// connected to if needed. // connected to if needed.
if height == -1 { if height == -1 {
genesis := btcutil.NewBlock(activeNetParams.genesisBlock) genesis := btcutil.NewBlock(activeNetParams.GenesisBlock)
_, err := db.InsertBlock(genesis) _, err := db.InsertBlock(genesis)
if err != nil { if err != nil {
db.Close() db.Close()
return nil, err return nil, err
} }
btcdLog.Infof("Inserted genesis block %v", btcdLog.Infof("Inserted genesis block %v",
activeNetParams.genesisHash) activeNetParams.GenesisHash)
height = 0 height = 0
} }

View file

@ -87,7 +87,7 @@ func btcdMain(serverChan chan<- *server) error {
}) })
// Create server and start it. // Create server and start it.
server, err := newServer(cfg.Listeners, db, activeNetParams.btcnet) server, err := newServer(cfg.Listeners, db, activeNetParams.Params)
if err != nil { if err != nil {
// TODO(oga) this logging could do with some beautifying. // TODO(oga) this logging could do with some beautifying.
btcdLog.Errorf("Unable to start server on %v: %v", btcdLog.Errorf("Unable to start server on %v: %v",

View file

@ -30,7 +30,6 @@ const (
defaultLogLevel = "info" defaultLogLevel = "info"
defaultLogDirname = "logs" defaultLogDirname = "logs"
defaultLogFilename = "btcd.log" defaultLogFilename = "btcd.log"
defaultBtcnet = btcwire.MainNet
defaultMaxPeers = 125 defaultMaxPeers = 125
defaultBanDuration = time.Hour * 24 defaultBanDuration = time.Hour * 24
defaultMaxRPCClients = 10 defaultMaxRPCClients = 10
@ -49,7 +48,6 @@ var (
btcdHomeDir = btcutil.AppDataDir("btcd", false) btcdHomeDir = btcutil.AppDataDir("btcd", false)
defaultConfigFile = filepath.Join(btcdHomeDir, defaultConfigFilename) defaultConfigFile = filepath.Join(btcdHomeDir, defaultConfigFilename)
defaultDataDir = filepath.Join(btcdHomeDir, defaultDataDirname) defaultDataDir = filepath.Join(btcdHomeDir, defaultDataDirname)
defaultListener = net.JoinHostPort("", netParams(defaultBtcnet).listenPort)
knownDbTypes = btcdb.SupportedDBs() knownDbTypes = btcdb.SupportedDBs()
defaultRPCKeyFile = filepath.Join(btcdHomeDir, "rpc.key") defaultRPCKeyFile = filepath.Join(btcdHomeDir, "rpc.key")
defaultRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert") defaultRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert")
@ -389,9 +387,9 @@ func loadConfig() (*config, []string, error) {
// Choose the active network params based on the testnet and regression // Choose the active network params based on the testnet and regression
// test net flags. // test net flags.
if cfg.TestNet3 { if cfg.TestNet3 {
activeNetParams = netParams(btcwire.TestNet3) activeNetParams = &testNet3Params
} else if cfg.RegressionTest { } else if cfg.RegressionTest {
activeNetParams = netParams(btcwire.TestNet) activeNetParams = &regressionNetParams
} }
// Append the network type to the data directory so it is "namespaced" // Append the network type to the data directory so it is "namespaced"
@ -401,12 +399,12 @@ func loadConfig() (*config, []string, error) {
// means each individual piece of serialized data does not have to // means each individual piece of serialized data does not have to
// worry about changing names per network and such. // worry about changing names per network and such.
cfg.DataDir = cleanAndExpandPath(cfg.DataDir) cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
cfg.DataDir = filepath.Join(cfg.DataDir, activeNetParams.netName) cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams))
// Append the network type to the log directory so it is "namespaced" // Append the network type to the log directory so it is "namespaced"
// per network in the same fashion as the data directory. // per network in the same fashion as the data directory.
cfg.LogDir = cleanAndExpandPath(cfg.LogDir) cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
cfg.LogDir = filepath.Join(cfg.LogDir, activeNetParams.netName) cfg.LogDir = filepath.Join(cfg.LogDir, netName(activeNetParams))
// Special show command to list supported subsystems and exit. // Special show command to list supported subsystems and exit.
if cfg.DebugLevel == "show" { if cfg.DebugLevel == "show" {
@ -526,7 +524,7 @@ func loadConfig() (*config, []string, error) {
// Check keys are valid and saved parsed versions. // Check keys are valid and saved parsed versions.
cfg.miningKeys = make([]btcutil.Address, 0, len(cfg.GetWorkKeys)) cfg.miningKeys = make([]btcutil.Address, 0, len(cfg.GetWorkKeys))
for _, strAddr := range cfg.GetWorkKeys { for _, strAddr := range cfg.GetWorkKeys {
addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.btcnet) addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.Net)
if err != nil { if err != nil {
str := "%s: the specified getworkkey '%s' failed to decode: %v" str := "%s: the specified getworkkey '%s' failed to decode: %v"
err := fmt.Errorf(str, "loadConfig", strAddr, err) err := fmt.Errorf(str, "loadConfig", strAddr, err)
@ -534,7 +532,7 @@ func loadConfig() (*config, []string, error) {
parser.WriteHelp(os.Stderr) parser.WriteHelp(os.Stderr)
return nil, nil, err return nil, nil, err
} }
if !addr.IsForNet(activeNetParams.btcnet) { if !addr.IsForNet(activeNetParams.Net) {
str := "%s: the specified getworkkey '%s' is on the wrong network" str := "%s: the specified getworkkey '%s' is on the wrong network"
err := fmt.Errorf(str, "loadConfig", strAddr) err := fmt.Errorf(str, "loadConfig", strAddr)
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View file

@ -778,8 +778,9 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool, isNe
} }
nextBlockHeight := curHeight + 1 nextBlockHeight := curHeight + 1
// Don't allow non-standard transactions on the main network. // Don't allow non-standard transactions if the network parameters
if activeNetParams.btcnet == btcwire.MainNet { // forbid their relaying.
if !activeNetParams.RelayNonStdTxs {
err := checkTransactionStandard(tx, nextBlockHeight) err := checkTransactionStandard(tx, nextBlockHeight)
if err != nil { if err != nil {
str := fmt.Sprintf("transaction %v is not a standard "+ str := fmt.Sprintf("transaction %v is not a standard "+
@ -844,9 +845,9 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool, isNe
return err return err
} }
// Don't allow transactions with non-standard inputs on the main // Don't allow transactions with non-standard inputs if the network
// network. // parameters forbid their relaying.
if activeNetParams.btcnet == btcwire.MainNet { if !activeNetParams.RelayNonStdTxs {
err := checkInputsStandard(tx, txStore) err := checkInputsStandard(tx, txStore)
if err != nil { if err != nil {
str := fmt.Sprintf("transaction %v has a non-standard "+ str := fmt.Sprintf("transaction %v has a non-standard "+

View file

@ -215,7 +215,7 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int64, addr btcutil
}) })
tx.AddTxOut(&btcwire.TxOut{ tx.AddTxOut(&btcwire.TxOut{
Value: btcchain.CalcBlockSubsidy(nextBlockHeight, Value: btcchain.CalcBlockSubsidy(nextBlockHeight,
activeNetParams.btcnet), activeNetParams.Net),
PkScript: pkScript, PkScript: pkScript,
}) })
return btcutil.NewTx(tx), nil return btcutil.NewTx(tx), nil
@ -787,11 +787,9 @@ func UpdateBlockTime(msgBlock *btcwire.MsgBlock, bManager *blockManager) error {
} }
msgBlock.Header.Timestamp = newTimestamp msgBlock.Header.Timestamp = newTimestamp
// Recalculate the required difficulty for the test networks since it // If running on a network that requires recalculating the difficulty,
// can change based on time. // do so now.
if activeNetParams.btcnet == btcwire.TestNet || if activeNetParams.ResetMinDifficulty {
activeNetParams.btcnet == btcwire.TestNet3 {
difficulty, err := bManager.CalcNextRequiredDifficulty(newTimestamp) difficulty, err := bManager.CalcNextRequiredDifficulty(newTimestamp)
if err != nil { if err != nil {
return err return err

View file

@ -5,28 +5,22 @@
package main package main
import ( import (
"github.com/conformal/btcchain" "github.com/conformal/btcnet"
"github.com/conformal/btcwire" "github.com/conformal/btcwire"
"math/big"
) )
// activeNetParams is a pointer to the parameters specific to the // activeNetParams is a pointer to the parameters specific to the
// currently active bitcoin network. // currently active bitcoin network.
var activeNetParams = netParams(defaultBtcnet) var activeNetParams = &mainNetParams
// params is used to group parameters for various networks such as the main // params is used to group parameters for various networks such as the main
// network and test networks. // network and test networks.
type params struct { type params struct {
netName string *btcnet.Params
btcnet btcwire.BitcoinNet peerPort string
genesisBlock *btcwire.MsgBlock listenPort string
genesisHash *btcwire.ShaHash rpcPort string
powLimit *big.Int dnsSeeds []string
powLimitBits uint32
peerPort string
listenPort string
rpcPort string
dnsSeeds []string
} }
// mainNetParams contains parameters specific to the main network // mainNetParams contains parameters specific to the main network
@ -36,15 +30,10 @@ type params struct {
// it does not handle on to btcd. This approach allows the wallet process // it does not handle on to btcd. This approach allows the wallet process
// to emulate the full reference implementation RPC API. // to emulate the full reference implementation RPC API.
var mainNetParams = params{ var mainNetParams = params{
netName: "mainnet", Params: &btcnet.MainNetParams,
btcnet: btcwire.MainNet, listenPort: btcwire.MainPort,
genesisBlock: btcchain.ChainParams(btcwire.MainNet).GenesisBlock, peerPort: btcwire.MainPort,
genesisHash: btcchain.ChainParams(btcwire.MainNet).GenesisHash, rpcPort: "8334",
powLimit: btcchain.ChainParams(btcwire.MainNet).PowLimit,
powLimitBits: btcchain.ChainParams(btcwire.MainNet).PowLimitBits,
listenPort: btcwire.MainPort,
peerPort: btcwire.MainPort,
rpcPort: "8334",
dnsSeeds: []string{ dnsSeeds: []string{
"seed.bitcoin.sipa.be", "seed.bitcoin.sipa.be",
"dnsseed.bluematt.me", "dnsseed.bluematt.me",
@ -55,54 +44,46 @@ var mainNetParams = params{
}, },
} }
// regressionParams contains parameters specific to the regression test network // regressionNetParams contains parameters specific to the regression test
// (btcwire.TestNet). NOTE: The RPC port is intentionally different than the // network (btcwire.TestNet). NOTE: The RPC port is intentionally different
// reference implementation - see the mainNetParams comment for details. // than the reference implementation - see the mainNetParams comment for
var regressionParams = params{ // details.
netName: "regtest", var regressionNetParams = params{
btcnet: btcwire.TestNet, Params: &btcnet.RegressionNetParams,
genesisBlock: btcchain.ChainParams(btcwire.TestNet).GenesisBlock, listenPort: btcwire.RegressionTestPort,
genesisHash: btcchain.ChainParams(btcwire.TestNet).GenesisHash, peerPort: btcwire.TestNetPort,
powLimit: btcchain.ChainParams(btcwire.TestNet).PowLimit, rpcPort: "18334",
powLimitBits: btcchain.ChainParams(btcwire.TestNet).PowLimitBits, dnsSeeds: []string{},
listenPort: btcwire.RegressionTestPort,
peerPort: btcwire.TestNetPort,
rpcPort: "18334",
dnsSeeds: []string{},
} }
// testNet3Params contains parameters specific to the test network (version 3) // testNet3Params contains parameters specific to the test network (version 3)
// (btcwire.TestNet3). NOTE: The RPC port is intentionally different than the // (btcwire.TestNet3). NOTE: The RPC port is intentionally different than the
// reference implementation - see the mainNetParams comment for details. // reference implementation - see the mainNetParams comment for details.
var testNet3Params = params{ var testNet3Params = params{
netName: "testnet", Params: &btcnet.TestNet3Params,
btcnet: btcwire.TestNet3, listenPort: btcwire.TestNetPort,
genesisBlock: btcchain.ChainParams(btcwire.TestNet3).GenesisBlock, peerPort: btcwire.TestNetPort,
genesisHash: btcchain.ChainParams(btcwire.TestNet3).GenesisHash, rpcPort: "18334",
powLimit: btcchain.ChainParams(btcwire.TestNet3).PowLimit,
powLimitBits: btcchain.ChainParams(btcwire.TestNet3).PowLimitBits,
listenPort: btcwire.TestNetPort,
peerPort: btcwire.TestNetPort,
rpcPort: "18334",
dnsSeeds: []string{ dnsSeeds: []string{
"testnet-seed.bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me", "testnet-seed.bluematt.me",
}, },
} }
// netParams returns parameters specific to the passed bitcoin network. // netName returns the name used when referring to a bitcoin network. At the
func netParams(btcnet btcwire.BitcoinNet) *params { // time of writing, btcd currently places blocks for testnet version 3 in the
switch btcnet { // data and log directory "testnet", which does not match the Name field of the
case btcwire.TestNet: // btcnet parameters. This function can be used to override this directory name
return &regressionParams // as "testnet" when the passed active network matches btcwire.TestNet3.
//
// A proper upgrade to move the data and log directories for this network to
// "testnet3" is planned for the future, at which point this function can be
// removed and the network parameter's name used instead.
func netName(netParams *params) string {
switch netParams.Net {
case btcwire.TestNet3: case btcwire.TestNet3:
return &testNet3Params return "testnet"
// Return main net by default.
case btcwire.MainNet:
fallthrough
default: default:
return &mainNetParams return netParams.Name
} }
} }

View file

@ -588,7 +588,7 @@ func handleCreateRawTransaction(s *rpcServer, cmd btcjson.Cmd) (interface{}, err
// Decode the provided address. // Decode the provided address.
addr, err := btcutil.DecodeAddress(encodedAddr, addr, err := btcutil.DecodeAddress(encodedAddr,
activeNetParams.btcnet) activeNetParams.Net)
if err != nil { if err != nil {
return nil, btcjson.Error{ return nil, btcjson.Error{
Code: btcjson.ErrInvalidAddressOrKey.Code, Code: btcjson.ErrInvalidAddressOrKey.Code,
@ -1710,7 +1710,7 @@ func handleGetWorkSubmission(s *rpcServer, hexData string) (interface{}, error)
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
// Ensure the submitted block hash is less than the target difficulty. // Ensure the submitted block hash is less than the target difficulty.
err = btcchain.CheckProofOfWork(block, activeNetParams.powLimit) err = btcchain.CheckProofOfWork(block, activeNetParams.PowLimit)
if err != nil { if err != nil {
// Anything other than a rule violation is an unexpected error, // Anything other than a rule violation is an unexpected error,
// so return that error as an internal error. // so return that error as an internal error.
@ -1998,7 +1998,7 @@ func verifyChain(db btcdb.Db, level, depth int32) error {
// Level 1 does basic chain sanity checks. // Level 1 does basic chain sanity checks.
if level > 0 { if level > 0 {
err := btcchain.CheckBlockSanity(block, err := btcchain.CheckBlockSanity(block,
activeNetParams.powLimit) activeNetParams.PowLimit)
if err != nil { if err != nil {
rpcsLog.Errorf("Verify is unable to "+ rpcsLog.Errorf("Verify is unable to "+
"validate block at sha %v height "+ "validate block at sha %v height "+
@ -2088,7 +2088,7 @@ func getDifficultyRatio(bits uint32) float64 {
// converted back to a number. Note this is not the same as the the // converted back to a number. Note this is not the same as the the
// proof of work limit directly because the block difficulty is encoded // proof of work limit directly because the block difficulty is encoded
// in a block with the compact form which loses precision. // in a block with the compact form which loses precision.
max := btcchain.CompactToBig(activeNetParams.powLimitBits) max := btcchain.CompactToBig(activeNetParams.PowLimitBits)
target := btcchain.CompactToBig(bits) target := btcchain.CompactToBig(bits)
difficulty := new(big.Rat).SetFrac(max, target) difficulty := new(big.Rat).SetFrac(max, target)

View file

@ -1433,7 +1433,7 @@ func handleNotifyReceived(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjso
} }
for _, addrStr := range cmd.Addresses { for _, addrStr := range cmd.Addresses {
addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.btcnet) addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.Net)
if err != nil { if err != nil {
e := btcjson.Error{ e := btcjson.Error{
Code: btcjson.ErrInvalidAddressOrKey.Code, Code: btcjson.ErrInvalidAddressOrKey.Code,
@ -1630,7 +1630,7 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error)
var compressedPubkey [33]byte var compressedPubkey [33]byte
var uncompressedPubkey [65]byte var uncompressedPubkey [65]byte
for _, addrStr := range cmd.Addresses { for _, addrStr := range cmd.Addresses {
addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.btcnet) addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.Net)
if err != nil { if err != nil {
jsonErr := btcjson.Error{ jsonErr := btcjson.Error{
Code: btcjson.ErrInvalidAddressOrKey.Code, Code: btcjson.ErrInvalidAddressOrKey.Code,

View file

@ -12,6 +12,7 @@ import (
"fmt" "fmt"
"github.com/conformal/btcdb" "github.com/conformal/btcdb"
"github.com/conformal/btcjson" "github.com/conformal/btcjson"
"github.com/conformal/btcnet"
"github.com/conformal/btcwire" "github.com/conformal/btcwire"
"math" "math"
"net" "net"
@ -1003,9 +1004,9 @@ out:
} }
// newServer returns a new btcd server configured to listen on addr for the // newServer returns a new btcd server configured to listen on addr for the
// bitcoin network type specified in btcnet. Use start to begin accepting // bitcoin network type specified by netParams. Use start to begin accepting
// connections from peers. // connections from peers.
func newServer(listenAddrs []string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*server, error) { func newServer(listenAddrs []string, db btcdb.Db, netParams *btcnet.Params) (*server, error) {
nonce, err := btcwire.RandomUint64() nonce, err := btcwire.RandomUint64()
if err != nil { if err != nil {
return nil, err return nil, err
@ -1128,7 +1129,7 @@ func newServer(listenAddrs []string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*s
s := server{ s := server{
nonce: nonce, nonce: nonce,
listeners: listeners, listeners: listeners,
btcnet: btcnet, btcnet: netParams.Net,
addrManager: amgr, addrManager: amgr,
newPeers: make(chan *peer, cfg.MaxPeers), newPeers: make(chan *peer, cfg.MaxPeers),
donePeers: make(chan *peer, cfg.MaxPeers), donePeers: make(chan *peer, cfg.MaxPeers),