diff --git a/blockchain/stake/ticketdb_test.go b/blockchain/stake/ticketdb_test.go index 177c7ec7f1..7440a2d10d 100644 --- a/blockchain/stake/ticketdb_test.go +++ b/blockchain/stake/ticketdb_test.go @@ -270,3 +270,264 @@ func TestTicketDB(t *testing.T) { os.Remove("testdata/testtmdb") os.Remove("testdata") } + +// -------------------------------------------------------------------------------- +// TESTING VARIABLES BEGIN HERE + +// simNetPowLimit is the highest proof of work value a Decred block +// can have for the simulation test network. It is the value 2^255 - 1. +var simNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne) + +// SimNetParams defines the network parameters for the simulation test Decred +// 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 = &chaincfg.Params{ + Name: "simnet", + Net: wire.SimNet, + DefaultPort: "18555", + + // Chain parameters + GenesisBlock: &simNetGenesisBlock, + GenesisHash: &simNetGenesisHash, + CurrentBlockVersion: 0, + PowLimit: simNetPowLimit, + PowLimitBits: 0x207fffff, + ResetMinDifficulty: false, + GenerateSupported: true, + TimePerBlock: time.Second * 1, + WorkDiffAlpha: 1, + WorkDiffWindowSize: 8, + WorkDiffWindows: 4, + TargetTimespan: time.Second * 1 * 8, // TimePerBlock * WindowSize + RetargetAdjustmentFactor: 4, + + // Subsidy parameters. + BaseSubsidy: 50000000000, + MulSubsidy: 100, + DivSubsidy: 101, + ReductionInterval: 128, + WorkRewardProportion: 6, + StakeRewardProportion: 3, + BlockTaxProportion: 1, + + // Checkpoints ordered from oldest to newest. + Checkpoints: nil, + + // Mempool parameters + RelayNonStdTxs: true, + + // Address encoding magics + PubKeyAddrID: [2]byte{0x27, 0x6f}, // starts with Sk + PubKeyHashAddrID: [2]byte{0x0e, 0x91}, // starts with Ss + PKHEdwardsAddrID: [2]byte{0x0e, 0x71}, // starts with Se + PKHSchnorrAddrID: [2]byte{0x0e, 0x53}, // starts with SS + ScriptHashAddrID: [2]byte{0x0e, 0x6c}, // starts with Sc + PrivateKeyID: [2]byte{0x23, 0x07}, // starts with Ps + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x03}, // starts with sprv + HDPublicKeyID: [4]byte{0x04, 0x20, 0xbd, 0x3d}, // starts with spub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 115, // ASCII for s + + // Decred PoS parameters + MinimumStakeDiff: 20000, + TicketPoolSize: 64, + TicketsPerBlock: 5, + TicketMaturity: 16, + TicketExpiry: 256, // 4*TicketPoolSize + CoinbaseMaturity: 16, + SStxChangeMaturity: 1, + TicketPoolSizeWeight: 4, + StakeDiffAlpha: 1, + StakeDiffWindowSize: 8, + StakeDiffWindows: 8, + MaxFreshStakePerBlock: 40, // 8*TicketsPerBlock + StakeEnabledHeight: 16 + 16, // CoinbaseMaturity + TicketMaturity + StakeValidationHeight: 16 + (64 * 2), // CoinbaseMaturity + TicketPoolSize*2 + + // Decred organization related parameters + // + // "Dev org" address is a 3-of-3 P2SH going to wallet: + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // briefcase + // (seed 0x00000000000000000000000000000000000000000000000000000000000000) + // + // This same wallet owns the three ledger outputs for simnet. + // + // P2SH details for simnet dev org is below. + // + // address: Scc4ZC844nzuZCXsCFXUBXTLks2mD6psWom + // redeemScript: 532103e8c60c7336744c8dcc7b85c27789950fc52aa4e48f895ebbfb + // ac383ab893fc4c2103ff9afc246e0921e37d12e17d8296ca06a8f92a07fbe7857ed1d4 + // f0f5d94e988f21033ed09c7fa8b83ed53e6f2c57c5fa99ed2230c0d38edf53c0340d0f + // c2e79c725a53ae + // (3-of-3 multisig) + // Pubkeys used: + // SkQmxbeuEFDByPoTj41TtXat8tWySVuYUQpd4fuNNyUx51tF1csSs + // SkQn8ervNvAUEX5Ua3Lwjc6BAuTXRznDoDzsyxgjYqX58znY7w9e4 + // SkQkfkHZeBbMW8129tZ3KspEh1XBFC1btbkgzs6cjSyPbrgxzsKqk + // + OrganizationAddress: "ScuQxvveKGfpG1ypt6u27F99Anf7EW3cqhq", + BlockOneLedger: BlockOneLedgerSimNet, +} + +// BlockOneLedgerSimNet is the block one output ledger for the simulation +// network. See below under "Decred organization related parameters" for +// information on how to spend these outputs. +var BlockOneLedgerSimNet = []*chaincfg.TokenPayout{ + &chaincfg.TokenPayout{"Sshw6S86G2bV6W32cbc7EhtFy8f93rU6pae", 100000 * 1e8}, + &chaincfg.TokenPayout{"SsjXRK6Xz6CFuBt6PugBvrkdAa4xGbcZ18w", 100000 * 1e8}, + &chaincfg.TokenPayout{"SsfXiYkYkCoo31CuVQw428N6wWKus2ZEw5X", 100000 * 1e8}, +} + +var bigOne = new(big.Int).SetInt64(1) + +// simNetGenesisHash is the hash of the first block in the block chain for the +// simulation test network. +var simNetGenesisHash = simNetGenesisBlock.BlockSha() + +// simNetGenesisMerkleRoot is the hash of the first transaction in the genesis +// block for the simulation test network. It is the same as the merkle root for +// the main network. +var simNetGenesisMerkleRoot = genesisMerkleRoot + +// genesisCoinbaseTx legacy is the coinbase transaction for the genesis blocks for +// the regression test network and test network. +var genesisCoinbaseTxLegacy = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// genesisMerkleRoot is the hash of the first transaction in the genesis block +// for the main network. +var genesisMerkleRoot = genesisCoinbaseTxLegacy.TxSha() + +var regTestGenesisCoinbaseTx = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + Version: 0x0000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// simNetGenesisBlock defines the genesis block of the block chain which serves +// as the public transaction ledger for the simulation test network. +var simNetGenesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + MerkleRoot: simNetGenesisMerkleRoot, + StakeRoot: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + VoteBits: uint16(0x0000), + FinalState: [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Voters: uint16(0x0000), + FreshStake: uint8(0x00), + Revocations: uint8(0x00), + Timestamp: time.Unix(1401292357, 0), // 2009-01-08 20:54:25 -0600 CST + PoolSize: uint32(0), + Bits: 0x207fffff, // 545259519 + SBits: int64(0x0000000000000000), + Nonce: 0x00000000, + Height: uint32(0), + }, + Transactions: []*wire.MsgTx{®TestGenesisCoinbaseTx}, + STransactions: []*wire.MsgTx{}, +} diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index 5c670fbcdf..6ed4ace32a 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -1992,3 +1992,263 @@ func TestBlockValidationRules(t *testing.T) { "ErrDoubleSpend test 2: %v", err) } } + +// simNetPowLimit is the highest proof of work value a Decred block +// can have for the simulation test network. It is the value 2^255 - 1. +var simNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne) + +// SimNetParams defines the network parameters for the simulation test Decred +// 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 = &chaincfg.Params{ + Name: "simnet", + Net: wire.SimNet, + DefaultPort: "18555", + + // Chain parameters + GenesisBlock: &simNetGenesisBlock, + GenesisHash: &simNetGenesisHash, + CurrentBlockVersion: 0, + PowLimit: simNetPowLimit, + PowLimitBits: 0x207fffff, + ResetMinDifficulty: false, + GenerateSupported: true, + MaximumBlockSize: 1000000, + TimePerBlock: time.Second * 1, + WorkDiffAlpha: 1, + WorkDiffWindowSize: 8, + WorkDiffWindows: 4, + TargetTimespan: time.Second * 1 * 8, // TimePerBlock * WindowSize + RetargetAdjustmentFactor: 4, + + // Subsidy parameters. + BaseSubsidy: 50000000000, + MulSubsidy: 100, + DivSubsidy: 101, + ReductionInterval: 128, + WorkRewardProportion: 6, + StakeRewardProportion: 3, + BlockTaxProportion: 1, + + // Checkpoints ordered from oldest to newest. + Checkpoints: nil, + + // Mempool parameters + RelayNonStdTxs: true, + + // Address encoding magics + PubKeyAddrID: [2]byte{0x27, 0x6f}, // starts with Sk + PubKeyHashAddrID: [2]byte{0x0e, 0x91}, // starts with Ss + PKHEdwardsAddrID: [2]byte{0x0e, 0x71}, // starts with Se + PKHSchnorrAddrID: [2]byte{0x0e, 0x53}, // starts with SS + ScriptHashAddrID: [2]byte{0x0e, 0x6c}, // starts with Sc + PrivateKeyID: [2]byte{0x23, 0x07}, // starts with Ps + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x03}, // starts with sprv + HDPublicKeyID: [4]byte{0x04, 0x20, 0xbd, 0x3d}, // starts with spub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 115, // ASCII for s + + // Decred PoS parameters + MinimumStakeDiff: 20000, + TicketPoolSize: 64, + TicketsPerBlock: 5, + TicketMaturity: 16, + TicketExpiry: 256, // 4*TicketPoolSize + CoinbaseMaturity: 16, + SStxChangeMaturity: 1, + TicketPoolSizeWeight: 4, + StakeDiffAlpha: 1, + StakeDiffWindowSize: 8, + StakeDiffWindows: 8, + MaxFreshStakePerBlock: 40, // 8*TicketsPerBlock + StakeEnabledHeight: 16 + 16, // CoinbaseMaturity + TicketMaturity + StakeValidationHeight: 16 + (64 * 2), // CoinbaseMaturity + TicketPoolSize*2 + StakeBaseSigScript: []byte{0xDE, 0xAD, 0xBE, 0xEF}, + + // Decred organization related parameters + // + // "Dev org" address is a 3-of-3 P2SH going to wallet: + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // briefcase + // (seed 0x00000000000000000000000000000000000000000000000000000000000000) + // + // This same wallet owns the three ledger outputs for simnet. + // + // P2SH details for simnet dev org is below. + // + // address: Scc4ZC844nzuZCXsCFXUBXTLks2mD6psWom + // redeemScript: 532103e8c60c7336744c8dcc7b85c27789950fc52aa4e48f895ebbfb + // ac383ab893fc4c2103ff9afc246e0921e37d12e17d8296ca06a8f92a07fbe7857ed1d4 + // f0f5d94e988f21033ed09c7fa8b83ed53e6f2c57c5fa99ed2230c0d38edf53c0340d0f + // c2e79c725a53ae + // (3-of-3 multisig) + // Pubkeys used: + // SkQmxbeuEFDByPoTj41TtXat8tWySVuYUQpd4fuNNyUx51tF1csSs + // SkQn8ervNvAUEX5Ua3Lwjc6BAuTXRznDoDzsyxgjYqX58znY7w9e4 + // SkQkfkHZeBbMW8129tZ3KspEh1XBFC1btbkgzs6cjSyPbrgxzsKqk + // + OrganizationAddress: "ScuQxvveKGfpG1ypt6u27F99Anf7EW3cqhq", + BlockOneLedger: BlockOneLedgerSimNet, +} + +// BlockOneLedgerSimNet is the block one output ledger for the simulation +// network. See below under "Decred organization related parameters" for +// information on how to spend these outputs. +var BlockOneLedgerSimNet = []*chaincfg.TokenPayout{ + &chaincfg.TokenPayout{"Sshw6S86G2bV6W32cbc7EhtFy8f93rU6pae", 100000 * 1e8}, + &chaincfg.TokenPayout{"SsjXRK6Xz6CFuBt6PugBvrkdAa4xGbcZ18w", 100000 * 1e8}, + &chaincfg.TokenPayout{"SsfXiYkYkCoo31CuVQw428N6wWKus2ZEw5X", 100000 * 1e8}, +} + +var bigOne = new(big.Int).SetInt64(1) + +// simNetGenesisHash is the hash of the first block in the block chain for the +// simulation test network. +var simNetGenesisHash = simNetGenesisBlock.BlockSha() + +// simNetGenesisMerkleRoot is the hash of the first transaction in the genesis +// block for the simulation test network. It is the same as the merkle root for +// the main network. +var simNetGenesisMerkleRoot = genesisMerkleRoot + +// genesisCoinbaseTx legacy is the coinbase transaction for the genesis blocks for +// the regression test network and test network. +var genesisCoinbaseTxLegacy = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// genesisMerkleRoot is the hash of the first transaction in the genesis block +// for the main network. +var genesisMerkleRoot = genesisCoinbaseTxLegacy.TxSha() + +var regTestGenesisCoinbaseTx = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + Version: 0x0000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// simNetGenesisBlock defines the genesis block of the block chain which serves +// as the public transaction ledger for the simulation test network. +var simNetGenesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + MerkleRoot: simNetGenesisMerkleRoot, + StakeRoot: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + VoteBits: uint16(0x0000), + FinalState: [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Voters: uint16(0x0000), + FreshStake: uint8(0x00), + Revocations: uint8(0x00), + Timestamp: time.Unix(1401292357, 0), // 2009-01-08 20:54:25 -0600 CST + PoolSize: uint32(0), + Bits: 0x207fffff, // 545259519 + SBits: int64(0x0000000000000000), + Nonce: 0x00000000, + Height: uint32(0), + }, + Transactions: []*wire.MsgTx{®TestGenesisCoinbaseTx}, + STransactions: []*wire.MsgTx{}, +} diff --git a/chaincfg/genesis.go b/chaincfg/genesis.go index 2162a1985d..56af85e1bd 100644 --- a/chaincfg/genesis.go +++ b/chaincfg/genesis.go @@ -11,3 +11,236 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/wire" ) + +// MainNet ------------------------------------------------------------------------ + +// genesisCoinbaseTx is the coinbase transaction for the genesis blocks for +// the main network. +var genesisCoinbaseTx = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + // Fully null. + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + Tree: 0, + }, + SignatureScript: []byte{ + 0x00, 0x00, + }, + Sequence: 0xffffffff, + BlockHeight: wire.NullBlockHeight, + BlockIndex: wire.NullBlockIndex, + ValueIn: wire.NullValueIn, + }, + }, + TxOut: []*wire.TxOut{ + { + Version: 0x0000, + Value: 0x00000000, + PkScript: []byte{ + 0x80, 0x16, 0x79, 0xe9, 0x85, 0x61, 0xad, 0xa9, + 0x6c, 0xae, 0xc2, 0x94, 0x9a, 0x5d, 0x41, 0xc4, + 0xca, 0xb3, 0x85, 0x1e, 0xb7, 0x40, 0xd9, 0x51, + 0xc1, 0x0e, 0xcb, 0xcf, 0x26, 0x5c, 0x1f, 0xd9, + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// genesisMerkleRoot is the hash of the first transaction in the genesis block +// for the main network. +var genesisMerkleRoot = genesisCoinbaseTx.TxShaFull() + +// genesisBlock defines the genesis block of the block chain which serves as the +// public transaction ledger for the main network. +// +// The genesis block for Decred mainnet, testnet, and simnet are not evaluated +// for proof of work. The only values that are ever used elsewhere in the +// blockchain from it are: +// (1) The genesis block hash is used as the PrevBlock in params.go. +// (2) The difficulty starts off at the value given by bits. +// (3) The stake difficulty starts off at the value given by SBits. +// (4) The timestamp, which guides when blocks can be built on top of it +// and what the initial difficulty calculations come out to be. +// +// The genesis block is valid by definition and none of the fields within +// it are validated for correctness. +var genesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash{}, + MerkleRoot: genesisMerkleRoot, + StakeRoot: chainhash.Hash{}, + Timestamp: time.Unix(1454954400, 0), // Mon, 08 Feb 2016 18:00:00 GMT + Bits: 0x1b01ffff, // Difficulty 32767 + SBits: 2 * 1e8, // 2 Coin + Nonce: 0x00000000, + }, + Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, +} + +// genesisHash is the hash of the first block in the block chain for the main +// network (genesis block). +var genesisHash = genesisBlock.BlockSha() + +// TestNet ------------------------------------------------------------------------ + +// genesisCoinbaseTxLegacy is the coinbase transaction for the genesis block for +// the test network. +var genesisCoinbaseTxLegacy = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// testNetGenesisMerkleRoot is the hash of the first transaction in the genesis block +// for the test network. +var testNetGenesisMerkleRoot = genesisCoinbaseTxLegacy.TxSha() + +// testNetGenesisBlock defines the genesis block of the block chain which +// serves as the public transaction ledger for the test network (version 3). +var testNetGenesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash{}, + MerkleRoot: testNetGenesisMerkleRoot, + Timestamp: time.Unix(1453908222, 0), // 2016-01-27 TestNet9 + Bits: 0x1e00ffff, + SBits: 20000000, + Nonce: 0x18aea41a, + }, + Transactions: []*wire.MsgTx{&genesisCoinbaseTxLegacy}, +} + +// testNetGenesisHash is the hash of the first block in the block chain for the +// test network. +var testNetGenesisHash = testNetGenesisBlock.BlockSha() + +// SimNet ------------------------------------------------------------------------- + +var regTestGenesisCoinbaseTx = wire.MsgTx{ + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */ + 0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */ + 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */ + 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */ + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */ + 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, 0x69, 0x6e, /* | on brin| */ + 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, /* |k of sec|*/ + 0x6f, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, /* |ond bail| */ + 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, /* |out for |*/ + 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |banks| */ + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x00000000, + PkScript: []byte{ + 0x41, 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, /* |A.g....U| */ + 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, /* |H'.g..q0| */ + 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, /* |..\..(.9| */ + 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */ + 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */ + 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */ + 0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */ + 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */ + 0x1d, 0x5f, 0xac, /* |._.| */ + }, + }, + }, + LockTime: 0, + Expiry: 0, +} + +// simNetGenesisMerkleRoot is the hash of the first transaction in the genesis +// block for the simulation test network. It is the same as the merkle root for +// the main network. +var simNetGenesisMerkleRoot = genesisMerkleRoot + +// simNetGenesisBlock defines the genesis block of the block chain which serves +// as the public transaction ledger for the simulation test network. +var simNetGenesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + MerkleRoot: simNetGenesisMerkleRoot, + StakeRoot: chainhash.Hash([chainhash.HashSize]byte{ // Make go vet happy. + 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, + }), + VoteBits: uint16(0x0000), + FinalState: [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + Voters: uint16(0x0000), + FreshStake: uint8(0x00), + Revocations: uint8(0x00), + Timestamp: time.Unix(1401292357, 0), // 2009-01-08 20:54:25 -0600 CST + PoolSize: uint32(0), + Bits: 0x207fffff, // 545259519 + SBits: int64(0x0000000000000000), + Nonce: 0x00000000, + Height: uint32(0), + }, + Transactions: []*wire.MsgTx{®TestGenesisCoinbaseTx}, + STransactions: []*wire.MsgTx{}, +} + +// simNetGenesisHash is the hash of the first block in the block chain for the +// simulation test network. +var simNetGenesisHash = simNetGenesisBlock.BlockSha() diff --git a/chaincfg/genesis_test.go b/chaincfg/genesis_test.go index 032b610634..6a549623c3 100644 --- a/chaincfg/genesis_test.go +++ b/chaincfg/genesis_test.go @@ -13,3 +13,125 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/decred/dcrd/chaincfg" ) + +// TestGenesisBlock tests the genesis block of the main network for validity by +// checking the encoded bytes and hashes. +func TestGenesisBlock(t *testing.T) { + + genesisBlockBytes, _ := hex.DecodeString("0100000000000000000000000000" + + "000000000000000000000000000000000000000000000dc101dfc3c6a2eb10ca0" + + "c5374e10d28feb53f7eabcc850511ceadb99174aa660000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000" + + "000000000ffff011b00c2eb0b000000000000000000000000a0d7b85600000000" + + "00000000000000000000000000000000000000000000000000000000000000000" + + "00000000101000000010000000000000000000000000000000000000000000000" + + "000000000000000000ffffffff00ffffffff01000000000000000000002080167" + + "9e98561ada96caec2949a5d41c4cab3851eb740d951c10ecbcf265c1fd9000000" + + "000000000001ffffffffffffffff00000000ffffffff02000000") + + // Encode the genesis block to raw bytes. + var buf bytes.Buffer + err := chaincfg.MainNetParams.GenesisBlock.Serialize(&buf) + if err != nil { + t.Fatalf("TestGenesisBlock: %v", err) + } + + // Ensure the encoded block matches the expected bytes. + if !bytes.Equal(buf.Bytes(), genesisBlockBytes) { + t.Fatalf("TestGenesisBlock: Genesis block does not appear valid - "+ + "got %v, want %v", spew.Sdump(buf.Bytes()), + spew.Sdump(genesisBlockBytes)) + } + + // Check hash of the block against expected hash. + hash := chaincfg.MainNetParams.GenesisBlock.BlockSha() + if !chaincfg.MainNetParams.GenesisHash.IsEqual(&hash) { + t.Fatalf("TestGenesisBlock: Genesis block hash does not "+ + "appear valid - got %v, want %v", spew.Sdump(hash), + spew.Sdump(chaincfg.MainNetParams.GenesisHash)) + } +} + +// TestTestNetGenesisBlock tests the genesis block of the test network (version +// 9) for validity by checking the encoded bytes and hashes. +func TestTestNetGenesisBlock(t *testing.T) { + // Encode the genesis block to raw bytes. + var buf bytes.Buffer + err := chaincfg.TestNetParams.GenesisBlock.Serialize(&buf) + if err != nil { + t.Fatalf("TestTestNetGenesisBlock: %v", err) + } + + testNetGenesisBlockBytes, _ := hex.DecodeString("0100000000000000000" + + "000000000000000000000000000000000000000000000000000000571a3f8bb" + + "1903091a18edd3efbc324c79876764af2424071a480d3f04ea16a2000000000" + + "000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000ffff001e002d310100000000000000000000000" + + "0fee0a8561aa4ae180000000000000000000000000000000000000000000000" + + "000000000000000000000000000101000000010000000000000000000000000" + + "000000000000000000000000000000000000000ffffffff00ffffffff010000" + + "0000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e" + + "03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7" + + "ba0b8d578a4c702b6bf11d5fac0000000000000000010000000000000000000" + + "00000000000004d04ffff001d0104455468652054696d65732030332f4a616e" + + "2f32303039204368616e63656c6c6f72206f6e206272696e6b206f662073656" + + "36f6e64206261696c6f757420666f722062616e6b7300") + + // Ensure the encoded block matches the expected bytes. + if !bytes.Equal(buf.Bytes(), testNetGenesisBlockBytes) { + t.Fatalf("TestTestNetGenesisBlock: Genesis block does not "+ + "appear valid - got %v, want %v", + spew.Sdump(buf.Bytes()), + spew.Sdump(testNetGenesisBlockBytes)) + } + + // Check hash of the block against expected hash. + hash := chaincfg.TestNetParams.GenesisBlock.BlockSha() + if !chaincfg.TestNetParams.GenesisHash.IsEqual(&hash) { + t.Fatalf("TestTestNetGenesisBlock: Genesis block hash does "+ + "not appear valid - got %v, want %v", spew.Sdump(hash), + spew.Sdump(chaincfg.TestNetParams.GenesisHash)) + } +} + +// TestSimNetGenesisBlock tests the genesis block of the simulation test network +// for validity by checking the encoded bytes and hashes. +func TestSimNetGenesisBlock(t *testing.T) { + // Encode the genesis block to raw bytes. + var buf bytes.Buffer + err := chaincfg.SimNetParams.GenesisBlock.Serialize(&buf) + if err != nil { + t.Fatalf("TestSimNetGenesisBlock: %v", err) + } + + simNetGenesisBlockBytes, _ := hex.DecodeString("0100000000000000000" + + "000000000000000000000000000000000000000000000000000000dc101dfc" + + "3c6a2eb10ca0c5374e10d28feb53f7eabcc850511ceadb99174aa660000000" + + "00000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000ffff7f20000000000000000000000000000" + + "00000450686530000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000101000000010000000000000000000" + + "000000000000000000000000000000000000000000000ffffffff00fffffff" + + "f0100000000000000000000434104678afdb0fe5548271967f1a67130b7105" + + "cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112d" + + "e5c384df7ba0b8d578a4c702b6bf11d5fac000000000000000001000000000" + + "000000000000000000000004d04ffff001d0104455468652054696d6573203" + + "0332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b2" + + "06f66207365636f6e64206261696c6f757420666f722062616e6b7300") + + // Ensure the encoded block matches the expected bytes. + if !bytes.Equal(buf.Bytes(), simNetGenesisBlockBytes) { + t.Fatalf("TestSimNetGenesisBlock: Genesis block does not "+ + "appear valid - got %v, want %v", + spew.Sdump(buf.Bytes()), + spew.Sdump(simNetGenesisBlockBytes)) + } + + // Check hash of the block against expected hash. + hash := chaincfg.SimNetParams.GenesisBlock.BlockSha() + if !chaincfg.SimNetParams.GenesisHash.IsEqual(&hash) { + t.Fatalf("TestSimNetGenesisBlock: Genesis block hash does "+ + "not appear valid - got %v, want %v", spew.Sdump(hash), + spew.Sdump(chaincfg.SimNetParams.GenesisHash)) + } +} diff --git a/chaincfg/params.go b/chaincfg/params.go index 4ad5073904..6f53a9b3de 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -13,3 +13,693 @@ import ( "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/wire" ) + +// 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 Decred 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) + + // testNetPowLimit is the highest proof of work value a Decred block + // can have for the test network. It is the value 2^232 - 1. + testNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 232), bigOne) + + // simNetPowLimit is the highest proof of work value a Decred 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) +) + +// SigHashOptimization is an optimization for verification of transactions that +// do CHECKSIG operations with hashType SIGHASH_ALL. Although there should be no +// consequences to daemons that are simply running a node, it may be the case +// that you could cause database corruption if you turn this code on, create and +// manipulate your own MsgTx, then include them in blocks. For safety, if you're +// using the daemon with wallet or mining with the daemon this should be disabled. +// If you believe that any MsgTxs in your daemon will be used mutably, do NOT +// turn on this feature. It is disabled by default. +// This feature is considered EXPERIMENTAL, enable at your own risk! +var SigHashOptimization = false + +// CPUMinerThreads is the default number of threads to utilize with the +// CPUMiner when mining. +var CPUMinerThreads = 1 + +// 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 chain.IsCheckpointCandidate for details on the selection +// criteria. +type Checkpoint struct { + Height int64 + Hash *chainhash.Hash +} + +// TokenPayout is a payout for block 1 which specifies an address and an amount +// to pay to that address in a transaction output. +type TokenPayout struct { + Address string + Amount int64 +} + +// Params defines a Decred network by its parameters. These parameters may be +// used by Decred 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 wire.CurrencyNet + DefaultPort string + + // Starting block for the network (block 0). + GenesisBlock *wire.MsgBlock + + // Starting block hash. + GenesisHash *chainhash.Hash + + // The version of the block that the majority of the network is currently + // on. + CurrentBlockVersion int32 + + // Maximum value for nbits (minimum Proof of Work) as a uint256. + PowLimit *big.Int + + // Maximum value for nbits (minimum Proof of Work) in compact form. + PowLimitBits uint32 + + // Testnet difficulty reset flag. + ResetMinDifficulty bool + + // MinDiffResetTimeFactor is the amount to multiply TimePerBlock by to + // reset the difficulty to the minimum network factor. + MinDiffResetTimeFactor time.Duration + + // GenerateSupported specifies whether or not CPU mining is allowed. + GenerateSupported bool + + // MaximumBlockSize is the maximum size of a block that can be generated + // on the network. + MaximumBlockSize int + + // TimePerBlock is the desired amount of time to generate each block in + // minutes. + TimePerBlock time.Duration + + // WorkDiffAlpha is the stake difficulty EMA calculation alpha (smoothing) + // value. It is different from a normal EMA alpha. Closer to 1 --> smoother. + WorkDiffAlpha int64 + + // WorkDiffWindowSize is the number of windows (intervals) used for calculation + // of the exponentially weighted average. + WorkDiffWindowSize int64 + + // WorkDiffWindows is the number of windows (intervals) used for calculation + // of the exponentially weighted average. + WorkDiffWindows int64 + + // targetTimespan is the desired amount of time that should elapse + // before block difficulty requirement is examined to determine how + // it should be changed in order to maintain the desired block + // generation rate. This value should correspond to the product of + // WorkDiffWindowSize and TimePerBlock above. + TargetTimespan time.Duration + + // RetargetAdjustmentFactor is the adjustment factor used to limit + // the minimum and maximum amount of adjustment that can occur between + // difficulty retargets. + RetargetAdjustmentFactor int64 + + // Subsidy parameters. + // + // Subsidy calculation for exponential reductions: + // 0 for i in range (0, height / ReductionInterval): + // 1 subsidy *= MulSubsidy + // 2 subsidy /= DivSubsidy + // + // Caveat: Don't overflow the int64 register!! + + // BaseSubsidy is the starting subsidy amount for mined blocks. + BaseSubsidy int64 + + // Subsidy reduction multiplier. + MulSubsidy int64 + + // Subsidy reduction divisor. + DivSubsidy int64 + + // Reduction interval in blocks. + ReductionInterval int64 + + // WorkRewardProportion is the comparative amount of the subsidy given for + // creating a block. + WorkRewardProportion uint16 + + // StakeRewardProportion is the comparative amount of the subsidy given for + // casting stake votes (collectively, per block). + StakeRewardProportion uint16 + + // BlockTaxProportion is the inverse of the percentage of funds for each + // block to allocate to the developer organization. + // e.g. 10% --> 10 (or 1 / (1/10)) + // Special case: disable taxes with a value of 0 + BlockTaxProportion uint16 + + // Checkpoints ordered from oldest to newest. + Checkpoints []Checkpoint + + // Mempool parameters + RelayNonStdTxs bool + + // NetworkAddressPrefix is the first letter of the network + // for any given address encoded as a string. + NetworkAddressPrefix string + + // Address encoding magics + PubKeyAddrID [2]byte // First 2 bytes of a P2PK address + PubKeyHashAddrID [2]byte // First 2 bytes of a P2PKH address + PKHEdwardsAddrID [2]byte // First 2 bytes of an Edwards P2PKH address + PKHSchnorrAddrID [2]byte // First 2 bytes of a secp256k1 Schnorr P2PKH address + ScriptHashAddrID [2]byte // First 2 bytes of a P2SH address + PrivateKeyID [2]byte // First 2 bytes of a WIF private key + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID [4]byte + HDPublicKeyID [4]byte + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType uint32 + + // MinimumStakeDiff if the minimum amount of Atoms required to purchase a + // stake ticket. + MinimumStakeDiff int64 + + // Ticket pool sizes for Decred PoS. This denotes the number of possible + // buckets/number of different ticket numbers. It is also the number of + // possible winner numbers there are. + TicketPoolSize uint16 + + // Average number of tickets per block for Decred PoS. + TicketsPerBlock uint16 + + // Number of blocks for tickets to mature (spendable at TicketMaturity+1). + TicketMaturity uint16 + + // Number of blocks for tickets to expire after they have matured. This MUST + // be >= (StakeEnabledHeight + StakeValidationHeight). + TicketExpiry uint32 + + // Maturity for spending coinbase tx. + CoinbaseMaturity uint16 + + // Maturity for spending SStx change outputs. + SStxChangeMaturity uint16 + + // TicketPoolSizeWeight is the multiplicative weight applied to the + // ticket pool size difference between a window period and its target + // when determining the stake system. + TicketPoolSizeWeight uint16 + + // StakeDiffAlpha is the stake difficulty EMA calculation alpha (smoothing) + // value. It is different from a normal EMA alpha. Closer to 1 --> smoother. + StakeDiffAlpha int64 + + // StakeDiffWindowSize is the number of blocks used for each interval in + // exponentially weighted average. + StakeDiffWindowSize int64 + + // StakeDiffWindows is the number of windows (intervals) used for calculation + // of the exponentially weighted average. + StakeDiffWindows int64 + + // MaxFreshStakePerBlock is the maximum number of new tickets that may be + // submitted per block. + MaxFreshStakePerBlock uint8 + + // StakeEnabledHeight is the height in which the first ticket could possibly + // mature. + StakeEnabledHeight int64 + + // StakeValidationHeight is the height at which votes (SSGen) are required + // to add a new block to the top of the blockchain. This height is the + // first block that will be voted on, but will include in itself no votes. + StakeValidationHeight int64 + + // StakeBaseSigScript is the consensus stakebase signature script for all + // votes on the network. This isn't signed in any way, so without forcing + // it to be this value miners/daemons could freely change it. + StakeBaseSigScript []byte + + // OrganizationAddress is the static address for block taxes to be + // distributed to in every block's coinbase. It should ideally be + // a P2SH multisignature address. + OrganizationAddress string + + // BlockOneLedger specifies the list of payouts in the coinbase of + // block height 1. If there are no payouts to be given, set this + // to an empty slice. + BlockOneLedger []*TokenPayout +} + +// MainNetParams defines the network parameters for the main Decred network. +var MainNetParams = Params{ + Name: "mainnet", + Net: wire.MainNet, + DefaultPort: "9108", + + // Chain parameters + GenesisBlock: &genesisBlock, + GenesisHash: &genesisHash, + CurrentBlockVersion: 1, + PowLimit: mainPowLimit, + PowLimitBits: 0x1d00ffff, + ResetMinDifficulty: false, + MinDiffResetTimeFactor: 0x7FFFFFFF, + GenerateSupported: false, + MaximumBlockSize: 393216, + TimePerBlock: time.Minute * 5, + WorkDiffAlpha: 1, + WorkDiffWindowSize: 144, + WorkDiffWindows: 20, + TargetTimespan: time.Minute * 5 * 144, // TimePerBlock * WindowSize + RetargetAdjustmentFactor: 4, + + // Subsidy parameters. + BaseSubsidy: 3119582664, // 21m + MulSubsidy: 100, + DivSubsidy: 101, + ReductionInterval: 6144, + WorkRewardProportion: 6, + StakeRewardProportion: 3, + BlockTaxProportion: 1, + + // Checkpoints ordered from oldest to newest. + Checkpoints: []Checkpoint{}, + + // Mempool parameters + RelayNonStdTxs: false, + + // Address encoding magics + NetworkAddressPrefix: "D", + PubKeyAddrID: [2]byte{0x13, 0x86}, // starts with Dk + PubKeyHashAddrID: [2]byte{0x07, 0x3f}, // starts with Ds + PKHEdwardsAddrID: [2]byte{0x07, 0x1f}, // starts with De + PKHSchnorrAddrID: [2]byte{0x07, 0x01}, // starts with DS + ScriptHashAddrID: [2]byte{0x07, 0x1a}, // starts with Dc + PrivateKeyID: [2]byte{0x22, 0xde}, // starts with Pm + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x02, 0xfd, 0xa4, 0xe8}, // starts with dprv + HDPublicKeyID: [4]byte{0x02, 0xfd, 0xa9, 0x26}, // starts with dpub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 20, + + // Decred PoS parameters + MinimumStakeDiff: 2 * 1e8, // 2 Coin + TicketPoolSize: 8192, + TicketsPerBlock: 5, + TicketMaturity: 256, + TicketExpiry: 40960, // 5*TicketPoolSize + CoinbaseMaturity: 256, + SStxChangeMaturity: 1, + TicketPoolSizeWeight: 4, + StakeDiffAlpha: 1, // Minimal + StakeDiffWindowSize: 144, + StakeDiffWindows: 20, + MaxFreshStakePerBlock: 20, // 4*TicketsPerBlock + StakeEnabledHeight: 256 + 256, // CoinbaseMaturity + TicketMaturity + StakeValidationHeight: 4096, // ~14 days + StakeBaseSigScript: []byte{0x00, 0x00}, + + // Decred organization related parameters + OrganizationAddress: "Dcur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx", + BlockOneLedger: BlockOneLedgerMainNet, +} + +// TestNetParams defines the network parameters for the test currency network. +// This network is sometimes simply called "testnet". +var TestNetParams = Params{ + Name: "testnet", + Net: wire.TestNet, + DefaultPort: "19108", + + // Chain parameters + GenesisBlock: &testNetGenesisBlock, + GenesisHash: &testNetGenesisHash, + CurrentBlockVersion: 0, + PowLimit: testNetPowLimit, + PowLimitBits: 0x1e00ffff, + ResetMinDifficulty: false, + MinDiffResetTimeFactor: 0x7FFFFFFF, + GenerateSupported: true, + MaximumBlockSize: 1000000, + TimePerBlock: time.Minute * 2, + WorkDiffAlpha: 1, + WorkDiffWindowSize: 144, + WorkDiffWindows: 20, + TargetTimespan: time.Minute * 2 * 144, // TimePerBlock * WindowSize + RetargetAdjustmentFactor: 4, + + // Subsidy parameters. + BaseSubsidy: 2500000000, // 25 Coin + MulSubsidy: 100, + DivSubsidy: 101, + ReductionInterval: 2048, + WorkRewardProportion: 6, + StakeRewardProportion: 3, + BlockTaxProportion: 1, + + // Checkpoints ordered from oldest to newest. + Checkpoints: []Checkpoint{}, + + // Mempool parameters + RelayNonStdTxs: true, + + // Address encoding magics + NetworkAddressPrefix: "T", + PubKeyAddrID: [2]byte{0x28, 0xf7}, // starts with Tk + PubKeyHashAddrID: [2]byte{0x0f, 0x21}, // starts with Ts + PKHEdwardsAddrID: [2]byte{0x0f, 0x01}, // starts with Te + PKHSchnorrAddrID: [2]byte{0x0e, 0xe3}, // starts with TS + ScriptHashAddrID: [2]byte{0x0e, 0xfc}, // starts with Tc + PrivateKeyID: [2]byte{0x23, 0x0e}, // starts with Pt + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x97}, // starts with tprv + HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xd1}, // starts with tpub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 11, + + // Decred PoS parameters + MinimumStakeDiff: 20000000, // 0.2 Coin + TicketPoolSize: 1024, + TicketsPerBlock: 5, + TicketMaturity: 16, + TicketExpiry: 6144, // 6*TicketPoolSize + CoinbaseMaturity: 16, + SStxChangeMaturity: 1, + TicketPoolSizeWeight: 4, + StakeDiffAlpha: 1, + StakeDiffWindowSize: 144, + StakeDiffWindows: 20, + MaxFreshStakePerBlock: 20, // 4*TicketsPerBlock + StakeEnabledHeight: 16 + 16, // CoinbaseMaturity + TicketMaturity + StakeValidationHeight: 768, // Arbitrary + StakeBaseSigScript: []byte{0xDE, 0xAD, 0xBE, 0xEF}, + + // Decred organization related parameters + OrganizationAddress: "TcemyEtyHSg9L7jww7uihv9BJfKL6YGiZYn", + BlockOneLedger: BlockOneLedgerTestNet, +} + +// SimNetParams defines the network parameters for the simulation test Decred +// 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: wire.SimNet, + DefaultPort: "18555", + + // Chain parameters + GenesisBlock: &simNetGenesisBlock, + GenesisHash: &simNetGenesisHash, + CurrentBlockVersion: 0, + PowLimit: simNetPowLimit, + PowLimitBits: 0x207fffff, + ResetMinDifficulty: false, + MinDiffResetTimeFactor: 0x7FFFFFFF, + GenerateSupported: true, + MaximumBlockSize: 1000000, + TimePerBlock: time.Second * 1, + WorkDiffAlpha: 1, + WorkDiffWindowSize: 8, + WorkDiffWindows: 4, + TargetTimespan: time.Second * 1 * 8, // TimePerBlock * WindowSize + RetargetAdjustmentFactor: 4, + + // Subsidy parameters. + BaseSubsidy: 50000000000, + MulSubsidy: 100, + DivSubsidy: 101, + ReductionInterval: 128, + WorkRewardProportion: 6, + StakeRewardProportion: 3, + BlockTaxProportion: 1, + + // Checkpoints ordered from oldest to newest. + Checkpoints: nil, + + // Mempool parameters + RelayNonStdTxs: true, + + // Address encoding magics + NetworkAddressPrefix: "S", + PubKeyAddrID: [2]byte{0x27, 0x6f}, // starts with Sk + PubKeyHashAddrID: [2]byte{0x0e, 0x91}, // starts with Ss + PKHEdwardsAddrID: [2]byte{0x0e, 0x71}, // starts with Se + PKHSchnorrAddrID: [2]byte{0x0e, 0x53}, // starts with SS + ScriptHashAddrID: [2]byte{0x0e, 0x6c}, // starts with Sc + PrivateKeyID: [2]byte{0x23, 0x07}, // starts with Ps + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x03}, // starts with sprv + HDPublicKeyID: [4]byte{0x04, 0x20, 0xbd, 0x3d}, // starts with spub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 115, // ASCII for s + + // Decred PoS parameters + MinimumStakeDiff: 20000, + TicketPoolSize: 64, + TicketsPerBlock: 5, + TicketMaturity: 16, + TicketExpiry: 384, // 6*TicketPoolSize + CoinbaseMaturity: 16, + SStxChangeMaturity: 1, + TicketPoolSizeWeight: 4, + StakeDiffAlpha: 1, + StakeDiffWindowSize: 8, + StakeDiffWindows: 8, + MaxFreshStakePerBlock: 20, // 4*TicketsPerBlock + StakeEnabledHeight: 16 + 16, // CoinbaseMaturity + TicketMaturity + StakeValidationHeight: 16 + (64 * 2), // CoinbaseMaturity + TicketPoolSize*2 + StakeBaseSigScript: []byte{0xDE, 0xAD, 0xBE, 0xEF}, + + // Decred organization related parameters + // + // "Dev org" address is a 3-of-3 P2SH going to wallet: + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // aardvark adroitness aardvark adroitness + // briefcase + // (seed 0x00000000000000000000000000000000000000000000000000000000000000) + // + // This same wallet owns the three ledger outputs for simnet. + // + // P2SH details for simnet dev org is below. + // + // address: Scc4ZC844nzuZCXsCFXUBXTLks2mD6psWom + // redeemScript: 532103e8c60c7336744c8dcc7b85c27789950fc52aa4e48f895ebbfb + // ac383ab893fc4c2103ff9afc246e0921e37d12e17d8296ca06a8f92a07fbe7857ed1d4 + // f0f5d94e988f21033ed09c7fa8b83ed53e6f2c57c5fa99ed2230c0d38edf53c0340d0f + // c2e79c725a53ae + // (3-of-3 multisig) + // Pubkeys used: + // SkQmxbeuEFDByPoTj41TtXat8tWySVuYUQpd4fuNNyUx51tF1csSs + // SkQn8ervNvAUEX5Ua3Lwjc6BAuTXRznDoDzsyxgjYqX58znY7w9e4 + // SkQkfkHZeBbMW8129tZ3KspEh1XBFC1btbkgzs6cjSyPbrgxzsKqk + // + OrganizationAddress: "ScuQxvveKGfpG1ypt6u27F99Anf7EW3cqhq", + BlockOneLedger: BlockOneLedgerSimNet, +} + +var ( + // ErrDuplicateNet describes an error where the parameters for a Decred + // network could not be set due to the network already being a standard + // network or previously-registered into this package. + ErrDuplicateNet = errors.New("duplicate Decred network") + + // ErrUnknownHDKeyID describes an error where the provided id which + // is intended to identify the network for a hierarchical deterministic + // private extended key is not registered. + ErrUnknownHDKeyID = errors.New("unknown hd private extended key bytes") +) + +var ( + registeredNets = map[wire.CurrencyNet]struct{}{ + MainNetParams.Net: struct{}{}, + TestNetParams.Net: struct{}{}, + SimNetParams.Net: struct{}{}, + } + + pubKeyAddrIDs = map[[2]byte]struct{}{ + MainNetParams.PubKeyAddrID: struct{}{}, + TestNetParams.PubKeyAddrID: struct{}{}, + SimNetParams.PubKeyAddrID: struct{}{}, + } + + pubKeyHashAddrIDs = map[[2]byte]struct{}{ + MainNetParams.PubKeyHashAddrID: struct{}{}, + TestNetParams.PubKeyHashAddrID: struct{}{}, + SimNetParams.PubKeyHashAddrID: struct{}{}, + } + + pkhEdwardsAddrIDs = map[[2]byte]struct{}{ + MainNetParams.PKHEdwardsAddrID: struct{}{}, + TestNetParams.PKHEdwardsAddrID: struct{}{}, + SimNetParams.PKHEdwardsAddrID: struct{}{}, + } + + pkhSchnorrAddrIDs = map[[2]byte]struct{}{ + MainNetParams.PKHSchnorrAddrID: struct{}{}, + TestNetParams.PKHSchnorrAddrID: struct{}{}, + SimNetParams.PKHSchnorrAddrID: struct{}{}, + } + + scriptHashAddrIDs = map[[2]byte]struct{}{ + MainNetParams.ScriptHashAddrID: struct{}{}, + TestNetParams.ScriptHashAddrID: struct{}{}, + SimNetParams.ScriptHashAddrID: struct{}{}, + } + + hdPrivToPubKeyIDs = map[[4]byte][]byte{ + MainNetParams.HDPrivateKeyID: MainNetParams.HDPublicKeyID[:], + TestNetParams.HDPrivateKeyID: TestNetParams.HDPublicKeyID[:], + SimNetParams.HDPrivateKeyID: SimNetParams.HDPublicKeyID[:], + } +) + +// Register registers the network parameters for a Decred network. This may +// error with ErrDuplicateNet if the network is already registered (either +// due to a previous Register call, or the network being one of the default +// networks). +// +// 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{}{} + pubKeyAddrIDs[params.PubKeyAddrID] = struct{}{} + pubKeyHashAddrIDs[params.PubKeyHashAddrID] = struct{}{} + scriptHashAddrIDs[params.ScriptHashAddrID] = struct{}{} + hdPrivToPubKeyIDs[params.HDPrivateKeyID] = params.HDPublicKeyID[:] + return nil +} + +// IsPubKeyAddrID returns whether the id is an identifier known to prefix a +// pay-to-pubkey address on any default or registered network. +func IsPubKeyAddrID(id [2]byte) bool { + _, ok := pubKeyHashAddrIDs[id] + return ok +} + +// 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 [2]byte) bool { + _, ok := pubKeyHashAddrIDs[id] + return ok +} + +func IsPKHEdwardsAddrID(id [2]byte) bool { + _, ok := pkhEdwardsAddrIDs[id] + return ok +} + +func IsPKHSchnorrAddrID(id [2]byte) bool { + _, ok := pkhSchnorrAddrIDs[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 [2]byte) bool { + _, ok := scriptHashAddrIDs[id] + return ok +} + +// HDPrivateKeyToPublicKeyID accepts a private hierarchical deterministic +// extended key id and returns the associated public key id. When the provided +// id is not registered, the ErrUnknownHDKeyID error will be returned. +func HDPrivateKeyToPublicKeyID(id []byte) ([]byte, error) { + if len(id) != 4 { + return nil, ErrUnknownHDKeyID + } + + var key [4]byte + copy(key[:], id) + pubBytes, ok := hdPrivToPubKeyIDs[key] + if !ok { + return nil, ErrUnknownHDKeyID + } + + return pubBytes, nil +} + +// newHashFromStr converts the passed big-endian hex string into a +// wire.Hash. It only differs from the one available in wire 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 newHashFromStr(hexStr string) *chainhash.Hash { + sha, err := chainhash.NewHashFromStr(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 +} + +// BlockOneSubsidy returns the total subsidy of block height 1 for the +// network. +func (p *Params) BlockOneSubsidy() int64 { + if len(p.BlockOneLedger) == 0 { + return 0 + } + + sum := int64(0) + for _, output := range p.BlockOneLedger { + sum += output.Amount + } + + return sum +} + +func (p *Params) TotalSubsidyProportions() uint16 { + return p.WorkRewardProportion + p.StakeRewardProportion + p.BlockTaxProportion +}