// Copyright (c) 2014-2016 The btcsuite developers // Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package chaincfg import ( "encoding/hex" "math/big" "time" "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/wire" ) // bigOne is 1 represented as a big.Int. It is defined here to avoid the // overhead of creating it multiple times. var bigOne = big.NewInt(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 } // Vote describes a voting instance. It is self-describing so that the UI can // be directly implemented using the fields. Mask determines which bits can be // used. Bits are enumerated and must be consecutive. Each vote requires one // and only one abstain (bits = 0) and reject vote (IsNo = true). // // For example, change block height from int64 to uint64. // Vote { // Id: "blockheight", // Description: "Change block height from int64 to uint64" // Mask: 0x0006, // Choices: []Choice{ // { // Id: "abstain", // Description: "abstain voting for change", // Bits: 0x0000, // IsAbstain: true, // IsNo: false, // }, // { // Id: "no", // Description: "reject changing block height to uint64", // Bits: 0x0002, // IsAbstain: false, // IsNo: false, // }, // { // Id: "yes", // Description: "accept changing block height to uint64", // Bits: 0x0004, // IsAbstain: false, // IsNo: true, // }, // }, // } // type Vote struct { // Single unique word identifying the vote. Id string // Longer description of what the vote is about. Description string // Usable bits for this vote. Mask uint16 Choices []Choice } // Choice defines one of the possible Choices that make up a vote. The 0 value // in Bits indicates the default choice. Care should be taken not to bias a // vote with the default choice. type Choice struct { // Single unique word identifying vote (e.g. yes) Id string // Longer description of the vote. Description string // Bits used for this vote. Bits uint16 // This is the abstain choice. By convention this must be the 0 vote // (abstain) and exist only once in the Vote.Choices array. IsAbstain bool // This choice indicates a hard No Vote. By convention this must exist // only once in the Vote.Choices array. IsNo bool } // VoteIndex compares vote to Choice.Bits and returns the index into the // Choices array. If the vote is invalid it returns -1. func (v *Vote) VoteIndex(vote uint16) int { vote &= v.Mask for k := range v.Choices { if vote == v.Choices[k].Bits { return k } } return -1 } const ( // VoteIDMaxBlockSize is the vote ID for the maximum block size // increase agenda used for the hard fork demo. VoteIDMaxBlockSize = "maxblocksize" // VoteIDSDiffAlgorithm is the vote ID for the new stake difficulty // algorithm (aka ticket price) agenda defined by DCP0001. VoteIDSDiffAlgorithm = "sdiffalgorithm" // VoteIDLNSupport is the vote ID for determining if the developers // should work on integrating Lightning Network support. VoteIDLNSupport = "lnsupport" // VoteIDLNFeatures is the vote ID for the agenda that introduces // features useful for the Lightning Network (among other uses) defined // by DCP0002 and DCP0003. VoteIDLNFeatures = "lnfeatures" // VoteIDFixLNSeqLocks is the vote ID for the agenda that corrects the // sequence lock functionality needed for Lightning Network (among other // uses) defined by DCP0004. VoteIDFixLNSeqLocks = "fixlnseqlocks" ) // ConsensusDeployment defines details related to a specific consensus rule // change that is voted in. This is part of BIP0009. type ConsensusDeployment struct { // Vote describes the what is being voted on and what the choices are. // This is sitting in a struct in order to make merging between btcd // easier. Vote Vote // StartTime is the median block time after which voting on the // deployment starts. StartTime uint64 // ExpireTime is the median block time after which the attempted // deployment expires. ExpireTime uint64 } // TokenPayout is a payout for block 1 which specifies a required script // version, script, and amount to pay in a transaction output. type TokenPayout struct { ScriptVersion uint16 Script []byte Amount int64 } // mustPayout returns a token payout populated with script version 0, the // provided hex-encoded script string converted to bytes and the provided // amount. It will panic if the specified script hex fails to parse so errors // in the source code be detected. It will only (and must only) be called with // hard-coded, and therefore known good, hex-encoded scripts. func mustPayout(script string, amount int64) TokenPayout { return TokenPayout{ ScriptVersion: 0, Script: hexDecode(script), Amount: amount, } } // DNSSeed identifies a DNS seed. type DNSSeed struct { // Host defines the hostname of the seed. Host string // HasFiltering defines whether the seed supports filtering // by service flags (wire.ServiceFlag). HasFiltering bool } // String returns the hostname of the DNS seed in human-readable form. func (d DNSSeed) String() string { return d.Host } // 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 defines a human-readable identifier for the network. Name string // Net defines the magic bytes used to identify the network. Net wire.CurrencyNet // DefaultPort defines the default peer-to-peer port for the network. DefaultPort string // DNSSeeds defines a list of DNS seeds for the network that are used // as one method to discover peers. DNSSeeds []DNSSeed // GenesisBlock defines the first block of the chain. GenesisBlock *wire.MsgBlock // GenesisHash is the starting block hash. GenesisHash chainhash.Hash // PowLimit defines the highest allowed proof of work value for a block // as a uint256. PowLimit *big.Int // PowLimitBits defines the highest allowed proof of work value for a // block in compact form. PowLimitBits uint32 // ReduceMinDifficulty defines whether the network should reduce the // minimum required difficulty after a long enough period of time has // passed without finding a block. This is really only useful for test // networks and should not be set on a main network. ReduceMinDifficulty bool // MinDiffReductionTime is the amount of time after which the minimum // required difficulty should be reduced when a block hasn't been found. // // NOTE: This only applies if ReduceMinDifficulty is true. MinDiffReductionTime time.Duration // GenerateSupported specifies whether or not CPU mining is allowed. GenerateSupported bool // MaximumBlockSizes are the maximum sizes of a block that can be // generated on the network. It is an array because the max block size // can be different values depending on the results of a voting agenda. // The first entry is the initial block size for the network, while the // other entries are potential block size changes which take effect when // the vote for the associated agenda succeeds. MaximumBlockSizes []int // MaxTxSize is the maximum number of bytes a serialized transaction can // be in order to be considered valid by consensus. MaxTxSize int // TargetTimePerBlock is the desired amount of time to generate each // block. TargetTimePerBlock 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 the 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 / SubsidyReductionInterval): // 1 subsidy *= MulSubsidy // 2 subsidy /= DivSubsidy // // NOTE: BaseSubsidy must be a max of 140,739,635,871,744 atoms or incorrect // results will occur due to int64 overflow. This value comes from // MaxInt64/MaxUint16 = (2^63 - 1)/(2^16 - 1) = 2^47 + 2^31 + 2^15. // BaseSubsidy is the starting subsidy amount for mined blocks. BaseSubsidy int64 // Subsidy reduction multiplier. MulSubsidy int64 // Subsidy reduction divisor. DivSubsidy int64 // SubsidyReductionInterval is the reduction interval in blocks. SubsidyReductionInterval 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 // These fields are related to voting on consensus rule changes as // defined by BIP0009. // // RuleChangeActivationQurom is the number of votes required for a vote // to take effect. // // RuleChangeActivationInterval is the number of blocks in each threshold // state retarget window. // // Deployments define the specific consensus rule changes to be voted // on for the stake version (the map key). RuleChangeActivationQuorum uint32 RuleChangeActivationMultiplier uint32 RuleChangeActivationDivisor uint32 RuleChangeActivationInterval uint32 Deployments map[uint32][]ConsensusDeployment // Enforce current block version once network has upgraded. BlockEnforceNumRequired uint64 // Reject previous block versions once network has upgraded. BlockRejectNumRequired uint64 // The number of nodes to check. BlockUpgradeNumToCheck uint64 // AcceptNonStdTxs is a mempool param to either accept and relay // non standard txs to the network or reject them AcceptNonStdTxs 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 // SLIP-0044 registered coin type used for BIP44, used in the hierarchical // deterministic path for address generation. // All SLIP-0044 registered coin types are defined here: // https://github.com/satoshilabs/slips/blob/master/slip-0044.md SLIP0044CoinType uint32 // Legacy BIP44 coin type used in the hierarchical deterministic path for // address generation. Previous name was HDCoinType, the LegacyCoinType // was introduced for backwards compatibility. Usually, SLIP0044CoinType // should be used instead. LegacyCoinType 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 // CoinbaseMaturity is the number of blocks required before newly mined // coins (coinbase transactions) can be spent. 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 // StakeVersionInterval determines the interval where the stake version // is calculated. StakeVersionInterval 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 // StakeMajorityMultiplier and StakeMajorityDivisor are used // to calculate the super majority of stake votes using integer math as // such: X*StakeMajorityMultiplier/StakeMajorityDivisor StakeMajorityMultiplier int32 StakeMajorityDivisor int32 // OrganizationPkScript is the output script for block taxes to be // distributed to in every block's coinbase. It should ideally be a P2SH // multisignature address. OrganizationPkScriptVersion is the version // of the output script. Until PoS hardforking is implemented, this // version must always match for a block to validate. OrganizationPkScript []byte OrganizationPkScriptVersion uint16 // 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 } // HDPrivKeyVersion returns the hierarchical deterministic extended private key // magic version bytes for the network the parameters define. func (p *Params) HDPrivKeyVersion() [4]byte { return p.HDPrivateKeyID } // HDPubKeyVersion returns the hierarchical deterministic extended public key // magic version bytes for the network the parameters define. func (p *Params) HDPubKeyVersion() [4]byte { return p.HDPublicKeyID } // AddrIDPubKeyV0 returns the magic prefix bytes for version 0 pay-to-pubkey // addresses. func (p *Params) AddrIDPubKeyV0() [2]byte { return p.PubKeyAddrID } // AddrIDPubKeyHashECDSAV0 returns the magic prefix bytes for version 0 // pay-to-pubkey-hash addresses where the underlying pubkey is secp256k1 and the // signature algorithm is ECDSA. func (p *Params) AddrIDPubKeyHashECDSAV0() [2]byte { return p.PubKeyHashAddrID } // AddrIDPubKeyHashEd25519V0 returns the magic prefix bytes for version 0 // pay-to-pubkey-hash addresses where the underlying pubkey and signature // algorithm are Ed25519. func (p *Params) AddrIDPubKeyHashEd25519V0() [2]byte { return p.PKHEdwardsAddrID } // AddrIDPubKeyHashSchnorrV0 returns the magic prefix bytes for version 0 // pay-to-pubkey-hash addresses where the underlying pubkey is secp256k1 and the // signature algorithm is Schnorr. func (p *Params) AddrIDPubKeyHashSchnorrV0() [2]byte { return p.PKHSchnorrAddrID } // AddrIDScriptHashV0 returns the magic prefix bytes for version 0 // pay-to-script-hash addresses. func (p *Params) AddrIDScriptHashV0() [2]byte { return p.ScriptHashAddrID } // BaseSubsidyValue returns the starting base max potential subsidy amount for // mined blocks. This value is reduced over time and then split proportionally // between PoW, PoS, and the Treasury. The reduction is controlled by the // SubsidyReductionInterval, SubsidyReductionMultiplier, and // SubsidyReductionDivisor parameters. func (p *Params) BaseSubsidyValue() int64 { return p.BaseSubsidy } // SubsidyReductionMultiplier returns the multiplier to use when performing // the exponential subsidy reduction. func (p *Params) SubsidyReductionMultiplier() int64 { return p.MulSubsidy } // SubsidyReductionDivisor returns the divisor to use when performing the // exponential subsidy reduction. func (p *Params) SubsidyReductionDivisor() int64 { return p.DivSubsidy } // SubsidyReductionIntervalBlocks returns the reduction interval in number of // blocks. func (p *Params) SubsidyReductionIntervalBlocks() int64 { return p.SubsidyReductionInterval } // WorkSubsidyProportion returns the comparative proportion of the subsidy // generated for creating a block (PoW). // // The proportional split between PoW, PoS, and the Treasury is calculated // by treating each of the proportional parameters as a ratio to the sum of // the three proportional parameters: WorkSubsidyProportion, // StakeSubsidyProportion, and TreasurySubsidyProportion. // // For example: // WorkSubsidyProportion: 6 => 6 / (6+3+1) => 6/10 => 60% // StakeSubsidyProportion: 3 => 3 / (6+3+1) => 3/10 => 30% // TreasurySubsidyProportion: 1 => 1 / (6+3+1) => 1/10 => 10% func (p *Params) WorkSubsidyProportion() uint16 { return p.WorkRewardProportion } // StakeSubsidyProportion returns the comparative proportion of the subsidy // generated for casting stake votes (collectively, per block). See the // documentation for WorkSubsidyProportion for more details on how the // parameter is used. func (p *Params) StakeSubsidyProportion() uint16 { return p.StakeRewardProportion } // TreasurySubsidyProportion returns the comparative proportion of the // subsidy allocated to the project treasury. See the documentation for // WorkSubsidyProportion for more details on how the parameter is used. func (p *Params) TreasurySubsidyProportion() uint16 { return p.BlockTaxProportion } // VotesPerBlock returns the maximum number of votes a block must contain to // receive full subsidy. func (p *Params) VotesPerBlock() uint16 { return p.TicketsPerBlock } // StakeValidationBeginHeight returns the height at which votes become required // to extend a block. This height is the first that will be voted on, but will // not include any votes itself. func (p *Params) StakeValidationBeginHeight() int64 { return p.StakeValidationHeight } // StakeEnableHeight returns the height at which the first ticket could possibly // mature. func (p *Params) StakeEnableHeight() int64 { return p.StakeEnabledHeight } // TicketExpiryBlocks returns the number of blocks after maturity that tickets // expire. This will be >= (StakeEnableHeight() + StakeValidationBeginHeight()). func (p *Params) TicketExpiryBlocks() uint32 { return p.TicketExpiry } // newHashFromStr converts the passed big-endian hex string into a // chainhash.Hash. It only differs from the one available in chainhash 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 { hash, 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 hash } func hexDecode(hexStr string) []byte { b, err := hex.DecodeString(hexStr) if err != nil { panic(err) } return b } // 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 } // TotalSubsidyProportions is the sum of WorkReward, StakeReward, and BlockTax // proportions. func (p *Params) TotalSubsidyProportions() uint16 { return p.WorkRewardProportion + p.StakeRewardProportion + p.BlockTaxProportion } // LatestCheckpointHeight is the height of the latest checkpoint block in the // parameters. func (p *Params) LatestCheckpointHeight() int64 { if len(p.Checkpoints) == 0 { return 0 } return p.Checkpoints[len(p.Checkpoints)-1].Height }