Merge pull request #1692 from guggero/signet

wire+chaincfg: add signet params
This commit is contained in:
Olaoluwa Osuntokun 2021-04-26 11:01:13 -07:00 committed by GitHub
commit 7eba688b65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 347 additions and 5 deletions

View file

@ -170,3 +170,31 @@ var simNetGenesisBlock = wire.MsgBlock{
},
Transactions: []*wire.MsgTx{&genesisCoinbaseTx},
}
// sigNetGenesisHash is the hash of the first block in the block chain for the
// signet test network.
var sigNetGenesisHash = chainhash.Hash{
0xf6, 0x1e, 0xee, 0x3b, 0x63, 0xa3, 0x80, 0xa4,
0x77, 0xa0, 0x63, 0xaf, 0x32, 0xb2, 0xbb, 0xc9,
0x7c, 0x9f, 0xf9, 0xf0, 0x1f, 0x2c, 0x42, 0x25,
0xe9, 0x73, 0x98, 0x81, 0x08, 0x00, 0x00, 0x00,
}
// sigNetGenesisMerkleRoot is the hash of the first transaction in the genesis
// block for the signet test network. It is the same as the merkle root for
// the main network.
var sigNetGenesisMerkleRoot = genesisMerkleRoot
// sigNetGenesisBlock defines the genesis block of the block chain which serves
// as the public transaction ledger for the signet test network.
var sigNetGenesisBlock = wire.MsgBlock{
Header: wire.BlockHeader{
Version: 1,
PrevBlock: chainhash.Hash{}, // 0000000000000000000000000000000000000000000000000000000000000000
MerkleRoot: sigNetGenesisMerkleRoot, // 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
Timestamp: time.Unix(1598918400, 0), // 2020-09-01 00:00:00 +0000 UTC
Bits: 0x1e0377ae, // 503543726 [00000377ae000000000000000000000000000000000000000000000000000000]
Nonce: 52613770,
},
Transactions: []*wire.MsgTx{&genesisCoinbaseTx},
}

View file

