// Copyright (c) 2014 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package btcnet import ( "errors" "math/big" "github.com/conformal/btcwire" ) // These variables are the chain proof-of-work limit parameters for each default // network. var ( // bigOne is 1 represented as a big.Int. It is defined here to avoid // the overhead of creating it multiple times. bigOne = big.NewInt(1) // mainPowLimit is the highest proof of work value a Bitcoin block can // have for the main network. It is the value 2^224 - 1. mainPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne) // regressionPowLimit is the highest proof of work value a Bitcoin block // can have for the regression test network. It is the value 2^255 - 1. regressionPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne) // testNet3PowLimit is the highest proof of work value a Bitcoin block // can have for the test network (version 3). It is the value // 2^224 - 1. testNet3PowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne) // simNetPowLimit is the highest proof of work value a Bitcoin block // can have for the simulation test network. It is the value 2^255 - 1. simNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne) ) // Checkpoint identifies a known good point in the block chain. Using // checkpoints allows a few optimizations for old blocks during initial download // and also prevents forks from old blocks. // // Each checkpoint is selected based upon several factors. See the // documentation for btcchain.IsCheckpointCandidate for details on the selection // criteria. type Checkpoint struct { Height int64 Hash *btcwire.ShaHash } // Params defines a Bitcoin network by its parameters. These parameters may be // used by Bitcoin applications to differentiate networks as well as addresses // and keys for one network from those intended for use on another network. type Params struct { Name string Net btcwire.BitcoinNet DefaultPort string // Chain parameters GenesisBlock *btcwire.MsgBlock GenesisHash *btcwire.ShaHash PowLimit *big.Int PowLimitBits uint32 SubsidyHalvingInterval int32 ResetMinDifficulty bool // Checkpoints ordered from oldest to newest. Checkpoints []Checkpoint // Reject version 1 blocks once a majority of the network has upgraded. // This is part of BIP0034. BlockV1RejectNumRequired uint64 BlockV1RejectNumToCheck uint64 // Ensure coinbase starts with serialized block heights for version 2 // blocks or newer once a majority of the network has upgraded. CoinbaseBlockHeightNumRequired uint64 CoinbaseBlockHeightNumToCheck uint64 // Mempool parameters RelayNonStdTxs bool // Encoding magics PubKeyHashAddrID byte // First byte of a P2PKH address ScriptHashAddrID byte // First byte of a P2SH address PrivateKeyID byte // First byte of a WIF private key } // MainNetParams defines the network parameters for the main Bitcoin network. var MainNetParams = Params{ Name: "mainnet", Net: btcwire.MainNet, DefaultPort: "8333", // Chain parameters GenesisBlock: &genesisBlock, GenesisHash: &genesisHash, PowLimit: mainPowLimit, PowLimitBits: 0x1d00ffff, SubsidyHalvingInterval: 210000, ResetMinDifficulty: false, // Checkpoints ordered from oldest to newest. Checkpoints: []Checkpoint{ {11111, newShaHashFromStr("0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")}, {33333, newShaHashFromStr("000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")}, {74000, newShaHashFromStr("0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")}, {105000, newShaHashFromStr("00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")}, {134444, newShaHashFromStr("00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")}, {168000, newShaHashFromStr("000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")}, {193000, newShaHashFromStr("000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")}, {210000, newShaHashFromStr("000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")}, {216116, newShaHashFromStr("00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")}, {225430, newShaHashFromStr("00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")}, {250000, newShaHashFromStr("000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")}, {267300, newShaHashFromStr("000000000000000a83fbd660e918f218bf37edd92b748ad940483c7c116179ac")}, {279000, newShaHashFromStr("0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")}, {300255, newShaHashFromStr("0000000000000000162804527c6e9b9f0563a280525f9d08c12041def0a0f3b2")}, }, // Reject version 1 blocks once a majority of the network has upgraded. // 95% (950 / 1000) // This is part of BIP0034. BlockV1RejectNumRequired: 950, BlockV1RejectNumToCheck: 1000, // Ensure coinbase starts with serialized block heights for version 2 // blocks or newer once a majority of the network has upgraded. // 75% (750 / 1000) // This is part of BIP0034. CoinbaseBlockHeightNumRequired: 750, CoinbaseBlockHeightNumToCheck: 1000, // Mempool parameters RelayNonStdTxs: false, // Encoding magics PubKeyHashAddrID: 0x00, // starts with 1 ScriptHashAddrID: 0x05, // starts with 3 PrivateKeyID: 0x80, // starts with 5 (uncompressed) or K (compressed) } // RegressionNetParams defines the network parameters for the regression test // Bitcoin network. Not to be confused with the test Bitcoin network (version // 3), this network is sometimes simply called "testnet". var RegressionNetParams = Params{ Name: "regtest", Net: btcwire.TestNet, DefaultPort: "18444", // Chain parameters GenesisBlock: ®TestGenesisBlock, GenesisHash: ®TestGenesisHash, PowLimit: regressionPowLimit, PowLimitBits: 0x207fffff, SubsidyHalvingInterval: 150, ResetMinDifficulty: true, // Checkpoints ordered from oldest to newest. Checkpoints: nil, // Reject version 1 blocks once a majority of the network has upgraded. // 75% (75 / 100) // This is part of BIP0034. BlockV1RejectNumRequired: 75, BlockV1RejectNumToCheck: 100, // Ensure coinbase starts with serialized block heights for version 2 // blocks or newer once a majority of the network has upgraded. // 51% (51 / 100) // This is part of BIP0034. CoinbaseBlockHeightNumRequired: 51, CoinbaseBlockHeightNumToCheck: 100, // Mempool parameters RelayNonStdTxs: true, // Encoding magics PubKeyHashAddrID: 0x6f, // starts with m or n ScriptHashAddrID: 0xc4, // starts with 2 PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) } // TestNet3Params defines the network parameters for the test Bitcoin network // (version 3). Not to be confused with the regression test network, this // network is sometimes simply called "testnet". var TestNet3Params = Params{ Name: "testnet3", Net: btcwire.TestNet3, DefaultPort: "18333", // Chain parameters GenesisBlock: &testNet3GenesisBlock, GenesisHash: &testNet3GenesisHash, PowLimit: testNet3PowLimit, PowLimitBits: 0x1d00ffff, SubsidyHalvingInterval: 210000, ResetMinDifficulty: true, // Checkpoints ordered from oldest to newest. Checkpoints: []Checkpoint{ {546, newShaHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, }, // Reject version 1 blocks once a majority of the network has upgraded. // 75% (75 / 100) // This is part of BIP0034. BlockV1RejectNumRequired: 75, BlockV1RejectNumToCheck: 100, // Ensure coinbase starts with serialized block heights for version 2 // blocks or newer once a majority of the network has upgraded. // 51% (51 / 100) // This is part of BIP0034. CoinbaseBlockHeightNumRequired: 51, CoinbaseBlockHeightNumToCheck: 100, // Mempool parameters RelayNonStdTxs: true, // Encoding magics PubKeyHashAddrID: 0x6f, // starts with m or n ScriptHashAddrID: 0xc4, // starts with 2 PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) } // SimNetParams defines the network parameters for the simulation test Bitcoin // network. This network is similar to the normal test network except it is // intended for private use within a group of individuals doing simulation // testing. The functionality is intended to differ in that the only nodes // which are specifically specified are used to create the network rather than // following normal discovery rules. This is important as otherwise it would // just turn into another public testnet. var SimNetParams = Params{ Name: "simnet", Net: btcwire.SimNet, DefaultPort: "18555", // Chain parameters GenesisBlock: &simNetGenesisBlock, GenesisHash: &simNetGenesisHash, PowLimit: simNetPowLimit, PowLimitBits: 0x207fffff, SubsidyHalvingInterval: 210000, ResetMinDifficulty: true, // Checkpoints ordered from oldest to newest. Checkpoints: nil, // Reject version 1 blocks once a majority of the network has upgraded. // 75% (75 / 100) BlockV1RejectNumRequired: 75, BlockV1RejectNumToCheck: 100, // Ensure coinbase starts with serialized block heights for version 2 // blocks or newer once a majority of the network has upgraded. // 51% (51 / 100) CoinbaseBlockHeightNumRequired: 51, CoinbaseBlockHeightNumToCheck: 100, // Mempool parameters RelayNonStdTxs: true, // Encoding magics PubKeyHashAddrID: 0x3f, // starts with S ScriptHashAddrID: 0x7b, // starts with s PrivateKeyID: 0x64, // starts with 4 (uncompressed) or F (compressed) } var ( // ErrDuplicateNet describes an error where the parameters for a Bitcoin // network could not be set due to the network already being a standard // network or previously-registered into this package. ErrDuplicateNet = errors.New("duplicate Bitcoin network") ) var ( registeredNets = map[btcwire.BitcoinNet]struct{}{} pubKeyHashAddrIDs = map[byte]struct{}{ MainNetParams.PubKeyHashAddrID: struct{}{}, TestNet3Params.PubKeyHashAddrID: struct{}{}, // shared with regtest SimNetParams.PubKeyHashAddrID: struct{}{}, } scriptHashAddrIDs = map[byte]struct{}{ MainNetParams.ScriptHashAddrID: struct{}{}, TestNet3Params.ScriptHashAddrID: struct{}{}, // shared with regtest SimNetParams.ScriptHashAddrID: struct{}{}, } ) // Register registers the network parameters for a Bitcoin network. This may // error with ErrDuplicateNet if the network is already registered. // // Network parameters should be registered into this package by a main package // as early as possible. Then, library packages may lookup networks or network // parameters based on inputs and work regardless of the network being standard // or not. func Register(params *Params) error { if _, ok := registeredNets[params.Net]; ok { return ErrDuplicateNet } registeredNets[params.Net] = struct{}{} pubKeyHashAddrIDs[params.PubKeyHashAddrID] = struct{}{} scriptHashAddrIDs[params.ScriptHashAddrID] = struct{}{} return nil } // IsPubKeyHashAddrID returns whether the id is an identifier known to prefix a // pay-to-pubkey-hash address on any default or registered network. This is // used when decoding an address string into a specific address type. It is up // to the caller to check both this and IsScriptHashAddrID and decide whether an // address is a pubkey hash address, script hash address, neither, or // undeterminable (if both return true). func IsPubKeyHashAddrID(id byte) bool { _, ok := pubKeyHashAddrIDs[id] return ok } // IsScriptHashAddrID returns whether the id is an identifier known to prefix a // pay-to-script-hash address on any default or registered network. This is // used when decoding an address string into a specific address type. It is up // to the caller to check both this and IsPubKeyHashAddrID and decide whether an // address is a pubkey hash address, script hash address, neither, or // undeterminable (if both return true). func IsScriptHashAddrID(id byte) bool { _, ok := scriptHashAddrIDs[id] return ok } // newShaHashFromStr converts the passed big-endian hex string into a // btcwire.ShaHash. It only differs from the one available in btcwire in that // it panics on an error since it will only (and must only) be called with // hard-coded, and therefore known good, hashes. func newShaHashFromStr(hexStr string) *btcwire.ShaHash { sha, err := btcwire.NewShaHashFromStr(hexStr) if err != nil { // Ordinarily I don't like panics in library code since it // can take applications down without them having a chance to // recover which is extremely annoying, however an exception is // being made in this case because the only way this can panic // is if there is an error in the hard-coded hashes. Thus it // will only ever potentially panic on init and therefore is // 100% predictable. panic(err) } return sha }