From bcc78565fd3be82f0adbc4ba9f439f5e5a2d0ebc Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Thu, 22 May 2014 23:14:36 -0500 Subject: [PATCH] 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 --- blockmanager.go | 4 +-- btcd.go | 2 +- config.go | 14 ++++---- mempool.go | 11 +++--- mining.go | 10 +++--- params.go | 95 ++++++++++++++++++++----------------------------- rpcserver.go | 8 ++--- rpcwebsocket.go | 4 +-- server.go | 7 ++-- 9 files changed, 67 insertions(+), 88 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index f328cf3e1..d9d3b3b3d 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -1487,14 +1487,14 @@ func loadBlockDB() (btcdb.Db, error) { // Insert the appropriate genesis block for the bitcoin network being // connected to if needed. if height == -1 { - genesis := btcutil.NewBlock(activeNetParams.genesisBlock) + genesis := btcutil.NewBlock(activeNetParams.GenesisBlock) _, err := db.InsertBlock(genesis) if err != nil { db.Close() return nil, err } btcdLog.Infof("Inserted genesis block %v", - activeNetParams.genesisHash) + activeNetParams.GenesisHash) height = 0 } diff --git a/btcd.go b/btcd.go index 064721b64..b41c9bfb2 100644 --- a/btcd.go +++ b/btcd.go @@ -87,7 +87,7 @@ func btcdMain(serverChan chan<- *server) error { }) // Create server and start it. - server, err := newServer(cfg.Listeners, db, activeNetParams.btcnet) + server, err := newServer(cfg.Listeners, db, activeNetParams.Params) if err != nil { // TODO(oga) this logging could do with some beautifying. btcdLog.Errorf("Unable to start server on %v: %v", diff --git a/config.go b/config.go index b5b2b46bf..3e944e466 100644 --- a/config.go +++ b/config.go @@ -30,7 +30,6 @@ const ( defaultLogLevel = "info" defaultLogDirname = "logs" defaultLogFilename = "btcd.log" - defaultBtcnet = btcwire.MainNet defaultMaxPeers = 125 defaultBanDuration = time.Hour * 24 defaultMaxRPCClients = 10 @@ -49,7 +48,6 @@ var ( btcdHomeDir = btcutil.AppDataDir("btcd", false) defaultConfigFile = filepath.Join(btcdHomeDir, defaultConfigFilename) defaultDataDir = filepath.Join(btcdHomeDir, defaultDataDirname) - defaultListener = net.JoinHostPort("", netParams(defaultBtcnet).listenPort) knownDbTypes = btcdb.SupportedDBs() defaultRPCKeyFile = filepath.Join(btcdHomeDir, "rpc.key") 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 // test net flags. if cfg.TestNet3 { - activeNetParams = netParams(btcwire.TestNet3) + activeNetParams = &testNet3Params } else if cfg.RegressionTest { - activeNetParams = netParams(btcwire.TestNet) + activeNetParams = ®ressionNetParams } // 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 // worry about changing names per network and such. 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" // per network in the same fashion as the data directory. 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. if cfg.DebugLevel == "show" { @@ -526,7 +524,7 @@ func loadConfig() (*config, []string, error) { // Check keys are valid and saved parsed versions. cfg.miningKeys = make([]btcutil.Address, 0, len(cfg.GetWorkKeys)) for _, strAddr := range cfg.GetWorkKeys { - addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.btcnet) + addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.Net) if err != nil { str := "%s: the specified getworkkey '%s' failed to decode: %v" err := fmt.Errorf(str, "loadConfig", strAddr, err) @@ -534,7 +532,7 @@ func loadConfig() (*config, []string, error) { parser.WriteHelp(os.Stderr) 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" err := fmt.Errorf(str, "loadConfig", strAddr) fmt.Fprintln(os.Stderr, err) diff --git a/mempool.go b/mempool.go index cf609d1ce..84f6dc056 100644 --- a/mempool.go +++ b/mempool.go @@ -778,8 +778,9 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isOrphan *bool, isNe } nextBlockHeight := curHeight + 1 - // Don't allow non-standard transactions on the main network. - if activeNetParams.btcnet == btcwire.MainNet { + // Don't allow non-standard transactions if the network parameters + // forbid their relaying. + if !activeNetParams.RelayNonStdTxs { err := checkTransactionStandard(tx, nextBlockHeight) if err != nil { 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 } - // Don't allow transactions with non-standard inputs on the main - // network. - if activeNetParams.btcnet == btcwire.MainNet { + // Don't allow transactions with non-standard inputs if the network + // parameters forbid their relaying. + if !activeNetParams.RelayNonStdTxs { err := checkInputsStandard(tx, txStore) if err != nil { str := fmt.Sprintf("transaction %v has a non-standard "+ diff --git a/mining.go b/mining.go index d33c1a490..77789c65e 100644 --- a/mining.go +++ b/mining.go @@ -215,7 +215,7 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int64, addr btcutil }) tx.AddTxOut(&btcwire.TxOut{ Value: btcchain.CalcBlockSubsidy(nextBlockHeight, - activeNetParams.btcnet), + activeNetParams.Net), PkScript: pkScript, }) return btcutil.NewTx(tx), nil @@ -787,11 +787,9 @@ func UpdateBlockTime(msgBlock *btcwire.MsgBlock, bManager *blockManager) error { } msgBlock.Header.Timestamp = newTimestamp - // Recalculate the required difficulty for the test networks since it - // can change based on time. - if activeNetParams.btcnet == btcwire.TestNet || - activeNetParams.btcnet == btcwire.TestNet3 { - + // If running on a network that requires recalculating the difficulty, + // do so now. + if activeNetParams.ResetMinDifficulty { difficulty, err := bManager.CalcNextRequiredDifficulty(newTimestamp) if err != nil { return err diff --git a/params.go b/params.go index 51c760332..8f29a839f 100644 --- a/params.go +++ b/params.go @@ -5,28 +5,22 @@ package main import ( - "github.com/conformal/btcchain" + "github.com/conformal/btcnet" "github.com/conformal/btcwire" - "math/big" ) // activeNetParams is a pointer to the parameters specific to the // currently active bitcoin network. -var activeNetParams = netParams(defaultBtcnet) +var activeNetParams = &mainNetParams // params is used to group parameters for various networks such as the main // network and test networks. type params struct { - netName string - btcnet btcwire.BitcoinNet - genesisBlock *btcwire.MsgBlock - genesisHash *btcwire.ShaHash - powLimit *big.Int - powLimitBits uint32 - peerPort string - listenPort string - rpcPort string - dnsSeeds []string + *btcnet.Params + peerPort string + listenPort string + rpcPort string + dnsSeeds []string } // 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 // to emulate the full reference implementation RPC API. var mainNetParams = params{ - netName: "mainnet", - btcnet: btcwire.MainNet, - genesisBlock: btcchain.ChainParams(btcwire.MainNet).GenesisBlock, - genesisHash: btcchain.ChainParams(btcwire.MainNet).GenesisHash, - powLimit: btcchain.ChainParams(btcwire.MainNet).PowLimit, - powLimitBits: btcchain.ChainParams(btcwire.MainNet).PowLimitBits, - listenPort: btcwire.MainPort, - peerPort: btcwire.MainPort, - rpcPort: "8334", + Params: &btcnet.MainNetParams, + listenPort: btcwire.MainPort, + peerPort: btcwire.MainPort, + rpcPort: "8334", dnsSeeds: []string{ "seed.bitcoin.sipa.be", "dnsseed.bluematt.me", @@ -55,54 +44,46 @@ var mainNetParams = params{ }, } -// regressionParams contains parameters specific to the regression test network -// (btcwire.TestNet). NOTE: The RPC port is intentionally different than the -// reference implementation - see the mainNetParams comment for details. -var regressionParams = params{ - netName: "regtest", - btcnet: btcwire.TestNet, - genesisBlock: btcchain.ChainParams(btcwire.TestNet).GenesisBlock, - genesisHash: btcchain.ChainParams(btcwire.TestNet).GenesisHash, - powLimit: btcchain.ChainParams(btcwire.TestNet).PowLimit, - powLimitBits: btcchain.ChainParams(btcwire.TestNet).PowLimitBits, - listenPort: btcwire.RegressionTestPort, - peerPort: btcwire.TestNetPort, - rpcPort: "18334", - dnsSeeds: []string{}, +// regressionNetParams contains parameters specific to the regression test +// network (btcwire.TestNet). NOTE: The RPC port is intentionally different +// than the reference implementation - see the mainNetParams comment for +// details. +var regressionNetParams = params{ + Params: &btcnet.RegressionNetParams, + listenPort: btcwire.RegressionTestPort, + peerPort: btcwire.TestNetPort, + rpcPort: "18334", + dnsSeeds: []string{}, } // testNet3Params contains parameters specific to the test network (version 3) // (btcwire.TestNet3). NOTE: The RPC port is intentionally different than the // reference implementation - see the mainNetParams comment for details. var testNet3Params = params{ - netName: "testnet", - btcnet: btcwire.TestNet3, - genesisBlock: btcchain.ChainParams(btcwire.TestNet3).GenesisBlock, - genesisHash: btcchain.ChainParams(btcwire.TestNet3).GenesisHash, - powLimit: btcchain.ChainParams(btcwire.TestNet3).PowLimit, - powLimitBits: btcchain.ChainParams(btcwire.TestNet3).PowLimitBits, - listenPort: btcwire.TestNetPort, - peerPort: btcwire.TestNetPort, - rpcPort: "18334", + Params: &btcnet.TestNet3Params, + listenPort: btcwire.TestNetPort, + peerPort: btcwire.TestNetPort, + rpcPort: "18334", dnsSeeds: []string{ "testnet-seed.bitcoin.petertodd.org", "testnet-seed.bluematt.me", }, } -// netParams returns parameters specific to the passed bitcoin network. -func netParams(btcnet btcwire.BitcoinNet) *params { - switch btcnet { - case btcwire.TestNet: - return ®ressionParams - +// netName returns the name used when referring to a bitcoin network. At the +// time of writing, btcd currently places blocks for testnet version 3 in the +// data and log directory "testnet", which does not match the Name field of the +// btcnet parameters. This function can be used to override this directory name +// 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: - return &testNet3Params - - // Return main net by default. - case btcwire.MainNet: - fallthrough + return "testnet" default: - return &mainNetParams + return netParams.Name } } diff --git a/rpcserver.go b/rpcserver.go index 8bada7a83..e3cd4efbe 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -588,7 +588,7 @@ func handleCreateRawTransaction(s *rpcServer, cmd btcjson.Cmd) (interface{}, err // Decode the provided address. addr, err := btcutil.DecodeAddress(encodedAddr, - activeNetParams.btcnet) + activeNetParams.Net) if err != nil { return nil, btcjson.Error{ Code: btcjson.ErrInvalidAddressOrKey.Code, @@ -1710,7 +1710,7 @@ func handleGetWorkSubmission(s *rpcServer, hexData string) (interface{}, error) msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] // 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 { // Anything other than a rule violation is an unexpected 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. if level > 0 { err := btcchain.CheckBlockSanity(block, - activeNetParams.powLimit) + activeNetParams.PowLimit) if err != nil { rpcsLog.Errorf("Verify is unable to "+ "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 // proof of work limit directly because the block difficulty is encoded // in a block with the compact form which loses precision. - max := btcchain.CompactToBig(activeNetParams.powLimitBits) + max := btcchain.CompactToBig(activeNetParams.PowLimitBits) target := btcchain.CompactToBig(bits) difficulty := new(big.Rat).SetFrac(max, target) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 07d8e1d7f..96511d873 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -1433,7 +1433,7 @@ func handleNotifyReceived(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjso } for _, addrStr := range cmd.Addresses { - addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.btcnet) + addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.Net) if err != nil { e := btcjson.Error{ Code: btcjson.ErrInvalidAddressOrKey.Code, @@ -1630,7 +1630,7 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error) var compressedPubkey [33]byte var uncompressedPubkey [65]byte for _, addrStr := range cmd.Addresses { - addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.btcnet) + addr, err := btcutil.DecodeAddress(addrStr, activeNetParams.Net) if err != nil { jsonErr := btcjson.Error{ Code: btcjson.ErrInvalidAddressOrKey.Code, diff --git a/server.go b/server.go index 5592912cd..4dd9a0278 100644 --- a/server.go +++ b/server.go @@ -12,6 +12,7 @@ import ( "fmt" "github.com/conformal/btcdb" "github.com/conformal/btcjson" + "github.com/conformal/btcnet" "github.com/conformal/btcwire" "math" "net" @@ -1003,9 +1004,9 @@ out: } // 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. -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() if err != nil { return nil, err @@ -1128,7 +1129,7 @@ func newServer(listenAddrs []string, db btcdb.Db, btcnet btcwire.BitcoinNet) (*s s := server{ nonce: nonce, listeners: listeners, - btcnet: btcnet, + btcnet: netParams.Net, addrManager: amgr, newPeers: make(chan *peer, cfg.MaxPeers), donePeers: make(chan *peer, cfg.MaxPeers),