349 lines
13 KiB
Go
349 lines
13 KiB
Go
// 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: 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)
|
|
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
|
|
}
|