@ -118,6 +118,33 @@ func TestSimNetGenesisBlock(t *testing.T) {
}
}
// TestSigNetGenesisBlock tests the genesis block of the signet test network for
// validity by checking the encoded bytes and hashes.
func TestSigNetGenesisBlock(t *testing.T) {
// Encode the genesis block to raw bytes.
var buf bytes.Buffer
err := SigNetParams.GenesisBlock.Serialize(&buf)
if err != nil {
t.Fatalf("TestSigNetGenesisBlock: %v", err)
}
// Ensure the encoded block matches the expected bytes.
if !bytes.Equal(buf.Bytes(), sigNetGenesisBlockBytes) {
t.Fatalf("TestSigNetGenesisBlock: Genesis block does not "+
"appear valid - got %v, want %v",
spew.Sdump(buf.Bytes()),
spew.Sdump(sigNetGenesisBlockBytes))
}
// Check hash of the block against expected hash.
hash := SigNetParams.GenesisBlock.BlockHash()
if !SigNetParams.GenesisHash.IsEqual(&hash) {
t.Fatalf("TestSigNetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash),
spew.Sdump(SigNetParams.GenesisHash))
}
}
// genesisBlockBytes are the wire encoded bytes for the genesis block of the
// main network as of protocol version 60002.
var genesisBlockBytes = []byte{
@ -281,3 +308,44 @@ var simNetGenesisBlockBytes = []byte{
0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, /* |.Lp+k.._|*/
0xac, 0x00, 0x00, 0x00, 0x00, /* |.....| */
}
// sigNetGenesisBlockBytes are the wire encoded bytes for the genesis block of
// the signet test network as of protocol version 70002.
var sigNetGenesisBlockBytes = []byte{
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |...@....| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x3b, 0xa3, 0xed, 0xfd, /* |........| */
0x7a, 0x7b, 0x12, 0xb2, 0x7a, 0xc7, 0x2c, 0x3e, /* |....;...| */
0x67, 0x76, 0x8f, 0x61, 0x7f, 0xc8, 0x1b, 0xc3, /* |z{..z.,>| */
0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, 0xb8, 0xaa, /* |gv.a....| */
0x4b, 0x1e, 0x5e, 0x4a, 0x00, 0x8f, 0x4d, 0x5f, /* |..Q2:...| */
0xae, 0x77, 0x03, 0x1e, 0x8a, 0xd2, 0x22, 0x03, /* |K.^J..M_| */
0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* |.w....".| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* |........| */
0xff, 0xff, 0x4d, 0x04, 0xff, 0xff, 0x00, 0x1d, /* |........| */
0x01, 0x04, 0x45, 0x54, 0x68, 0x65, 0x20, 0x54, /* |..M.....| */
0x69, 0x6d, 0x65, 0x73, 0x20, 0x30, 0x33, 0x2f, /* |..EThe T| */
0x4a, 0x61, 0x6e, 0x2f, 0x32, 0x30, 0x30, 0x39, /* |imes 03/| */
0x20, 0x43, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x6c, /* |Jan/2009| */
0x6c, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x20, 0x62, /* | Chancel| */
0x72, 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, /* |lor on b| */
0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x62, /* |rink of| */
0x61, 0x69, 0x6c, 0x6f, 0x75, 0x74, 0x20, 0x66, /* |second b| */
0x6f, 0x72, 0x20, 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |ailout f| */
0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf2, 0x05, /* |or banks| */
0x2a, 0x01, 0x00, 0x00, 0x00, 0x43, 0x41, 0x04, /* |........| */
0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, /* |*....CA.| */
0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7, 0x10, /* |g....UH'| */
0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, /* |.g..q0..| */
0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, 0xb6, /* |\..(.9..| */
0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, /* |yb...a..| */
0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, 0xde, /* |I..?L.8.| */
0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, /* |.U......| */
0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, /* |\8M....W| */
0xac, 0x00, 0x00, 0x00, 0x00, /* |.....| */
}

View file

@ -5,6 +5,8 @@
package chaincfg
import (
"encoding/binary"
"encoding/hex"
"errors"
"math"
"math/big"
@ -38,6 +40,30 @@ var (
// 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)
// sigNetPowLimit is the highest proof of work value a bitcoin block can
// have for the signet test network. It is the value 0x0377ae << 216.
sigNetPowLimit = new(big.Int).Lsh(new(big.Int).SetInt64(0x0377ae), 216)
// DefaultSignetChallenge is the byte representation of the signet
// challenge for the default (public, Taproot enabled) signet network.
// This is the binary equivalent of the bitcoin script
// 1 03ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430
// 0359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c4 2
// OP_CHECKMULTISIG
DefaultSignetChallenge, _ = hex.DecodeString(
"512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d" +
"1e086be430210359ef5021964fe22d6f8e05b2463c9540ce9688" +
"3fe3b278760f048f5189f2e6c452ae",
)
// DefaultSignetDNSSeeds is the list of seed nodes for the default
// (public, Taproot enabled) signet network.
DefaultSignetDNSSeeds = []DNSSeed{
{"178.128.221.177", false},
{"2a01:7c8:d005:390::5", false},
{"v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333", false},
}
)
// Checkpoint identifies a known good point in the block chain. Using
@ -96,6 +122,11 @@ const (
// includes the deployment of BIPS 141, 142, 144, 145, 147 and 173.
DeploymentSegwit
// DeploymentTaproot defines the rule change deployment ID for the
// Taproot (+Schnorr) soft-fork package. The taproot package includes
// the deployment of BIPS 340, 341 and 342.
DeploymentTaproot
// NOTE: DefinedDeployments must always come last since it is used to
// determine how many defined deployments there currently are.
@ -578,6 +609,107 @@ var SimNetParams = Params{
HDCoinType: 115, // ASCII for s
}
// SigNetParams defines the network parameters for the default public signet
// Bitcoin network. Not to be confused with the regression test network, this
// network is sometimes simply called "signet" or "taproot signet".
var SigNetParams = CustomSignetParams(
DefaultSignetChallenge, DefaultSignetDNSSeeds,
)
// CustomSignetParams creates network parameters for a custom signet network
// from a challenge. The challenge is the binary compiled version of the block
// challenge script.
func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params {
// The message start is defined as the first four bytes of the sha256d
// of the challenge script, as a single push (i.e. prefixed with the
// challenge script length).
challengeLength := byte(len(challenge))
hashDouble := chainhash.DoubleHashB(
append([]byte{challengeLength}, challenge...),
)
// We use little endian encoding of the hash prefix to be in line with
// the other wire network identities.
net := binary.LittleEndian.Uint32(hashDouble[0:4])
return Params{
Name: "signet",
Net: wire.BitcoinNet(net),
DefaultPort: "38333",
DNSSeeds: dnsSeeds,
// Chain parameters
GenesisBlock: &sigNetGenesisBlock,
GenesisHash: &sigNetGenesisHash,
PowLimit: sigNetPowLimit,
PowLimitBits: 0x1e0377ae,
BIP0034Height: 1,
BIP0065Height: 1,
BIP0066Height: 1,
CoinbaseMaturity: 100,
SubsidyReductionInterval: 210000,
TargetTimespan: time.Hour * 24 * 14, // 14 days
TargetTimePerBlock: time.Minute * 10, // 10 minutes
RetargetAdjustmentFactor: 4, // 25% less, 400% more
ReduceMinDifficulty: false,
MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2
GenerateSupported: false,
// Checkpoints ordered from oldest to newest.
Checkpoints: nil,
// Consensus rule change deployments.
//
// The miner confirmation window is defined as:
// target proof of work timespan / target proof of work spacing
RuleChangeActivationThreshold: 1916, // 95% of 2016
MinerConfirmationWindow: 2016,
Deployments: [DefinedDeployments]ConsensusDeployment{
DeploymentTestDummy: {
BitNumber: 28,
StartTime: 1199145601, // January 1, 2008 UTC
ExpireTime: 1230767999, // December 31, 2008 UTC
},
DeploymentCSV: {
BitNumber: 0,
StartTime: 0, // Always available for vote
ExpireTime: math.MaxInt64, // Never expires
},
DeploymentSegwit: {
BitNumber: 1,
StartTime: 0, // Always available for vote
ExpireTime: math.MaxInt64, // Never expires.
},
DeploymentTaproot: {
BitNumber: 2,
StartTime: 0, // Always available for vote
ExpireTime: math.MaxInt64, // Never expires.
},
},
// Mempool parameters
RelayNonStdTxs: false,
// Human-readable part for Bech32 encoded segwit addresses, as defined in
// BIP 173.
Bech32HRPSegwit: "tb", // always tb for test net
// Address encoding magics
PubKeyHashAddrID: 0x6f, // starts with m or n
ScriptHashAddrID: 0xc4, // starts with 2
WitnessPubKeyHashAddrID: 0x03, // starts with QW
WitnessScriptHashAddrID: 0x28, // starts with T7n
PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed)
// BIP32 hierarchical deterministic extended key magics
HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv
HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub
// BIP44 coin type used in the hierarchical deterministic path for
// address generation.
HDCoinType: 1,
}
}
var (
// ErrDuplicateNet describes an error where the parameters for a Bitcoin
// network could not be set due to the network already being a standard

View file

@ -6,6 +6,8 @@ package chaincfg
import (
"bytes"
"encoding/hex"
"math/big"
"testing"
)
@ -84,3 +86,50 @@ func TestInvalidHDKeyID(t *testing.T) {
t.Fatalf("HDPrivateKeyToPublicKeyID: want err ErrUnknownHDKeyID, got %v", err)
}
}
func TestSigNetPowLimit(t *testing.T) {
sigNetPowLimitHex, _ := hex.DecodeString(
"00000377ae000000000000000000000000000000000000000000000000000000",
)
powLimit := new(big.Int).SetBytes(sigNetPowLimitHex)
if sigNetPowLimit.Cmp(powLimit) != 0 {
t.Fatalf("Signet PoW limit bits (%s) not equal to big int (%s)",
sigNetPowLimit.Text(16), powLimit.Text(16))
}
if compactToBig(sigNetGenesisBlock.Header.Bits).Cmp(powLimit) != 0 {
t.Fatalf("Signet PoW limit header bits (%d) not equal to big "+
"int (%s)", sigNetGenesisBlock.Header.Bits,
powLimit.Text(16))
}
}
// compactToBig is a copy of the blockchain.CompactToBig function. We copy it
// here so we don't run into a circular dependency just because of a test.
func compactToBig(compact uint32) *big.Int {
// Extract the mantissa, sign bit, and exponent.
mantissa := compact & 0x007fffff
isNegative := compact&0x00800000 != 0
exponent := uint(compact >> 24)
// Since the base for the exponent is 256, the exponent can be treated
// as the number of bytes to represent the full 256-bit number. So,
// treat the exponent as the number of bytes and shift the mantissa
// right or left accordingly. This is equivalent to:
// N = mantissa * 256^(exponent-3)
var bn *big.Int
if exponent <= 3 {
mantissa >>= 8 * (3 - exponent)
bn = big.NewInt(int64(mantissa))
} else {
bn = big.NewInt(int64(mantissa))
bn.Lsh(bn, 8*(exponent-3))
}
// Make it negative if the sign bit is set.
if isNegative {
bn = bn.Neg(bn)
}
return bn
}

View file

@ -107,6 +107,7 @@ type config struct {
SimNet bool `long:"simnet" description:"Connect to the simulation test network"`
TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"`
TestNet3 bool `long:"testnet" description:"Connect to testnet"`
SigNet bool `long:"signet" description:"Connect to signet"`
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
Wallet bool `long:"wallet" description:"Connect to wallet"`
}
@ -138,6 +139,12 @@ func normalizeAddress(addr string, chain *chaincfg.Params, useWallet bool) (stri
} else {
defaultPort = "18334"
}
case &chaincfg.SigNetParams:
if useWallet {
defaultPort = "38332"
} else {
defaultPort = "38332"
}
default:
if useWallet {
defaultPort = "8332"
@ -273,6 +280,10 @@ func loadConfig() (*config, []string, error) {
numNets++
network = &chaincfg.RegressionNetParams
}
if cfg.SigNet {
numNets++
network = &chaincfg.SigNetParams
}
if numNets > 1 {
str := "%s: Multiple network params can't be used " +

View file

@ -8,6 +8,7 @@ import (
"bufio"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io"
@ -159,6 +160,9 @@ type config struct {
RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"`
SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
SimNet bool `long:"simnet" description:"Use the simulation test network"`
SigNet bool `long:"signet" description:"Use the signet test network"`
SigNetChallenge string `long:"signetchallenge" description:"Connect to a custom signet network defined by this challenge instead of using the global default signet test network -- Can be specified multiple times"`
SigNetSeedNode []string `long:"signetseednode" description:"Specify a seed node for the signet network instead of using the global default signet network seed nodes"`
TestNet3 bool `long:"testnet" description:"Use the test network"`
TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
TrickleInterval time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"`
@ -475,8 +479,8 @@ func loadConfig() (*config, []string, error) {
// Load additional config from file.
var configFileError error
parser := newConfigParser(&cfg, &serviceOpts, flags.Default)
if !(preCfg.RegressionTest || preCfg.SimNet) || preCfg.ConfigFile !=
defaultConfigFile {
if !(preCfg.RegressionTest || preCfg.SimNet || preCfg.SigNet) ||
preCfg.ConfigFile != defaultConfigFile {
if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) {
err := createDefaultConfigFile(preCfg.ConfigFile)
@ -550,9 +554,49 @@ func loadConfig() (*config, []string, error) {
activeNetParams = &simNetParams
cfg.DisableDNSSeed = true
}
if cfg.SigNet {
numNets++
activeNetParams = &sigNetParams
// Let the user overwrite the default signet parameters. The
// challenge defines the actual signet network to join and the
// seed nodes are needed for network discovery.
sigNetChallenge := chaincfg.DefaultSignetChallenge
sigNetSeeds := chaincfg.DefaultSignetDNSSeeds
if cfg.SigNetChallenge != "" {
challenge, err := hex.DecodeString(cfg.SigNetChallenge)
if err != nil {
str := "%s: Invalid signet challenge, hex " +
"decode failed: %v"
err := fmt.Errorf(str, funcName, err)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
sigNetChallenge = challenge
}
if len(cfg.SigNetSeedNode) > 0 {
sigNetSeeds = make(
[]chaincfg.DNSSeed, len(cfg.SigNetSeedNode),
)
for idx, seed := range cfg.SigNetSeedNode {
sigNetSeeds[idx] = chaincfg.DNSSeed{
Host: seed,
HasFiltering: false,
}
}
}
chainParams := chaincfg.CustomSignetParams(
sigNetChallenge, sigNetSeeds,
)
activeNetParams.Params = &chainParams
}
if numNets > 1 {
str := "%s: The testnet, regtest, segnet, and simnet params " +
"can't be used together -- choose one of the four"
str := "%s: The testnet, regtest, segnet, signet and simnet " +
"params can't be used together -- choose one of the " +
"five"
err := fmt.Errorf(str, funcName)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)

2
doc.go
View file

@ -72,7 +72,7 @@ Application Options:
minute (default: 15)
--listen= Add an interface/port to listen for connections
(default all interfaces port: 8333, testnet:
18333)
18333, signet: 38333)
--logdir= Directory to log output
--maxorphantx= Max number of orphan transactions to keep in
memory (default: 100)

View file

@ -55,6 +55,13 @@ var simNetParams = params{
rpcPort: "18556",
}
// sigNetParams contains parameters specific to the Signet network
// (wire.SigNet).
var sigNetParams = params{
Params: &chaincfg.SigNetParams,
rpcPort: "38332",
}
// 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

View file

@ -1256,6 +1256,9 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str
case chaincfg.DeploymentSegwit:
forkName = "segwit"
case chaincfg.DeploymentTaproot:
forkName = "taproot"
default:
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInternal.Code,