github.com/decred/dcrd/blockchain@v1.2.1/subsidy.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Copyright (c) 2015-2019 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  
    12  	"github.com/decred/dcrd/blockchain/stake"
    13  	"github.com/decred/dcrd/blockchain/standalone"
    14  	"github.com/decred/dcrd/chaincfg"
    15  	"github.com/decred/dcrd/dcrutil"
    16  	"github.com/decred/dcrd/txscript"
    17  	"github.com/decred/dcrd/wire"
    18  )
    19  
    20  // The number of values to precalculate on initialization of the subsidy
    21  // cache.
    22  const subsidyCacheInitWidth = 4
    23  
    24  // SubsidyCache is a structure that caches calculated values of subsidy so that
    25  // they're not constantly recalculated. The blockchain struct itself possesses a
    26  // pointer to a preinitialized SubsidyCache.
    27  //
    28  // Deprecated: Use standalone.SubsidyCache instead.
    29  type SubsidyCache = standalone.SubsidyCache
    30  
    31  // subsidyParams adapts v1 chaincfg.Params to implement the
    32  // standalone.SubsidyParams interface.  It is already implemented by the v2
    33  // chaincfg.Params, but updating to those requires a major version bump since
    34  // the type is used in the public API.
    35  type subsidyParams struct {
    36  	*chaincfg.Params
    37  }
    38  
    39  // BaseSubsidyValue returns the starting base max potential subsidy amount for
    40  // mined blocks.
    41  //
    42  // This is part of the standalone.SubsidyParams interface.
    43  func (p *subsidyParams) BaseSubsidyValue() int64 {
    44  	return p.BaseSubsidy
    45  }
    46  
    47  // SubsidyReductionMultiplier returns the multiplier to use when performing the
    48  // exponential subsidy reduction.
    49  //
    50  // This is part of the standalone.SubsidyParams interface.
    51  func (p *subsidyParams) SubsidyReductionMultiplier() int64 {
    52  	return p.MulSubsidy
    53  }
    54  
    55  // SubsidyReductionDivisor returns the divisor to use when performing the
    56  // exponential subsidy reduction.
    57  //
    58  // This is part of the standalone.SubsidyParams interface.
    59  func (p *subsidyParams) SubsidyReductionDivisor() int64 {
    60  	return p.DivSubsidy
    61  }
    62  
    63  // SubsidyReductionIntervalBlocks returns the reduction interval in number of
    64  // blocks.
    65  //
    66  // This is part of the standalone.SubsidyParams interface.
    67  func (p *subsidyParams) SubsidyReductionIntervalBlocks() int64 {
    68  	return p.SubsidyReductionInterval
    69  }
    70  
    71  // WorkSubsidyProportion returns the comparative proportion of the subsidy
    72  // generated for creating a block (PoW).
    73  //
    74  // This is part of the standalone.SubsidyParams interface.
    75  func (p *subsidyParams) WorkSubsidyProportion() uint16 {
    76  	return p.WorkRewardProportion
    77  }
    78  
    79  // StakeSubsidyProportion returns the comparative proportion of the subsidy
    80  // generated for casting stake votes (collectively, per block).
    81  //
    82  // This is part of the standalone.SubsidyParams interface.
    83  func (p *subsidyParams) StakeSubsidyProportion() uint16 {
    84  	return p.StakeRewardProportion
    85  }
    86  
    87  // TreasurySubsidyProportion returns the comparative proportion of the subsidy
    88  // allocated to the project treasury.
    89  //
    90  // This is part of the standalone.SubsidyParams interface.
    91  func (p *subsidyParams) TreasurySubsidyProportion() uint16 {
    92  	return p.BlockTaxProportion
    93  }
    94  
    95  // VotesPerBlock returns the maximum number of votes a block must contain to
    96  // receive full subsidy.
    97  //
    98  // This is part of the standalone.SubsidyParams interface.
    99  func (p *subsidyParams) VotesPerBlock() uint16 {
   100  	return p.TicketsPerBlock
   101  }
   102  
   103  // StakeValidationBeginHeight returns the height at which votes become required
   104  // to extend a block.  This height is the first that will be voted on, but will
   105  // not include any votes itself.
   106  //
   107  // This is part of the standalone.SubsidyParams interface.
   108  func (p *subsidyParams) StakeValidationBeginHeight() int64 {
   109  	return p.StakeValidationHeight
   110  }
   111  
   112  // NewSubsidyCache initializes a new subsidy cache for a given height. It
   113  // precalculates the values of the subsidy that are most likely to be seen by
   114  // the client when it connects to the network.
   115  //
   116  // Deprecated: Use standalone.NewSubsidyCache instead.
   117  func NewSubsidyCache(height int64, params *chaincfg.Params) *SubsidyCache {
   118  	return standalone.NewSubsidyCache(&subsidyParams{params})
   119  }
   120  
   121  // CalcBlockWorkSubsidy calculates the proof of work subsidy for a block as a
   122  // proportion of the total subsidy.
   123  //
   124  // Deprecated: Use standalone.SubsidyCache.CalcWorkSubsidy instead.
   125  func CalcBlockWorkSubsidy(subsidyCache *SubsidyCache, height int64, voters uint16, params *chaincfg.Params) int64 {
   126  	return subsidyCache.CalcWorkSubsidy(height, voters)
   127  }
   128  
   129  // CalcStakeVoteSubsidy calculates the subsidy for a stake vote based on the height
   130  // of its input SStx.
   131  //
   132  // Safe for concurrent access.
   133  //
   134  // Deprecated: Use standalone.SubsidyCache.CalcStakeVoteSubsidy instead.
   135  func CalcStakeVoteSubsidy(subsidyCache *SubsidyCache, height int64, params *chaincfg.Params) int64 {
   136  	return subsidyCache.CalcStakeVoteSubsidy(height)
   137  }
   138  
   139  // CalcBlockTaxSubsidy calculates the subsidy for the organization address in the
   140  // coinbase.
   141  //
   142  // Safe for concurrent access.
   143  //
   144  // Deprecated: Use standalone.SubsidyCache.CalcTreasurySubsidy instead.
   145  func CalcBlockTaxSubsidy(subsidyCache *SubsidyCache, height int64, voters uint16, params *chaincfg.Params) int64 {
   146  	return subsidyCache.CalcTreasurySubsidy(height, voters)
   147  }
   148  
   149  // blockOneCoinbasePaysTokens checks to see if the first block coinbase pays
   150  // out to the network initial token ledger.
   151  func blockOneCoinbasePaysTokens(tx *dcrutil.Tx, params *chaincfg.Params) error {
   152  	// If no ledger is specified, just return true.
   153  	if len(params.BlockOneLedger) == 0 {
   154  		return nil
   155  	}
   156  
   157  	if tx.MsgTx().LockTime != 0 {
   158  		errStr := fmt.Sprintf("block 1 coinbase has invalid locktime")
   159  		return ruleError(ErrBlockOneTx, errStr)
   160  	}
   161  
   162  	if tx.MsgTx().Expiry != wire.NoExpiryValue {
   163  		errStr := fmt.Sprintf("block 1 coinbase has invalid expiry")
   164  		return ruleError(ErrBlockOneTx, errStr)
   165  	}
   166  
   167  	if tx.MsgTx().TxIn[0].Sequence != wire.MaxTxInSequenceNum {
   168  		errStr := fmt.Sprintf("block 1 coinbase not finalized")
   169  		return ruleError(ErrBlockOneInputs, errStr)
   170  	}
   171  
   172  	if len(tx.MsgTx().TxOut) == 0 {
   173  		errStr := fmt.Sprintf("coinbase outputs empty in block 1")
   174  		return ruleError(ErrBlockOneOutputs, errStr)
   175  	}
   176  
   177  	ledger := params.BlockOneLedger
   178  	if len(ledger) != len(tx.MsgTx().TxOut) {
   179  		errStr := fmt.Sprintf("wrong number of outputs in block 1 coinbase; "+
   180  			"got %v, expected %v", len(tx.MsgTx().TxOut), len(ledger))
   181  		return ruleError(ErrBlockOneOutputs, errStr)
   182  	}
   183  
   184  	// Check the addresses and output amounts against those in the ledger.
   185  	const consensusScriptVersion = 0
   186  	for i, txout := range tx.MsgTx().TxOut {
   187  		if txout.Version != consensusScriptVersion {
   188  			str := fmt.Sprintf("block one output %d script version %d is not %d",
   189  				i, txout.Version, consensusScriptVersion)
   190  			return ruleError(ErrBlockOneOutputs, str)
   191  		}
   192  
   193  		// There should only be one address.
   194  		_, addrs, _, err :=
   195  			txscript.ExtractPkScriptAddrs(txout.Version, txout.PkScript, params)
   196  		if err != nil {
   197  			return ruleError(ErrBlockOneOutputs, err.Error())
   198  		}
   199  		if len(addrs) != 1 {
   200  			errStr := fmt.Sprintf("too many addresses in output")
   201  			return ruleError(ErrBlockOneOutputs, errStr)
   202  		}
   203  
   204  		addrLedger, err := dcrutil.DecodeAddress(ledger[i].Address)
   205  		if err != nil {
   206  			return err
   207  		}
   208  
   209  		if !bytes.Equal(addrs[0].ScriptAddress(), addrLedger.ScriptAddress()) {
   210  			errStr := fmt.Sprintf("address in output %v has non matching "+
   211  				"address; got %v (hash160 %x), want %v (hash160 %x)",
   212  				i,
   213  				addrs[0].EncodeAddress(),
   214  				addrs[0].ScriptAddress(),
   215  				addrLedger.EncodeAddress(),
   216  				addrLedger.ScriptAddress())
   217  			return ruleError(ErrBlockOneOutputs, errStr)
   218  		}
   219  
   220  		if txout.Value != ledger[i].Amount {
   221  			errStr := fmt.Sprintf("address in output %v has non matching "+
   222  				"amount; got %v, want %v", i, txout.Value, ledger[i].Amount)
   223  			return ruleError(ErrBlockOneOutputs, errStr)
   224  		}
   225  	}
   226  
   227  	return nil
   228  }
   229  
   230  // BlockOneCoinbasePaysTokens checks to see if the first block coinbase pays
   231  // out to the network initial token ledger.
   232  //
   233  // Deprecated: This will be removed in the next major version bump.
   234  func BlockOneCoinbasePaysTokens(tx *dcrutil.Tx, params *chaincfg.Params) error {
   235  	return blockOneCoinbasePaysTokens(tx, params)
   236  }
   237  
   238  // coinbasePaysTreasury checks to see if a given block's coinbase correctly pays
   239  // the treasury.
   240  func coinbasePaysTreasury(subsidyCache *standalone.SubsidyCache, tx *dcrutil.Tx, height int64, voters uint16, params *chaincfg.Params) error {
   241  	// Treasury subsidy only applies from block 2 onwards.
   242  	if height <= 1 {
   243  		return nil
   244  	}
   245  
   246  	// Treasury subsidy is disabled.
   247  	if params.BlockTaxProportion == 0 {
   248  		return nil
   249  	}
   250  
   251  	if len(tx.MsgTx().TxOut) == 0 {
   252  		str := fmt.Sprintf("invalid coinbase (no outputs)")
   253  		return ruleError(ErrNoTxOutputs, str)
   254  	}
   255  
   256  	treasuryOutput := tx.MsgTx().TxOut[0]
   257  	if treasuryOutput.Version != params.OrganizationPkScriptVersion {
   258  		str := fmt.Sprintf("treasury output version %d is instead of %d",
   259  			treasuryOutput.Version, params.OrganizationPkScriptVersion)
   260  		return ruleError(ErrNoTax, str)
   261  	}
   262  	if !bytes.Equal(treasuryOutput.PkScript, params.OrganizationPkScript) {
   263  		str := fmt.Sprintf("treasury output script is %x instead of %x",
   264  			treasuryOutput.PkScript, params.OrganizationPkScript)
   265  		return ruleError(ErrNoTax, str)
   266  	}
   267  
   268  	// Calculate the amount of subsidy that should have been paid out to the
   269  	// Treasury and ensure the subsidy generated is correct.
   270  	orgSubsidy := subsidyCache.CalcTreasurySubsidy(height, voters)
   271  	if orgSubsidy != treasuryOutput.Value {
   272  		str := fmt.Sprintf("treasury output amount is %s instead of %s",
   273  			dcrutil.Amount(treasuryOutput.Value), dcrutil.Amount(orgSubsidy))
   274  		return ruleError(ErrNoTax, str)
   275  	}
   276  
   277  	return nil
   278  }
   279  
   280  // CoinbasePaysTax checks to see if a given block's coinbase correctly pays
   281  // tax to the developer organization.
   282  //
   283  // Deprecated:  This will be removed in the next major version.
   284  func CoinbasePaysTax(subsidyCache *SubsidyCache, tx *dcrutil.Tx, height int64, voters uint16, params *chaincfg.Params) error {
   285  	return coinbasePaysTreasury(subsidyCache, tx, height, voters, params)
   286  }
   287  
   288  // calculateAddedSubsidy calculates the amount of subsidy added by a block
   289  // and its parent. The blocks passed to this function MUST be valid blocks
   290  // that have already been confirmed to abide by the consensus rules of the
   291  // network, or the function might panic.
   292  func calculateAddedSubsidy(block, parent *dcrutil.Block) int64 {
   293  	var subsidy int64
   294  	if headerApprovesParent(&block.MsgBlock().Header) {
   295  		subsidy += parent.MsgBlock().Transactions[0].TxIn[0].ValueIn
   296  	}
   297  
   298  	for _, stx := range block.MsgBlock().STransactions {
   299  		if stake.IsSSGen(stx) {
   300  			subsidy += stx.TxIn[0].ValueIn
   301  		}
   302  	}
   303  
   304  	return subsidy
   305  }
   306  
   307  // CalculateAddedSubsidy calculates the amount of subsidy added by a block
   308  // and its parent. The blocks passed to this function MUST be valid blocks
   309  // that have already been confirmed to abide by the consensus rules of the
   310  // network, or the function might panic.
   311  //
   312  // Deprecated:  This will no longer be exported in the next major version.
   313  func CalculateAddedSubsidy(block, parent *dcrutil.Block) int64 {
   314  	return calculateAddedSubsidy(block, parent)
   315  }