github.com/decred/dcrd/blockchain@v1.2.1/chaingen/generator.go (about) 1 // Copyright (c) 2016-2019 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package chaingen 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "fmt" 11 "math" 12 "math/big" 13 "runtime" 14 "sort" 15 "time" 16 17 "github.com/decred/dcrd/chaincfg" 18 "github.com/decred/dcrd/chaincfg/chainhash" 19 "github.com/decred/dcrd/dcrutil" 20 "github.com/decred/dcrd/txscript" 21 "github.com/decred/dcrd/wire" 22 ) 23 24 var ( 25 // hash256prngSeedConst is a constant derived from the hex 26 // representation of pi and is used in conjunction with a caller-provided 27 // seed when initializing the deterministic lottery prng. 28 hash256prngSeedConst = []byte{0x24, 0x3f, 0x6a, 0x88, 0x85, 0xa3, 0x08, 29 0xd3} 30 31 // opTrueScript is a simple public key script that contains the OP_TRUE 32 // opcode. It is defined here to reduce garbage creation. 33 opTrueScript = []byte{txscript.OP_TRUE} 34 35 // opTrueRedeemScript is the signature script that can be used to redeem 36 // a p2sh output to the opTrueScript. It is defined here to reduce 37 // garbage creation. 38 opTrueRedeemScript = []byte{txscript.OP_DATA_1, txscript.OP_TRUE} 39 40 // coinbaseSigScript is the signature script used by the tests when 41 // creating standard coinbase transactions. It is defined here to 42 // reduce garbage creation. 43 coinbaseSigScript = []byte{txscript.OP_0, txscript.OP_0} 44 ) 45 46 const ( 47 // voteBitYes is the specific bit that is set in the vote bits to 48 // indicate that the previous block is valid. 49 voteBitYes = 0x01 50 ) 51 52 // SpendableOut represents a transaction output that is spendable along with 53 // additional metadata such as the block its in and how much it pays. 54 type SpendableOut struct { 55 prevOut wire.OutPoint 56 blockHeight uint32 57 blockIndex uint32 58 amount dcrutil.Amount 59 } 60 61 // PrevOut returns the outpoint associated with the spendable output. 62 func (s *SpendableOut) PrevOut() wire.OutPoint { 63 return s.prevOut 64 } 65 66 // BlockHeight returns the block height of the block the spendable output is in. 67 func (s *SpendableOut) BlockHeight() uint32 { 68 return s.blockHeight 69 } 70 71 // BlockIndex returns the offset into the block the spendable output is in. 72 func (s *SpendableOut) BlockIndex() uint32 { 73 return s.blockIndex 74 } 75 76 // Amount returns the amount associated with the spendable output. 77 func (s *SpendableOut) Amount() dcrutil.Amount { 78 return s.amount 79 } 80 81 // makeSpendableOutForTxInternal returns a spendable output for the given 82 // transaction block height, transaction index within the block, transaction 83 // tree and transaction output index within the transaction. 84 func makeSpendableOutForTxInternal(tx *wire.MsgTx, blockHeight, txIndex, txOutIndex uint32, tree int8) SpendableOut { 85 return SpendableOut{ 86 prevOut: wire.OutPoint{ 87 Hash: *tx.CachedTxHash(), 88 Index: txOutIndex, 89 Tree: tree, 90 }, 91 blockHeight: blockHeight, 92 blockIndex: txIndex, 93 amount: dcrutil.Amount(tx.TxOut[txOutIndex].Value), 94 } 95 } 96 97 // MakeSpendableOutForTx returns a spendable output for a regular transaction. 98 func MakeSpendableOutForTx(tx *wire.MsgTx, blockHeight, txIndex, txOutIndex uint32) SpendableOut { 99 return makeSpendableOutForTxInternal(tx, blockHeight, txIndex, txOutIndex, wire.TxTreeRegular) 100 } 101 102 // MakeSpendableOutForSTx returns a spendable output for a stake transaction. 103 func MakeSpendableOutForSTx(tx *wire.MsgTx, blockHeight, txIndex, txOutIndex uint32) SpendableOut { 104 return makeSpendableOutForTxInternal(tx, blockHeight, txIndex, txOutIndex, wire.TxTreeStake) 105 } 106 107 // MakeSpendableOut returns a spendable output for the given block, transaction 108 // index within the block, and transaction output index within the transaction. 109 func MakeSpendableOut(block *wire.MsgBlock, txIndex, txOutIndex uint32) SpendableOut { 110 tx := block.Transactions[txIndex] 111 return MakeSpendableOutForTx(tx, block.Header.Height, txIndex, txOutIndex) 112 } 113 114 // MakeSpendableStakeOut returns a spendable stake output for the given block, 115 // transaction index within the block, and transaction output index within the 116 // transaction. 117 func MakeSpendableStakeOut(block *wire.MsgBlock, txIndex, txOutIndex uint32) SpendableOut { 118 tx := block.STransactions[txIndex] 119 return MakeSpendableOutForSTx(tx, block.Header.Height, txIndex, txOutIndex) 120 } 121 122 // stakeTicket represents a transaction that is an sstx along with the height of 123 // the block it was mined in and the its index within that block. 124 type stakeTicket struct { 125 tx *wire.MsgTx 126 blockHeight uint32 127 blockIndex uint32 128 } 129 130 // stakeTicketSorter implements sort.Interface to allow a slice of stake tickets 131 // to be sorted. 132 type stakeTicketSorter []*stakeTicket 133 134 // Len returns the number of stake tickets in the slice. It is part of the 135 // sort.Interface implementation. 136 func (t stakeTicketSorter) Len() int { return len(t) } 137 138 // Swap swaps the stake tickets at the passed indices. It is part of the 139 // sort.Interface implementation. 140 func (t stakeTicketSorter) Swap(i, j int) { t[i], t[j] = t[j], t[i] } 141 142 // Less returns whether the stake ticket with index i should sort before the 143 // stake ticket with index j. It is part of the sort.Interface implementation. 144 func (t stakeTicketSorter) Less(i, j int) bool { 145 iHash := t[i].tx.CachedTxHash()[:] 146 jHash := t[j].tx.CachedTxHash()[:] 147 return bytes.Compare(iHash, jHash) < 0 148 } 149 150 // Generator houses state used to ease the process of generating test blocks 151 // that build from one another along with housing other useful things such as 152 // available spendable outputs and generic payment scripts used throughout the 153 // tests. 154 type Generator struct { 155 params *chaincfg.Params 156 tip *wire.MsgBlock 157 tipName string 158 blocks map[chainhash.Hash]*wire.MsgBlock 159 blockHeights map[chainhash.Hash]uint32 160 blocksByName map[string]*wire.MsgBlock 161 p2shOpTrueAddr dcrutil.Address 162 p2shOpTrueScript []byte 163 164 // Used for tracking spendable coinbase outputs. 165 spendableOuts [][]SpendableOut 166 prevCollectedHash chainhash.Hash 167 168 // Used for tracking the live ticket pool and revocations. 169 originalParents map[chainhash.Hash]chainhash.Hash 170 immatureTickets []*stakeTicket 171 liveTickets []*stakeTicket 172 wonTickets map[chainhash.Hash][]*stakeTicket 173 expiredTickets []*stakeTicket 174 revokedTickets map[chainhash.Hash][]*stakeTicket 175 missedVotes map[chainhash.Hash]*stakeTicket 176 } 177 178 // MakeGenerator returns a generator instance initialized with the genesis block 179 // as the tip as well as a cached generic pay-to-script-hash script for OP_TRUE. 180 func MakeGenerator(params *chaincfg.Params) (Generator, error) { 181 // Generate a generic pay-to-script-hash script that is a simple 182 // OP_TRUE. This allows the tests to avoid needing to generate and 183 // track actual public keys and signatures. 184 p2shOpTrueAddr, err := dcrutil.NewAddressScriptHash(opTrueScript, params) 185 if err != nil { 186 return Generator{}, err 187 } 188 p2shOpTrueScript, err := txscript.PayToAddrScript(p2shOpTrueAddr) 189 if err != nil { 190 return Generator{}, err 191 } 192 193 genesis := params.GenesisBlock 194 genesisHash := genesis.BlockHash() 195 return Generator{ 196 params: params, 197 tip: genesis, 198 tipName: "genesis", 199 blocks: map[chainhash.Hash]*wire.MsgBlock{genesisHash: genesis}, 200 blockHeights: map[chainhash.Hash]uint32{genesis.BlockHash(): 0}, 201 blocksByName: map[string]*wire.MsgBlock{"genesis": genesis}, 202 p2shOpTrueAddr: p2shOpTrueAddr, 203 p2shOpTrueScript: p2shOpTrueScript, 204 originalParents: make(map[chainhash.Hash]chainhash.Hash), 205 wonTickets: make(map[chainhash.Hash][]*stakeTicket), 206 revokedTickets: make(map[chainhash.Hash][]*stakeTicket), 207 missedVotes: make(map[chainhash.Hash]*stakeTicket), 208 }, nil 209 } 210 211 // Params returns the chain params associated with the generator instance. 212 func (g *Generator) Params() *chaincfg.Params { 213 return g.params 214 } 215 216 // Tip returns the current tip block of the generator instance. 217 func (g *Generator) Tip() *wire.MsgBlock { 218 return g.tip 219 } 220 221 // TipName returns the name of the current tip block of the generator instance. 222 func (g *Generator) TipName() string { 223 return g.tipName 224 } 225 226 // P2shOpTrueAddr returns the generator p2sh script that is composed with 227 // a single OP_TRUE. 228 func (g *Generator) P2shOpTrueAddr() dcrutil.Address { 229 return g.p2shOpTrueAddr 230 } 231 232 // BlockByName returns the block associated with the provided block name. It 233 // will panic if the specified block name does not exist. 234 func (g *Generator) BlockByName(blockName string) *wire.MsgBlock { 235 block, ok := g.blocksByName[blockName] 236 if !ok { 237 panic(fmt.Sprintf("block name %s does not exist", blockName)) 238 } 239 return block 240 } 241 242 // BlockByHash returns the block associated with the provided block hash. It 243 // will panic if the specified block hash does not exist. 244 func (g *Generator) BlockByHash(hash *chainhash.Hash) *wire.MsgBlock { 245 block, ok := g.blocks[*hash] 246 if !ok { 247 panic(fmt.Sprintf("block with hash %s does not exist", hash)) 248 } 249 return block 250 } 251 252 // blockHeight returns the block height associated with the provided block hash. 253 // It will panic if the specified block hash does not exist. 254 func (g *Generator) blockHeight(hash chainhash.Hash) uint32 { 255 height, ok := g.blockHeights[hash] 256 if !ok { 257 panic(fmt.Sprintf("no block height found for block %s", hash)) 258 } 259 return height 260 } 261 262 // opReturnScript returns a provably-pruneable OP_RETURN script with the 263 // provided data. 264 func opReturnScript(data []byte) []byte { 265 builder := txscript.NewScriptBuilder() 266 script, err := builder.AddOp(txscript.OP_RETURN).AddData(data).Script() 267 if err != nil { 268 panic(err) 269 } 270 return script 271 } 272 273 // UniqueOpReturnScript returns a standard provably-pruneable OP_RETURN script 274 // with a random uint64 encoded as the data. 275 func UniqueOpReturnScript() []byte { 276 rand, err := wire.RandomUint64() 277 if err != nil { 278 panic(err) 279 } 280 281 data := make([]byte, 8) 282 binary.LittleEndian.PutUint64(data[0:8], rand) 283 return opReturnScript(data) 284 } 285 286 // calcFullSubsidy returns the full block subsidy for the given block height. 287 // 288 // NOTE: This and the other subsidy calculation funcs intentionally are not 289 // using the blockchain code since the intent is to be able to generate known 290 // good tests which exercise that code, so it wouldn't make sense to use the 291 // same code to generate them. 292 func (g *Generator) calcFullSubsidy(blockHeight uint32) dcrutil.Amount { 293 iterations := int64(blockHeight) / g.params.SubsidyReductionInterval 294 subsidy := g.params.BaseSubsidy 295 for i := int64(0); i < iterations; i++ { 296 subsidy *= g.params.MulSubsidy 297 subsidy /= g.params.DivSubsidy 298 } 299 return dcrutil.Amount(subsidy) 300 } 301 302 // calcPoWSubsidy returns the proof-of-work subsidy portion from a given full 303 // subsidy, block height, and number of votes that will be included in the 304 // block. 305 // 306 // NOTE: This and the other subsidy calculation funcs intentionally are not 307 // using the blockchain code since the intent is to be able to generate known 308 // good tests which exercise that code, so it wouldn't make sense to use the 309 // same code to generate them. 310 func (g *Generator) calcPoWSubsidy(fullSubsidy dcrutil.Amount, blockHeight uint32, numVotes uint16) dcrutil.Amount { 311 powProportion := dcrutil.Amount(g.params.WorkRewardProportion) 312 totalProportions := dcrutil.Amount(g.params.TotalSubsidyProportions()) 313 powSubsidy := (fullSubsidy * powProportion) / totalProportions 314 if int64(blockHeight) < g.params.StakeValidationHeight { 315 return powSubsidy 316 } 317 318 // Reduce the subsidy according to the number of votes. 319 ticketsPerBlock := dcrutil.Amount(g.params.TicketsPerBlock) 320 return (powSubsidy * dcrutil.Amount(numVotes)) / ticketsPerBlock 321 } 322 323 // calcPoSSubsidy returns the proof-of-stake subsidy portion for a given block 324 // height being voted on. 325 // 326 // NOTE: This and the other subsidy calculation funcs intentionally are not 327 // using the blockchain code since the intent is to be able to generate known 328 // good tests which exercise that code, so it wouldn't make sense to use the 329 // same code to generate them. 330 func (g *Generator) calcPoSSubsidy(heightVotedOn uint32) dcrutil.Amount { 331 if int64(heightVotedOn+1) < g.params.StakeValidationHeight { 332 return 0 333 } 334 335 fullSubsidy := g.calcFullSubsidy(heightVotedOn) 336 posProportion := dcrutil.Amount(g.params.StakeRewardProportion) 337 totalProportions := dcrutil.Amount(g.params.TotalSubsidyProportions()) 338 return (fullSubsidy * posProportion) / totalProportions 339 } 340 341 // calcDevSubsidy returns the dev org subsidy portion from a given full subsidy. 342 // 343 // NOTE: This and the other subsidy calculation funcs intentionally are not 344 // using the blockchain code since the intent is to be able to generate known 345 // good tests which exercise that code, so it wouldn't make sense to use the 346 // same code to generate them. 347 func (g *Generator) calcDevSubsidy(fullSubsidy dcrutil.Amount, blockHeight uint32, numVotes uint16) dcrutil.Amount { 348 devProportion := dcrutil.Amount(g.params.BlockTaxProportion) 349 totalProportions := dcrutil.Amount(g.params.TotalSubsidyProportions()) 350 devSubsidy := (fullSubsidy * devProportion) / totalProportions 351 if int64(blockHeight) < g.params.StakeValidationHeight { 352 return devSubsidy 353 } 354 355 // Reduce the subsidy according to the number of votes. 356 ticketsPerBlock := dcrutil.Amount(g.params.TicketsPerBlock) 357 return (devSubsidy * dcrutil.Amount(numVotes)) / ticketsPerBlock 358 } 359 360 // standardCoinbaseOpReturnScript returns a standard script suitable for use as 361 // the second output of a standard coinbase transaction of a new block. In 362 // particular, the serialized data used with the OP_RETURN starts with the block 363 // height and is followed by 32 bytes which are treated as 4 uint64 extra 364 // nonces. This implementation puts a cryptographically random value into the 365 // final extra nonce position. The actual format of the data after the block 366 // height is not defined however this effectively mirrors the actual mining code 367 // at the time it was written. 368 func standardCoinbaseOpReturnScript(blockHeight uint32) []byte { 369 rand, err := wire.RandomUint64() 370 if err != nil { 371 panic(err) 372 } 373 374 data := make([]byte, 36) 375 binary.LittleEndian.PutUint32(data[0:4], blockHeight) 376 binary.LittleEndian.PutUint64(data[28:36], rand) 377 return opReturnScript(data) 378 } 379 380 // addCoinbaseTxOutputs adds the following outputs to the provided transaction 381 // which is assumed to be a coinbase transaction: 382 // - First output pays the development subsidy portion to the dev org 383 // - Second output is a standard provably prunable data-only coinbase output 384 // - Third and subsequent outputs pay the pow subsidy portion to the generic 385 // OP_TRUE p2sh script hash 386 func (g *Generator) addCoinbaseTxOutputs(tx *wire.MsgTx, blockHeight uint32, devSubsidy, powSubsidy dcrutil.Amount) { 387 // First output is the developer subsidy. 388 tx.AddTxOut(&wire.TxOut{ 389 Value: int64(devSubsidy), 390 Version: g.params.OrganizationPkScriptVersion, 391 PkScript: g.params.OrganizationPkScript, 392 }) 393 394 // Second output is a provably prunable data-only output that is used 395 // to ensure the coinbase is unique. 396 tx.AddTxOut(wire.NewTxOut(0, standardCoinbaseOpReturnScript(blockHeight))) 397 398 // Final outputs are the proof-of-work subsidy split into more than one 399 // output. These are in turn used throughout the tests as inputs to 400 // other transactions such as ticket purchases and additional spend 401 // transactions. 402 const numPoWOutputs = 6 403 amount := powSubsidy / numPoWOutputs 404 for i := 0; i < numPoWOutputs; i++ { 405 if i == numPoWOutputs-1 { 406 amount = powSubsidy - amount*(numPoWOutputs-1) 407 } 408 tx.AddTxOut(wire.NewTxOut(int64(amount), g.p2shOpTrueScript)) 409 } 410 } 411 412 // CreateCoinbaseTx returns a coinbase transaction paying an appropriate 413 // subsidy based on the passed block height and number of votes to the dev org 414 // and proof-of-work miner. 415 // 416 // See the addCoinbaseTxOutputs documentation for a breakdown of the outputs 417 // the transaction contains. 418 func (g *Generator) CreateCoinbaseTx(blockHeight uint32, numVotes uint16) *wire.MsgTx { 419 // Calculate the subsidy proportions based on the block height and the 420 // number of votes the block will include. 421 fullSubsidy := g.calcFullSubsidy(blockHeight) 422 devSubsidy := g.calcDevSubsidy(fullSubsidy, blockHeight, numVotes) 423 powSubsidy := g.calcPoWSubsidy(fullSubsidy, blockHeight, numVotes) 424 425 tx := wire.NewMsgTx() 426 tx.AddTxIn(&wire.TxIn{ 427 // Coinbase transactions have no inputs, so previous outpoint is 428 // zero hash and max index. 429 PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, 430 wire.MaxPrevOutIndex, wire.TxTreeRegular), 431 Sequence: wire.MaxTxInSequenceNum, 432 ValueIn: int64(devSubsidy + powSubsidy), 433 BlockHeight: wire.NullBlockHeight, 434 BlockIndex: wire.NullBlockIndex, 435 SignatureScript: coinbaseSigScript, 436 }) 437 438 g.addCoinbaseTxOutputs(tx, blockHeight, devSubsidy, powSubsidy) 439 440 return tx 441 } 442 443 // PurchaseCommitmentScript returns a standard provably-pruneable OP_RETURN 444 // commitment script suitable for use in a ticket purchase tx (sstx) using the 445 // provided target address, amount, and fee limits. 446 func PurchaseCommitmentScript(addr dcrutil.Address, amount, voteFeeLimit, revocationFeeLimit dcrutil.Amount) []byte { 447 // The limits are defined in terms of the closest base 2 exponent and 448 // a bit that must be set to specify the limit is to be applied. The 449 // vote fee exponent is in the bottom 8 bits, while the revocation fee 450 // exponent is in the upper 8 bits. 451 limits := uint16(0) 452 if voteFeeLimit != 0 { 453 exp := uint16(math.Ceil(math.Log2(float64(voteFeeLimit)))) 454 limits |= (exp | 0x40) 455 } 456 if revocationFeeLimit != 0 { 457 exp := uint16(math.Ceil(math.Log2(float64(revocationFeeLimit)))) 458 limits |= ((exp | 0x40) << 8) 459 } 460 461 // The data consists of the 20-byte raw script address for the given 462 // address, 8 bytes for the amount to commit to (with the upper bit flag 463 // set to indicate a pay-to-script-hash address), and 2 bytes for the 464 // fee limits. 465 var data [30]byte 466 copy(data[:], addr.ScriptAddress()) 467 binary.LittleEndian.PutUint64(data[20:], uint64(amount)) 468 data[27] |= 1 << 7 469 binary.LittleEndian.PutUint16(data[28:], limits) 470 script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_RETURN). 471 AddData(data[:]).Script() 472 if err != nil { 473 panic(err) 474 } 475 return script 476 } 477 478 // CreateTicketPurchaseTx creates a new transaction that spends the provided 479 // output to purchase a stake submission ticket (sstx) at the given ticket 480 // price. Both the ticket and the change will go to a p2sh script that is 481 // composed with a single OP_TRUE. 482 // 483 // The transaction consists of the following outputs: 484 // - First output is an OP_SSTX followed by the OP_TRUE p2sh script hash 485 // - Second output is an OP_RETURN followed by the commitment script 486 // - Third output is an OP_SSTXCHANGE followed by the OP_TRUE p2sh script hash 487 func (g *Generator) CreateTicketPurchaseTx(spend *SpendableOut, ticketPrice, fee dcrutil.Amount) *wire.MsgTx { 488 // The first output is the voting rights address. This impl uses the 489 // standard pay-to-script-hash to an OP_TRUE. 490 pkScript, err := txscript.PayToSStx(g.p2shOpTrueAddr) 491 if err != nil { 492 panic(err) 493 } 494 495 // Generate the commitment script. 496 commitScript := PurchaseCommitmentScript(g.p2shOpTrueAddr, 497 ticketPrice+fee, 0, ticketPrice) 498 499 // Calculate change and generate script to deliver it. 500 change := spend.amount - ticketPrice - fee 501 changeScript, err := txscript.PayToSStxChange(g.p2shOpTrueAddr) 502 if err != nil { 503 panic(err) 504 } 505 506 // Generate and return the transaction spending from the provided 507 // spendable output with the previously described outputs. 508 tx := wire.NewMsgTx() 509 tx.AddTxIn(&wire.TxIn{ 510 PreviousOutPoint: spend.prevOut, 511 Sequence: wire.MaxTxInSequenceNum, 512 ValueIn: int64(spend.amount), 513 BlockHeight: spend.blockHeight, 514 BlockIndex: spend.blockIndex, 515 SignatureScript: opTrueRedeemScript, 516 }) 517 tx.AddTxOut(wire.NewTxOut(int64(ticketPrice), pkScript)) 518 tx.AddTxOut(wire.NewTxOut(0, commitScript)) 519 tx.AddTxOut(wire.NewTxOut(int64(change), changeScript)) 520 return tx 521 } 522 523 // isTicketPurchaseTx returns whether or not the passed transaction is a stake 524 // ticket purchase. 525 // 526 // NOTE: Like many other functions in this test code, this function 527 // intentionally does not use the blockchain/stake package code since the intent 528 // is to be able to generate known good tests which exercise that code, so it 529 // wouldn't make sense to use the same code to generate them. It must also be 530 // noted that this function is NOT robust. It is the minimum necessary needed 531 // by the testing framework. 532 func isTicketPurchaseTx(tx *wire.MsgTx) bool { 533 if len(tx.TxOut) == 0 { 534 return false 535 } 536 txOut := tx.TxOut[0] 537 scriptClass := txscript.GetScriptClass(txOut.Version, txOut.PkScript) 538 return scriptClass == txscript.StakeSubmissionTy 539 } 540 541 // isVoteTx returns whether or not the passed tx is a stake vote (ssgen). 542 // 543 // NOTE: Like many other functions in this test code, this function 544 // intentionally does not use the blockchain/stake package code since the intent 545 // is to be able to generate known good tests which exercise that code, so it 546 // wouldn't make sense to use the same code to generate them. It must also be 547 // noted that this function is NOT robust. It is the minimum necessary needed 548 // by the testing framework. 549 func isVoteTx(tx *wire.MsgTx) bool { 550 if len(tx.TxOut) < 3 { 551 return false 552 } 553 txOut := tx.TxOut[2] 554 scriptClass := txscript.GetScriptClass(txOut.Version, txOut.PkScript) 555 return scriptClass == txscript.StakeGenTy 556 } 557 558 // isRevocationTx returns whether or not the passed tx is a stake ticket 559 // revocation (ssrtx). 560 // 561 // NOTE: Like many other functions in this test code, this function 562 // intentionally does not use the blockchain/stake package code since the intent 563 // is to be able to generate known good tests which exercise that code, so it 564 // wouldn't make sense to use the same code to generate them. It must also be 565 // noted that this function is NOT robust. It is the minimum necessary needed 566 // by the testing framework. 567 func isRevocationTx(tx *wire.MsgTx) bool { 568 if len(tx.TxOut) == 0 { 569 return false 570 } 571 txOut := tx.TxOut[0] 572 scriptClass := txscript.GetScriptClass(txOut.Version, txOut.PkScript) 573 return scriptClass == txscript.StakeRevocationTy 574 } 575 576 // VoteCommitmentScript returns a standard provably-pruneable OP_RETURN script 577 // suitable for use in a vote tx (ssgen) given the block hash and height to vote 578 // on. 579 func VoteCommitmentScript(hash chainhash.Hash, height uint32) []byte { 580 // The vote commitment consists of a 32-byte hash of the block it is 581 // voting on along with its expected height as a 4-byte little-endian 582 // uint32. 32-byte hash + 4-byte uint32 = 36 bytes. 583 var data [36]byte 584 copy(data[:], hash[:]) 585 binary.LittleEndian.PutUint32(data[32:], height) 586 script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_RETURN). 587 AddData(data[:]).Script() 588 if err != nil { 589 panic(err) 590 } 591 return script 592 } 593 594 // voteBlockScript returns a standard provably-pruneable OP_RETURN script 595 // suitable for use in a vote tx (ssgen) given the block to vote on. 596 func voteBlockScript(parentBlock *wire.MsgBlock) []byte { 597 return VoteCommitmentScript(parentBlock.BlockHash(), 598 parentBlock.Header.Height) 599 } 600 601 // voteBitsScript returns a standard provably-pruneable OP_RETURN script 602 // suitable for use in a vote tx (ssgen) with the appropriate vote bits set 603 // depending on the provided params. 604 func voteBitsScript(bits uint16, voteVersion uint32) []byte { 605 data := make([]byte, 6) 606 binary.LittleEndian.PutUint16(data, bits) 607 binary.LittleEndian.PutUint32(data[2:], voteVersion) 608 if voteVersion == 0 { 609 data = data[:2] 610 } 611 script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_RETURN). 612 AddData(data).Script() 613 if err != nil { 614 panic(err) 615 } 616 return script 617 } 618 619 // CreateVoteTx returns a new transaction (ssgen) paying an appropriate subsidy 620 // for the given block height (and the number of votes per block) as well as the 621 // original commitments. 622 // 623 // The transaction consists of the following outputs: 624 // - First output is an OP_RETURN followed by the block hash and height 625 // - Second output is an OP_RETURN followed by the vote bits 626 // - Third and subsequent outputs are the payouts according to the ticket 627 // commitments and the appropriate proportion of the vote subsidy. 628 func (g *Generator) CreateVoteTx(voteBlock *wire.MsgBlock, ticketTx *wire.MsgTx, ticketBlockHeight, ticketBlockIndex uint32) *wire.MsgTx { 629 // Calculate the proof-of-stake subsidy proportion based on the block 630 // height. 631 posSubsidy := g.calcPoSSubsidy(voteBlock.Header.Height) 632 voteSubsidy := posSubsidy / dcrutil.Amount(g.params.TicketsPerBlock) 633 ticketPrice := dcrutil.Amount(ticketTx.TxOut[0].Value) 634 635 // The first output is the block (hash and height) the vote is for. 636 blockScript := voteBlockScript(voteBlock) 637 638 // The second output is the vote bits. 639 voteScript := voteBitsScript(voteBitYes, 0) 640 641 // The third and subsequent outputs pay the original commitment amounts 642 // along with the appropriate portion of the vote subsidy. This impl 643 // uses the standard pay-to-script-hash to an OP_TRUE. 644 stakeGenScript, err := txscript.PayToSSGen(g.p2shOpTrueAddr) 645 if err != nil { 646 panic(err) 647 } 648 649 // Generate and return the transaction with the proof-of-stake subsidy 650 // coinbase and spending from the provided ticket along with the 651 // previously described outputs. 652 ticketHash := ticketTx.CachedTxHash() 653 tx := wire.NewMsgTx() 654 tx.AddTxIn(&wire.TxIn{ 655 PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, 656 wire.MaxPrevOutIndex, wire.TxTreeRegular), 657 Sequence: wire.MaxTxInSequenceNum, 658 ValueIn: int64(voteSubsidy), 659 BlockHeight: wire.NullBlockHeight, 660 BlockIndex: wire.NullBlockIndex, 661 SignatureScript: g.params.StakeBaseSigScript, 662 }) 663 tx.AddTxIn(&wire.TxIn{ 664 PreviousOutPoint: *wire.NewOutPoint(ticketHash, 0, 665 wire.TxTreeStake), 666 Sequence: wire.MaxTxInSequenceNum, 667 ValueIn: int64(ticketPrice), 668 BlockHeight: ticketBlockHeight, 669 BlockIndex: ticketBlockIndex, 670 SignatureScript: opTrueRedeemScript, 671 }) 672 tx.AddTxOut(wire.NewTxOut(0, blockScript)) 673 tx.AddTxOut(wire.NewTxOut(0, voteScript)) 674 tx.AddTxOut(wire.NewTxOut(int64(voteSubsidy+ticketPrice), stakeGenScript)) 675 return tx 676 } 677 678 // createVoteTxFromTicket returns a new transaction (ssgen) paying an appropriate subsidy 679 // for the given block height (and the number of votes per block) as well as the 680 // original commitments. It requires a stake ticket as a parameter. 681 func (g *Generator) createVoteTxFromTicket(voteBlock *wire.MsgBlock, ticket *stakeTicket) *wire.MsgTx { 682 return g.CreateVoteTx(voteBlock, ticket.tx, ticket.blockHeight, ticket.blockIndex) 683 } 684 685 // CreateRevocationTx returns a new transaction (ssrtx) refunding the ticket 686 // price for a ticket which either missed its vote or expired. 687 // 688 // The transaction consists of the following inputs: 689 // - The outpoint of the ticket that was missed or expired. 690 // 691 // The transaction consists of the following outputs: 692 // - The payouts according to the ticket commitments. 693 func (g *Generator) CreateRevocationTx(ticketTx *wire.MsgTx, ticketBlockHeight, ticketBlockIndex uint32) *wire.MsgTx { 694 // The outputs pay the original commitment amounts. This impl uses the 695 // standard pay-to-script-hash to an OP_TRUE. 696 revokeScript, err := txscript.PayToSSRtx(g.p2shOpTrueAddr) 697 if err != nil { 698 panic(err) 699 } 700 701 // Generate and return the transaction spending from the provided ticket 702 // along with the previously described outputs. 703 ticketPrice := ticketTx.TxOut[0].Value 704 ticketHash := ticketTx.CachedTxHash() 705 tx := wire.NewMsgTx() 706 tx.AddTxIn(&wire.TxIn{ 707 PreviousOutPoint: *wire.NewOutPoint(ticketHash, 0, 708 wire.TxTreeStake), 709 Sequence: wire.MaxTxInSequenceNum, 710 ValueIn: ticketPrice, 711 BlockHeight: ticketBlockHeight, 712 BlockIndex: ticketBlockIndex, 713 SignatureScript: opTrueRedeemScript, 714 }) 715 tx.AddTxOut(wire.NewTxOut(ticketPrice, revokeScript)) 716 return tx 717 } 718 719 // CreateRevocationTxFromTicket returns a new transaction (ssrtx) refunding 720 // the ticket price for a ticket which either missed its vote or expired. 721 // It requires a stake ticket as a parameter. 722 func (g *Generator) createRevocationTxFromTicket(ticket *stakeTicket) *wire.MsgTx { 723 return g.CreateRevocationTx(ticket.tx, ticket.blockHeight, ticket.blockIndex) 724 } 725 726 // ancestorBlock returns the ancestor block at the provided height by following 727 // the chain backwards from the given block. The returned block will be nil 728 // when a height is requested that is after the height of the passed block. 729 // Also, a callback can optionally be provided that is invoked with each block 730 // as it traverses. 731 func (g *Generator) ancestorBlock(block *wire.MsgBlock, height uint32, f func(*wire.MsgBlock)) *wire.MsgBlock { 732 // Nothing to do if the requested height is outside of the valid 733 // range. 734 if block == nil || height > block.Header.Height { 735 return nil 736 } 737 738 // Iterate backwards until the requested height is reached. 739 for block != nil && block.Header.Height > height { 740 block = g.blocks[block.Header.PrevBlock] 741 if f != nil && block != nil { 742 f(block) 743 } 744 } 745 746 return block 747 } 748 749 // mergeDifficulty takes an original stake difficulty and two new, scaled 750 // stake difficulties, merges the new difficulties, and outputs a new 751 // merged stake difficulty. 752 func mergeDifficulty(oldDiff int64, newDiff1 int64, newDiff2 int64) int64 { 753 newDiff1Big := big.NewInt(newDiff1) 754 newDiff2Big := big.NewInt(newDiff2) 755 newDiff2Big.Lsh(newDiff2Big, 32) 756 757 oldDiffBig := big.NewInt(oldDiff) 758 oldDiffBigLSH := big.NewInt(oldDiff) 759 oldDiffBigLSH.Lsh(oldDiffBig, 32) 760 761 newDiff1Big.Div(oldDiffBigLSH, newDiff1Big) 762 newDiff2Big.Div(newDiff2Big, oldDiffBig) 763 764 // Combine the two changes in difficulty. 765 summedChange := big.NewInt(0) 766 summedChange.Set(newDiff2Big) 767 summedChange.Lsh(summedChange, 32) 768 summedChange.Div(summedChange, newDiff1Big) 769 summedChange.Mul(summedChange, oldDiffBig) 770 summedChange.Rsh(summedChange, 32) 771 772 return summedChange.Int64() 773 } 774 775 // limitRetarget clamps the passed new difficulty to the old one adjusted by the 776 // factor specified in the chain parameters. This ensures the difficulty can 777 // only move up or down by a limited amount. 778 func (g *Generator) limitRetarget(oldDiff, newDiff int64) int64 { 779 maxRetarget := g.params.RetargetAdjustmentFactor 780 switch { 781 case newDiff == 0: 782 fallthrough 783 case (oldDiff / newDiff) > (maxRetarget - 1): 784 return oldDiff / maxRetarget 785 case (newDiff / oldDiff) > (maxRetarget - 1): 786 return oldDiff * maxRetarget 787 } 788 789 return newDiff 790 } 791 792 // CalcNextRequiredDifficulty returns the required proof-of-work difficulty for 793 // the block after the current tip block the generator is associated with. 794 // 795 // An overview of the algorithm is as follows: 796 // 1) Use the proof-of-work limit for all blocks before the first retarget 797 // window 798 // 2) Use the previous block's difficulty if the next block is not at a retarget 799 // interval 800 // 3) Calculate the ideal retarget difficulty for each window based on the 801 // actual timespan of the window versus the target timespan and exponentially 802 // weight each difficulty such that the most recent window has the highest 803 // weight 804 // 4) Calculate the final retarget difficulty based on the exponential weighted 805 // average and ensure it is limited to the max retarget adjustment factor 806 func (g *Generator) CalcNextRequiredDifficulty() uint32 { 807 // Target difficulty before the first retarget interval is the pow 808 // limit. 809 nextHeight := g.tip.Header.Height + 1 810 windowSize := g.params.WorkDiffWindowSize 811 if int64(nextHeight) < windowSize { 812 return g.params.PowLimitBits 813 } 814 815 // Return the previous block's difficulty requirements if the next block 816 // is not at a difficulty retarget interval. 817 curDiff := int64(g.tip.Header.Bits) 818 if int64(nextHeight)%windowSize != 0 { 819 return uint32(curDiff) 820 } 821 822 // Calculate the ideal retarget difficulty for each window based on the 823 // actual time between blocks versus the target time and exponentially 824 // weight them. 825 adjustedTimespan := big.NewInt(0) 826 tempBig := big.NewInt(0) 827 weightedTimespanSum, weightSum := big.NewInt(0), big.NewInt(0) 828 targetTimespan := int64(g.params.TargetTimespan) 829 targetTimespanBig := big.NewInt(targetTimespan) 830 numWindows := g.params.WorkDiffWindows 831 weightAlpha := g.params.WorkDiffAlpha 832 block := g.tip 833 finalWindowTime := block.Header.Timestamp.UnixNano() 834 for i := int64(0); i < numWindows; i++ { 835 // Get the timestamp of the block at the start of the window and 836 // calculate the actual timespan accordingly. Use the target 837 // timespan if there are not yet enough blocks left to cover the 838 // window. 839 actualTimespan := targetTimespan 840 if int64(block.Header.Height) > windowSize { 841 for j := int64(0); j < windowSize; j++ { 842 block = g.blocks[block.Header.PrevBlock] 843 } 844 startWindowTime := block.Header.Timestamp.UnixNano() 845 actualTimespan = finalWindowTime - startWindowTime 846 847 // Set final window time for the next window. 848 finalWindowTime = startWindowTime 849 } 850 851 // Calculate the ideal retarget difficulty for the window based 852 // on the actual timespan and weight it exponentially by 853 // multiplying it by 2^(window_number) such that the most recent 854 // window receives the most weight. 855 // 856 // Also, since integer division is being used, shift up the 857 // number of new tickets 32 bits to avoid losing precision. 858 // 859 // windowWeightShift = ((numWindows - i) * weightAlpha) 860 // adjustedTimespan = (actualTimespan << 32) / targetTimespan 861 // weightedTimespanSum += adjustedTimespan << windowWeightShift 862 // weightSum += 1 << windowWeightShift 863 windowWeightShift := uint((numWindows - i) * weightAlpha) 864 adjustedTimespan.SetInt64(actualTimespan) 865 adjustedTimespan.Lsh(adjustedTimespan, 32) 866 adjustedTimespan.Div(adjustedTimespan, targetTimespanBig) 867 adjustedTimespan.Lsh(adjustedTimespan, windowWeightShift) 868 weightedTimespanSum.Add(weightedTimespanSum, adjustedTimespan) 869 weight := tempBig.SetInt64(1) 870 weight.Lsh(weight, windowWeightShift) 871 weightSum.Add(weightSum, weight) 872 } 873 874 // Calculate the retarget difficulty based on the exponential weighted 875 // average and shift the result back down 32 bits to account for the 876 // previous shift up in order to avoid losing precision. Then, limit it 877 // to the maximum allowed retarget adjustment factor. 878 // 879 // nextDiff = (weightedTimespanSum/weightSum * curDiff) >> 32 880 curDiffBig := tempBig.SetInt64(curDiff) 881 weightedTimespanSum.Div(weightedTimespanSum, weightSum) 882 weightedTimespanSum.Mul(weightedTimespanSum, curDiffBig) 883 weightedTimespanSum.Rsh(weightedTimespanSum, 32) 884 nextDiff := weightedTimespanSum.Int64() 885 nextDiff = g.limitRetarget(curDiff, nextDiff) 886 887 if nextDiff > int64(g.params.PowLimitBits) { 888 return g.params.PowLimitBits 889 } 890 return uint32(nextDiff) 891 } 892 893 // CalcNextReqStakeDifficulty returns the required stake difficulty (aka 894 // ticket price) for the block after the provided block the generator is 895 // associated with. 896 // 897 // See the documentation of CalcNextRequiredStakeDifficulty for more details. 898 func (g *Generator) CalcNextReqStakeDifficulty(prevBlock *wire.MsgBlock) int64 { 899 // Stake difficulty before any tickets could possibly be purchased is 900 // the minimum value. 901 nextHeight := prevBlock.Header.Height + 1 902 stakeDiffStartHeight := uint32(g.params.CoinbaseMaturity) + 1 903 if nextHeight < stakeDiffStartHeight { 904 return g.params.MinimumStakeDiff 905 } 906 907 // Return 0 if the current difficulty is already zero since any scaling 908 // of 0 is still 0. This should never really happen since there is a 909 // minimum stake difficulty, but the consensus code checks the condition 910 // just in case, so follow suit here. 911 curDiff := g.tip.Header.SBits 912 if curDiff == 0 { 913 return 0 914 } 915 916 // Return the previous block's difficulty requirements if the next block 917 // is not at a difficulty retarget interval. 918 windowSize := g.params.StakeDiffWindowSize 919 if int64(nextHeight)%windowSize != 0 { 920 return curDiff 921 } 922 923 // -------------------------------- 924 // Ideal pool size retarget metric. 925 // -------------------------------- 926 927 // Calculate the ideal retarget difficulty for each window based on the 928 // actual pool size in the window versus the target pool size and 929 // exponentially weight them. 930 var weightedPoolSizeSum, weightSum uint64 931 ticketsPerBlock := int64(g.params.TicketsPerBlock) 932 targetPoolSize := ticketsPerBlock * int64(g.params.TicketPoolSize) 933 block := prevBlock 934 numWindows := g.params.StakeDiffWindows 935 weightAlpha := g.params.StakeDiffAlpha 936 for i := int64(0); i < numWindows; i++ { 937 // Get the pool size for the block at the start of the window. 938 // Use zero if there are not yet enough blocks left to cover the 939 // window. 940 prevRetargetHeight := nextHeight - uint32(windowSize*(i+1)) 941 windowPoolSize := int64(0) 942 block = g.ancestorBlock(block, prevRetargetHeight, nil) 943 if block != nil { 944 windowPoolSize = int64(block.Header.PoolSize) 945 } 946 947 // Skew the pool size by the constant weight factor specified in 948 // the chain parameters (which is typically the max adjustment 949 // factor) in order to help weight the ticket pool size versus 950 // tickets per block. Also, ensure the skewed pool size is a 951 // minimum of 1. 952 skewedPoolSize := targetPoolSize + (windowPoolSize- 953 targetPoolSize)*int64(g.params.TicketPoolSizeWeight) 954 if skewedPoolSize <= 0 { 955 skewedPoolSize = 1 956 } 957 958 // Calculate the ideal retarget difficulty for the window based 959 // on the skewed pool size and weight it exponentially by 960 // multiplying it by 2^(window_number) such that the most recent 961 // window receives the most weight. 962 // 963 // Also, since integer division is being used, shift up the 964 // number of new tickets 32 bits to avoid losing precision. 965 // 966 // NOTE: The real algorithm uses big ints, but these purpose 967 // built tests won't be using large enough values to overflow, 968 // so just use uint64s. 969 adjusted := (skewedPoolSize << 32) / targetPoolSize 970 adjusted <<= uint64((numWindows - i) * weightAlpha) 971 weightedPoolSizeSum += uint64(adjusted) 972 weightSum += 1 << uint64((numWindows-i)*weightAlpha) 973 } 974 975 // Calculate the pool size retarget difficulty based on the exponential 976 // weighted average and shift the result back down 32 bits to account 977 // for the previous shift up in order to avoid losing precision. Then, 978 // limit it to the maximum allowed retarget adjustment factor. 979 // 980 // This is the first metric used in the final calculated difficulty. 981 nextPoolSizeDiff := (int64(weightedPoolSizeSum/weightSum) * curDiff) >> 32 982 nextPoolSizeDiff = g.limitRetarget(curDiff, nextPoolSizeDiff) 983 984 // ----------------------------------------- 985 // Ideal tickets per window retarget metric. 986 // ----------------------------------------- 987 988 // Calculate the ideal retarget difficulty for each window based on the 989 // actual number of new tickets in the window versus the target tickets 990 // per window and exponentially weight them. 991 var weightedTicketsSum uint64 992 targetTicketsPerWindow := ticketsPerBlock * windowSize 993 block = prevBlock 994 for i := int64(0); i < numWindows; i++ { 995 // Since the difficulty for the next block after the current tip 996 // is being calculated and there is no such block yet, the sum 997 // of all new tickets in the first window needs to start with 998 // the number of new tickets in the tip block. 999 var windowNewTickets int64 1000 if i == 0 { 1001 windowNewTickets = int64(block.Header.FreshStake) 1002 } 1003 1004 // Tally all of the new tickets in all blocks in the window and 1005 // ensure the number of new tickets is a minimum of 1. 1006 prevRetargetHeight := nextHeight - uint32(windowSize*(i+1)) 1007 block = g.ancestorBlock(block, prevRetargetHeight, func(blk *wire.MsgBlock) { 1008 windowNewTickets += int64(blk.Header.FreshStake) 1009 }) 1010 if windowNewTickets <= 0 { 1011 windowNewTickets = 1 1012 } 1013 1014 // Calculate the ideal retarget difficulty for the window based 1015 // on the number of new tickets and weight it exponentially by 1016 // multiplying it by 2^(window_number) such that the most recent 1017 // window receives the most weight. 1018 // 1019 // Also, since integer division is being used, shift up the 1020 // number of new tickets 32 bits to avoid losing precision. 1021 // 1022 // NOTE: The real algorithm uses big ints, but these purpose 1023 // built tests won't be using large enough values to overflow, 1024 // so just use uint64s. 1025 adjusted := (windowNewTickets << 32) / targetTicketsPerWindow 1026 adjusted <<= uint64((numWindows - i) * weightAlpha) 1027 weightedTicketsSum += uint64(adjusted) 1028 } 1029 1030 // Calculate the tickets per window retarget difficulty based on the 1031 // exponential weighted average and shift the result back down 32 bits 1032 // to account for the previous shift up in order to avoid losing 1033 // precision. Then, limit it to the maximum allowed retarget adjustment 1034 // factor. 1035 // 1036 // This is the second metric used in the final calculated difficulty. 1037 nextNewTixDiff := (int64(weightedTicketsSum/weightSum) * curDiff) >> 32 1038 nextNewTixDiff = g.limitRetarget(curDiff, nextNewTixDiff) 1039 1040 // Average the previous two metrics using scaled multiplication and 1041 // ensure the result is limited to both the maximum allowed retarget 1042 // adjustment factor and the minimum allowed stake difficulty. 1043 nextDiff := mergeDifficulty(curDiff, nextPoolSizeDiff, nextNewTixDiff) 1044 nextDiff = g.limitRetarget(curDiff, nextDiff) 1045 if nextDiff < g.params.MinimumStakeDiff { 1046 return g.params.MinimumStakeDiff 1047 } 1048 return nextDiff 1049 } 1050 1051 // CalcNextRequiredStakeDifficulty returns the required stake difficulty (aka 1052 // ticket price) for the block after the current tip block the generator is 1053 // associated with. 1054 // 1055 // An overview of the algorithm is as follows: 1056 // 1) Use the minimum value for any blocks before any tickets could have 1057 // possibly been purchased due to coinbase maturity requirements 1058 // 2) Return 0 if the current tip block stake difficulty is 0. This is a 1059 // safety check against a condition that should never actually happen. 1060 // 3) Use the previous block's difficulty if the next block is not at a retarget 1061 // interval 1062 // 4) Calculate the ideal retarget difficulty for each window based on the 1063 // actual pool size in the window versus the target pool size skewed by a 1064 // constant factor to weight the ticket pool size instead of the tickets per 1065 // block and exponentially weight each difficulty such that the most recent 1066 // window has the highest weight 1067 // 5) Calculate the pool size retarget difficulty based on the exponential 1068 // weighted average and ensure it is limited to the max retarget adjustment 1069 // factor -- This is the first metric used to calculate the final difficulty 1070 // 6) Calculate the ideal retarget difficulty for each window based on the 1071 // actual new tickets in the window versus the target new tickets per window 1072 // and exponentially weight each difficulty such that the most recent window 1073 // has the highest weight 1074 // 7) Calculate the tickets per window retarget difficulty based on the 1075 // exponential weighted average and ensure it is limited to the max retarget 1076 // adjustment factor 1077 // 8) Calculate the final difficulty by averaging the pool size retarget 1078 // difficulty from #5 and the tickets per window retarget difficulty from #7 1079 // using scaled multiplication and ensure it is limited to the max retarget 1080 // adjustment factor 1081 // 1082 // NOTE: In order to simplify the test code, this implementation does not use 1083 // big integers so it will NOT match the actual consensus code for really big 1084 // numbers. However, the parameters on simnet and the pool sizes used in these 1085 // tests are low enough that this is not an issue for the tests. Anyone looking 1086 // at this code should NOT use it for mainnet calculations as is since it will 1087 // not always yield the correct results. 1088 func (g *Generator) CalcNextRequiredStakeDifficulty() int64 { 1089 return g.CalcNextReqStakeDifficulty(g.tip) 1090 } 1091 1092 // hash256prng is a determinstic pseudorandom number generator that uses a 1093 // 256-bit secure hashing function to generate random uint32s starting from 1094 // an initial seed. 1095 type hash256prng struct { 1096 seed chainhash.Hash // Initialization seed 1097 idx uint64 // Hash iterator index 1098 cachedHash chainhash.Hash // Most recently generated hash 1099 hashOffset int // Offset into most recently generated hash 1100 } 1101 1102 // newHash256PRNG creates a pointer to a newly created hash256PRNG. 1103 func newHash256PRNG(seed []byte) *hash256prng { 1104 // The provided seed is initialized by appending a constant derived from 1105 // the hex representation of pi and hashing the result to give 32 bytes. 1106 // This ensures the PRNG is always doing a short number of rounds 1107 // regardless of input since it will only need to hash small messages 1108 // (less than 64 bytes). 1109 seedHash := chainhash.HashFunc(append(seed, hash256prngSeedConst...)) 1110 return &hash256prng{ 1111 seed: seedHash, 1112 idx: 0, 1113 cachedHash: seedHash, 1114 } 1115 } 1116 1117 // State returns a hash that represents the current state of the deterministic 1118 // PRNG. 1119 func (hp *hash256prng) State() chainhash.Hash { 1120 // The final state is the hash of the most recently generated hash 1121 // concatenated with both the hash iterator index and the offset into 1122 // the hash. 1123 // 1124 // hash(hp.cachedHash || hp.idx || hp.hashOffset) 1125 finalState := make([]byte, len(hp.cachedHash)+4+1) 1126 copy(finalState, hp.cachedHash[:]) 1127 offset := len(hp.cachedHash) 1128 binary.BigEndian.PutUint32(finalState[offset:], uint32(hp.idx)) 1129 offset += 4 1130 finalState[offset] = byte(hp.hashOffset) 1131 return chainhash.HashH(finalState) 1132 } 1133 1134 // Hash256Rand returns a uint32 random number using the pseudorandom number 1135 // generator and updates the state. 1136 func (hp *hash256prng) Hash256Rand() uint32 { 1137 offset := hp.hashOffset * 4 1138 r := binary.BigEndian.Uint32(hp.cachedHash[offset : offset+4]) 1139 hp.hashOffset++ 1140 1141 // Generate a new hash and reset the hash position index once it would 1142 // overflow the available bytes in the most recently generated hash. 1143 if hp.hashOffset > 7 { 1144 // Hash of the seed concatenated with the hash iterator index. 1145 // hash(hp.seed || hp.idx) 1146 data := make([]byte, len(hp.seed)+4) 1147 copy(data, hp.seed[:]) 1148 binary.BigEndian.PutUint32(data[len(hp.seed):], uint32(hp.idx)) 1149 hp.cachedHash = chainhash.HashH(data) 1150 hp.idx++ 1151 hp.hashOffset = 0 1152 } 1153 1154 // Roll over the entire PRNG by re-hashing the seed when the hash 1155 // iterator index overlows a uint32. 1156 if hp.idx > math.MaxUint32 { 1157 hp.seed = chainhash.HashH(hp.seed[:]) 1158 hp.cachedHash = hp.seed 1159 hp.idx = 0 1160 } 1161 1162 return r 1163 } 1164 1165 // uniformRandom returns a random in the range [0, upperBound) while avoiding 1166 // modulo bias to ensure a normal distribution within the specified range. 1167 func (hp *hash256prng) uniformRandom(upperBound uint32) uint32 { 1168 if upperBound < 2 { 1169 return 0 1170 } 1171 1172 // (2^32 - (x*2)) % x == 2^32 % x when x <= 2^31 1173 min := ((math.MaxUint32 - (upperBound * 2)) + 1) % upperBound 1174 if upperBound > 0x80000000 { 1175 min = 1 + ^upperBound 1176 } 1177 1178 r := hp.Hash256Rand() 1179 for r < min { 1180 r = hp.Hash256Rand() 1181 } 1182 return r % upperBound 1183 } 1184 1185 // winningTickets returns a slice of tickets that are required to vote for the 1186 // given block being voted on and live ticket pool and the associated underlying 1187 // deterministic prng state hash. 1188 func winningTickets(voteBlock *wire.MsgBlock, liveTickets []*stakeTicket, numVotes uint16) ([]*stakeTicket, chainhash.Hash, error) { 1189 // Serialize the parent block header used as the seed to the 1190 // deterministic pseudo random number generator for vote selection. 1191 var buf bytes.Buffer 1192 buf.Grow(wire.MaxBlockHeaderPayload) 1193 if err := voteBlock.Header.Serialize(&buf); err != nil { 1194 return nil, chainhash.Hash{}, err 1195 } 1196 1197 // Ensure the number of live tickets is within the allowable range. 1198 numLiveTickets := uint32(len(liveTickets)) 1199 if numLiveTickets > math.MaxUint32 { 1200 return nil, chainhash.Hash{}, fmt.Errorf("live ticket pool "+ 1201 "has %d tickets which is more than the max allowed of "+ 1202 "%d", len(liveTickets), uint32(math.MaxUint32)) 1203 } 1204 if uint32(numVotes) > numLiveTickets { 1205 return nil, chainhash.Hash{}, fmt.Errorf("live ticket pool "+ 1206 "has %d tickets, while %d are needed to vote", 1207 len(liveTickets), numVotes) 1208 } 1209 1210 // Construct list of winners by generating successive values from the 1211 // deterministic prng and using them as indices into the sorted live 1212 // ticket pool while skipping any duplicates that might occur. 1213 prng := newHash256PRNG(buf.Bytes()) 1214 winners := make([]*stakeTicket, 0, numVotes) 1215 usedOffsets := make(map[uint32]struct{}) 1216 for uint16(len(winners)) < numVotes { 1217 ticketIndex := prng.uniformRandom(numLiveTickets) 1218 if _, exists := usedOffsets[ticketIndex]; !exists { 1219 usedOffsets[ticketIndex] = struct{}{} 1220 winners = append(winners, liveTickets[ticketIndex]) 1221 } 1222 } 1223 return winners, prng.State(), nil 1224 } 1225 1226 // calcFinalLotteryState calculates the final lottery state for a set of winning 1227 // tickets and the associated deterministic prng state hash after selecting the 1228 // winners. It is the first 6 bytes of: 1229 // blake256(firstTicketHash || ... || lastTicketHash || prngStateHash) 1230 func calcFinalLotteryState(winners []*stakeTicket, prngStateHash chainhash.Hash) [6]byte { 1231 data := make([]byte, (len(winners)+1)*chainhash.HashSize) 1232 for i := 0; i < len(winners); i++ { 1233 h := winners[i].tx.CachedTxHash() 1234 copy(data[chainhash.HashSize*i:], h[:]) 1235 } 1236 copy(data[chainhash.HashSize*len(winners):], prngStateHash[:]) 1237 dataHash := chainhash.HashH(data) 1238 1239 var finalState [6]byte 1240 copy(finalState[:], dataHash[0:6]) 1241 return finalState 1242 } 1243 1244 // nextPowerOfTwo returns the next highest power of two from a given number if 1245 // it is not already a power of two. This is a helper function used during the 1246 // calculation of a merkle tree. 1247 func nextPowerOfTwo(n int) int { 1248 // Return the number if it's already a power of 2. 1249 if n&(n-1) == 0 { 1250 return n 1251 } 1252 1253 // Figure out and return the next power of two. 1254 exponent := uint(math.Log2(float64(n))) + 1 1255 return 1 << exponent // 2^exponent 1256 } 1257 1258 // hashMerkleBranches takes two hashes, treated as the left and right tree 1259 // nodes, and returns the hash of their concatenation. This is a helper 1260 // function used to aid in the generation of a merkle tree. 1261 func hashMerkleBranches(left *chainhash.Hash, right *chainhash.Hash) *chainhash.Hash { 1262 // Concatenate the left and right nodes. 1263 var hash [chainhash.HashSize * 2]byte 1264 copy(hash[:chainhash.HashSize], left[:]) 1265 copy(hash[chainhash.HashSize:], right[:]) 1266 1267 newHash := chainhash.HashH(hash[:]) 1268 return &newHash 1269 } 1270 1271 // buildMerkleTreeStore creates a merkle tree from a slice of transactions, 1272 // stores it using a linear array, and returns a slice of the backing array. A 1273 // linear array was chosen as opposed to an actual tree structure since it uses 1274 // about half as much memory. The following describes a merkle tree and how it 1275 // is stored in a linear array. 1276 // 1277 // A merkle tree is a tree in which every non-leaf node is the hash of its 1278 // children nodes. A diagram depicting how this works for Decred transactions 1279 // where h(x) is a blake256 hash follows: 1280 // 1281 // root = h1234 = h(h12 + h34) 1282 // / \ 1283 // h12 = h(h1 + h2) h34 = h(h3 + h4) 1284 // / \ / \ 1285 // h1 = h(tx1) h2 = h(tx2) h3 = h(tx3) h4 = h(tx4) 1286 // 1287 // The above stored as a linear array is as follows: 1288 // 1289 // [h1 h2 h3 h4 h12 h34 root] 1290 // 1291 // As the above shows, the merkle root is always the last element in the array. 1292 // 1293 // The number of inputs is not always a power of two which results in a 1294 // balanced tree structure as above. In that case, parent nodes with no 1295 // children are also zero and parent nodes with only a single left node 1296 // are calculated by concatenating the left node with itself before hashing. 1297 // Since this function uses nodes that are pointers to the hashes, empty nodes 1298 // will be nil. 1299 func buildMerkleTreeStore(transactions []*dcrutil.Tx) []*chainhash.Hash { 1300 // If there's an empty stake tree, return totally zeroed out merkle tree root 1301 // only. 1302 if len(transactions) == 0 { 1303 merkles := make([]*chainhash.Hash, 1) 1304 merkles[0] = &chainhash.Hash{} 1305 return merkles 1306 } 1307 1308 // Calculate how many entries are required to hold the binary merkle 1309 // tree as a linear array and create an array of that size. 1310 nextPoT := nextPowerOfTwo(len(transactions)) 1311 arraySize := nextPoT*2 - 1 1312 merkles := make([]*chainhash.Hash, arraySize) 1313 1314 // Create the base transaction hashes and populate the array with them. 1315 for i, tx := range transactions { 1316 msgTx := tx.MsgTx() 1317 txHashFull := msgTx.TxHashFull() 1318 merkles[i] = &txHashFull 1319 } 1320 1321 // Start the array offset after the last transaction and adjusted to the 1322 // next power of two. 1323 offset := nextPoT 1324 for i := 0; i < arraySize-1; i += 2 { 1325 switch { 1326 // When there is no left child node, the parent is nil too. 1327 case merkles[i] == nil: 1328 merkles[offset] = nil 1329 1330 // When there is no right child, the parent is generated by 1331 // hashing the concatenation of the left child with itself. 1332 case merkles[i+1] == nil: 1333 newHash := hashMerkleBranches(merkles[i], merkles[i]) 1334 merkles[offset] = newHash 1335 1336 // The normal case sets the parent node to the hash of the 1337 // concatenation of the left and right children. 1338 default: 1339 newHash := hashMerkleBranches(merkles[i], merkles[i+1]) 1340 merkles[offset] = newHash 1341 } 1342 offset++ 1343 } 1344 1345 return merkles 1346 } 1347 1348 // calcMerkleRoot creates a merkle tree from the slice of transactions and 1349 // returns the root of the tree. 1350 func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { 1351 utilTxns := make([]*dcrutil.Tx, 0, len(txns)) 1352 for _, tx := range txns { 1353 utilTxns = append(utilTxns, dcrutil.NewTx(tx)) 1354 } 1355 merkles := buildMerkleTreeStore(utilTxns) 1356 return *merkles[len(merkles)-1] 1357 } 1358 1359 // hashToBig converts a chainhash.Hash into a big.Int that can be used to 1360 // perform math comparisons. 1361 func hashToBig(hash *chainhash.Hash) *big.Int { 1362 // A Hash is in little-endian, but the big package wants the bytes in 1363 // big-endian, so reverse them. 1364 buf := *hash 1365 blen := len(buf) 1366 for i := 0; i < blen/2; i++ { 1367 buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] 1368 } 1369 1370 return new(big.Int).SetBytes(buf[:]) 1371 } 1372 1373 // compactToBig converts a compact representation of a whole number N to an 1374 // unsigned 32-bit number. The representation is similar to IEEE754 floating 1375 // point numbers. 1376 // 1377 // Like IEEE754 floating point, there are three basic components: the sign, 1378 // the exponent, and the mantissa. They are broken out as follows: 1379 // 1380 // * the most significant 8 bits represent the unsigned base 256 exponent 1381 // * bit 23 (the 24th bit) represents the sign bit 1382 // * the least significant 23 bits represent the mantissa 1383 // 1384 // ------------------------------------------------- 1385 // | Exponent | Sign | Mantissa | 1386 // ------------------------------------------------- 1387 // | 8 bits [31-24] | 1 bit [23] | 23 bits [22-00] | 1388 // ------------------------------------------------- 1389 // 1390 // The formula to calculate N is: 1391 // N = (-1^sign) * mantissa * 256^(exponent-3) 1392 // 1393 // This compact form is only used in Decred to encode unsigned 256-bit numbers 1394 // which represent difficulty targets, thus there really is not a need for a 1395 // sign bit, but it is implemented here to stay consistent with bitcoind. 1396 func compactToBig(compact uint32) *big.Int { 1397 // Extract the mantissa, sign bit, and exponent. 1398 mantissa := compact & 0x007fffff 1399 isNegative := compact&0x00800000 != 0 1400 exponent := uint(compact >> 24) 1401 1402 // Since the base for the exponent is 256, the exponent can be treated 1403 // as the number of bytes to represent the full 256-bit number. So, 1404 // treat the exponent as the number of bytes and shift the mantissa 1405 // right or left accordingly. This is equivalent to: 1406 // N = mantissa * 256^(exponent-3) 1407 var bn *big.Int 1408 if exponent <= 3 { 1409 mantissa >>= 8 * (3 - exponent) 1410 bn = big.NewInt(int64(mantissa)) 1411 } else { 1412 bn = big.NewInt(int64(mantissa)) 1413 bn.Lsh(bn, 8*(exponent-3)) 1414 } 1415 1416 // Make it negative if the sign bit is set. 1417 if isNegative { 1418 bn = bn.Neg(bn) 1419 } 1420 1421 return bn 1422 } 1423 1424 // IsSolved returns whether or not the header hashes to a value that is less 1425 // than or equal to the target difficulty as specified by its bits field. 1426 func IsSolved(header *wire.BlockHeader) bool { 1427 targetDifficulty := compactToBig(header.Bits) 1428 hash := header.BlockHash() 1429 return hashToBig(&hash).Cmp(targetDifficulty) <= 0 1430 } 1431 1432 // solveBlock attempts to find a nonce which makes the passed block header hash 1433 // to a value less than the target difficulty. When a successful solution is 1434 // found, true is returned and the nonce field of the passed header is updated 1435 // with the solution. False is returned if no solution exists. 1436 // 1437 // NOTE: This function will never solve blocks with a nonce of 0. This is done 1438 // so the 'NextBlock' function can properly detect when a nonce was modified by 1439 // a munge function. 1440 func solveBlock(header *wire.BlockHeader) bool { 1441 // sbResult is used by the solver goroutines to send results. 1442 type sbResult struct { 1443 found bool 1444 nonce uint32 1445 } 1446 1447 // solver accepts a block header and a nonce range to test. It is 1448 // intended to be run as a goroutine. 1449 targetDifficulty := compactToBig(header.Bits) 1450 quit := make(chan bool) 1451 results := make(chan sbResult) 1452 solver := func(hdr wire.BlockHeader, startNonce, stopNonce uint32) { 1453 // We need to modify the nonce field of the header, so make sure 1454 // we work with a copy of the original header. 1455 for i := startNonce; i >= startNonce && i <= stopNonce; i++ { 1456 select { 1457 case <-quit: 1458 results <- sbResult{false, 0} 1459 return 1460 default: 1461 hdr.Nonce = i 1462 hash := hdr.BlockHash() 1463 if hashToBig(&hash).Cmp( 1464 targetDifficulty) <= 0 { 1465 1466 results <- sbResult{true, i} 1467 return 1468 } 1469 } 1470 } 1471 results <- sbResult{false, 0} 1472 } 1473 1474 startNonce := uint32(1) 1475 stopNonce := uint32(math.MaxUint32) 1476 numCores := uint32(runtime.NumCPU()) 1477 noncesPerCore := (stopNonce - startNonce) / numCores 1478 for i := uint32(0); i < numCores; i++ { 1479 rangeStart := startNonce + (noncesPerCore * i) 1480 rangeStop := startNonce + (noncesPerCore * (i + 1)) - 1 1481 if i == numCores-1 { 1482 rangeStop = stopNonce 1483 } 1484 go solver(*header, rangeStart, rangeStop) 1485 } 1486 var foundResult bool 1487 for i := uint32(0); i < numCores; i++ { 1488 result := <-results 1489 if !foundResult && result.found { 1490 close(quit) 1491 header.Nonce = result.nonce 1492 foundResult = true 1493 } 1494 } 1495 1496 return foundResult 1497 } 1498 1499 // ReplaceWithNVotes returns a function that itself takes a block and modifies 1500 // it by replacing the votes in the stake tree with specified number of votes. 1501 // 1502 // NOTE: This must only be used as a munger to the 'NextBlock' function or it 1503 // will lead to an invalid live ticket pool. To help safeguard against improper 1504 // usage, it will panic if called with a block that does not connect to the 1505 // current tip block. 1506 func (g *Generator) ReplaceWithNVotes(numVotes uint16) func(*wire.MsgBlock) { 1507 return func(b *wire.MsgBlock) { 1508 // Attempt to prevent misuse of this function by ensuring the 1509 // provided block connects to the current tip. 1510 if b.Header.PrevBlock != g.tip.BlockHash() { 1511 panic(fmt.Sprintf("attempt to replace number of votes "+ 1512 "for block %s with parent %s that is not the "+ 1513 "current tip %s", b.BlockHash(), 1514 b.Header.PrevBlock, g.tip.BlockHash())) 1515 } 1516 1517 // Get the winning tickets for the specified number of votes. 1518 parentBlock := g.tip 1519 winners, _, err := winningTickets(parentBlock, g.liveTickets, 1520 numVotes) 1521 if err != nil { 1522 panic(err) 1523 } 1524 1525 // Generate vote transactions for the winning tickets. 1526 defaultNumVotes := int(g.params.TicketsPerBlock) 1527 numExisting := len(b.STransactions) - defaultNumVotes 1528 stakeTxns := make([]*wire.MsgTx, 0, numExisting+int(numVotes)) 1529 for _, ticket := range winners { 1530 voteTx := g.createVoteTxFromTicket(parentBlock, ticket) 1531 stakeTxns = append(stakeTxns, voteTx) 1532 } 1533 1534 // Add back the original stake transactions other than the 1535 // original stake votes that have been replaced. 1536 stakeTxns = append(stakeTxns, b.STransactions[defaultNumVotes:]...) 1537 1538 // Update the block with the new stake transactions and the 1539 // header with the new number of votes. 1540 b.STransactions = stakeTxns 1541 b.Header.Voters = numVotes 1542 1543 // Recalculate the coinbase amount based on the number of new 1544 // votes and update the coinbase so that the adjustment in 1545 // subsidy is accounted for. 1546 height := b.Header.Height 1547 fullSubsidy := g.calcFullSubsidy(height) 1548 devSubsidy := g.calcDevSubsidy(fullSubsidy, height, numVotes) 1549 powSubsidy := g.calcPoWSubsidy(fullSubsidy, height, numVotes) 1550 cbTx := b.Transactions[0] 1551 cbTx.TxIn[0].ValueIn = int64(devSubsidy + powSubsidy) 1552 cbTx.TxOut = nil 1553 g.addCoinbaseTxOutputs(cbTx, height, devSubsidy, powSubsidy) 1554 } 1555 } 1556 1557 // ReplaceVoteBitsN returns a function that itself takes a block and modifies 1558 // it by replacing the vote bits of the vote located at the provided index. It 1559 // will panic if the stake transaction at the provided index is not already a 1560 // vote. 1561 // 1562 // NOTE: This must only be used as a munger to the 'NextBlock' function or it 1563 // will lead to an invalid live ticket pool. 1564 func (g *Generator) ReplaceVoteBitsN(voteNum int, voteBits uint16) func(*wire.MsgBlock) { 1565 return func(b *wire.MsgBlock) { 1566 // Attempt to prevent misuse of this function by ensuring the 1567 // provided stake transaction number is actually a vote. 1568 stx := b.STransactions[voteNum] 1569 if !isVoteTx(stx) { 1570 panic(fmt.Sprintf("attempt to replace non-vote "+ 1571 "transaction #%d for for block %s", voteNum, 1572 b.BlockHash())) 1573 } 1574 1575 // Extract the existing vote version. 1576 existingScript := stx.TxOut[1].PkScript 1577 var voteVersion uint32 1578 if len(existingScript) >= 8 { 1579 voteVersion = binary.LittleEndian.Uint32(existingScript[4:8]) 1580 } 1581 1582 stx.TxOut[1].PkScript = voteBitsScript(voteBits, voteVersion) 1583 } 1584 } 1585 1586 // ReplaceBlockVersion returns a function that itself takes a block and modifies 1587 // it by replacing the stake version of the header. 1588 func ReplaceBlockVersion(newVersion int32) func(*wire.MsgBlock) { 1589 return func(b *wire.MsgBlock) { 1590 b.Header.Version = newVersion 1591 } 1592 } 1593 1594 // ReplaceStakeVersion returns a function that itself takes a block and modifies 1595 // it by replacing the stake version of the header. 1596 func ReplaceStakeVersion(newVersion uint32) func(*wire.MsgBlock) { 1597 return func(b *wire.MsgBlock) { 1598 b.Header.StakeVersion = newVersion 1599 } 1600 } 1601 1602 // ReplaceVoteVersions returns a function that itself takes a block and modifies 1603 // it by replacing the voter version of the stake transactions. 1604 // 1605 // NOTE: This must only be used as a munger to the 'NextBlock' function or it 1606 // will lead to an invalid live ticket pool. 1607 func ReplaceVoteVersions(newVersion uint32) func(*wire.MsgBlock) { 1608 return func(b *wire.MsgBlock) { 1609 for _, stx := range b.STransactions { 1610 if isVoteTx(stx) { 1611 stx.TxOut[1].PkScript = voteBitsScript( 1612 voteBitYes, newVersion) 1613 } 1614 } 1615 } 1616 } 1617 1618 // ReplaceVotes returns a function that itself takes a block and modifies it by 1619 // replacing the voter version and bits of the stake transactions. 1620 // 1621 // NOTE: This must only be used as a munger to the 'NextBlock' function or it 1622 // will lead to an invalid live ticket pool. 1623 func ReplaceVotes(voteBits uint16, newVersion uint32) func(*wire.MsgBlock) { 1624 return func(b *wire.MsgBlock) { 1625 for _, stx := range b.STransactions { 1626 if isVoteTx(stx) { 1627 stx.TxOut[1].PkScript = voteBitsScript(voteBits, 1628 newVersion) 1629 } 1630 } 1631 } 1632 } 1633 1634 // CreateSpendTx creates a transaction that spends from the provided spendable 1635 // output and includes an additional unique OP_RETURN output to ensure the 1636 // transaction ends up with a unique hash. The public key script is a simple 1637 // OP_TRUE p2sh script which avoids the need to track addresses and signature 1638 // scripts in the tests. The signature script is the opTrueRedeemScript. 1639 func (g *Generator) CreateSpendTx(spend *SpendableOut, fee dcrutil.Amount) *wire.MsgTx { 1640 spendTx := wire.NewMsgTx() 1641 spendTx.AddTxIn(&wire.TxIn{ 1642 PreviousOutPoint: spend.prevOut, 1643 Sequence: wire.MaxTxInSequenceNum, 1644 ValueIn: int64(spend.amount), 1645 BlockHeight: spend.blockHeight, 1646 BlockIndex: spend.blockIndex, 1647 SignatureScript: opTrueRedeemScript, 1648 }) 1649 spendTx.AddTxOut(wire.NewTxOut(int64(spend.amount-fee), 1650 g.p2shOpTrueScript)) 1651 spendTx.AddTxOut(wire.NewTxOut(0, UniqueOpReturnScript())) 1652 return spendTx 1653 } 1654 1655 // CreateSpendTxForTx creates a transaction that spends from the first output of 1656 // the provided transaction and includes an additional unique OP_RETURN output 1657 // to ensure the transaction ends up with a unique hash. The public key script 1658 // is a simple OP_TRUE p2sh script which avoids the need to track addresses and 1659 // signature scripts in the tests. This signature script the 1660 // opTrueRedeemScript. 1661 func (g *Generator) CreateSpendTxForTx(tx *wire.MsgTx, blockHeight, txIndex uint32, fee dcrutil.Amount) *wire.MsgTx { 1662 spend := MakeSpendableOutForTx(tx, blockHeight, txIndex, 0) 1663 return g.CreateSpendTx(&spend, fee) 1664 } 1665 1666 // removeTicket removes the passed index from the provided slice of tickets and 1667 // returns the resulting slice. This is an in-place modification. 1668 func removeTicket(tickets []*stakeTicket, index int) []*stakeTicket { 1669 copy(tickets[index:], tickets[index+1:]) 1670 tickets[len(tickets)-1] = nil // Prevent memory leak 1671 tickets = tickets[:len(tickets)-1] 1672 return tickets 1673 } 1674 1675 // connectLiveTickets updates the live ticket pool for a new tip block by 1676 // removing tickets that are now expired from it, removing the passed winners 1677 // from it, adding any immature tickets which are now mature to it, and 1678 // resorting it. 1679 func (g *Generator) connectLiveTickets(blockHash *chainhash.Hash, height uint32, winners, purchases []*stakeTicket) { 1680 // Move expired tickets from the live ticket pool to the expired ticket 1681 // pool. 1682 ticketMaturity := uint32(g.params.TicketMaturity) 1683 ticketExpiry := g.params.TicketExpiry 1684 for i := 0; i < len(g.liveTickets); i++ { 1685 ticket := g.liveTickets[i] 1686 liveHeight := ticket.blockHeight + ticketMaturity 1687 expireHeight := liveHeight + ticketExpiry 1688 if height >= expireHeight { 1689 g.liveTickets = removeTicket(g.liveTickets, i) 1690 g.expiredTickets = append(g.expiredTickets, ticket) 1691 1692 // This is required because the ticket at the current 1693 // offset was just removed from the slice that is being 1694 // iterated, so adjust the offset down one accordingly. 1695 i-- 1696 } 1697 } 1698 1699 // Move winning tickets from the live ticket pool to won tickets pool. 1700 for i := 0; i < len(g.liveTickets); i++ { 1701 ticket := g.liveTickets[i] 1702 for _, winner := range winners { 1703 if ticket.tx.CachedTxHash() == winner.tx.CachedTxHash() { 1704 g.liveTickets = removeTicket(g.liveTickets, i) 1705 1706 // This is required because the ticket at the 1707 // current offset was just removed from the 1708 // slice that is being iterated, so adjust the 1709 // offset down one accordingly. 1710 i-- 1711 break 1712 } 1713 } 1714 } 1715 g.wonTickets[*blockHash] = winners 1716 1717 // Move immature tickets which are now mature to the live ticket pool. 1718 for i := 0; i < len(g.immatureTickets); i++ { 1719 ticket := g.immatureTickets[i] 1720 liveHeight := ticket.blockHeight + ticketMaturity 1721 if height >= liveHeight { 1722 g.immatureTickets = removeTicket(g.immatureTickets, i) 1723 g.liveTickets = append(g.liveTickets, ticket) 1724 1725 // This is required because the ticket at the current 1726 // offset was just removed from the slice that is being 1727 // iterated, so adjust the offset down one accordingly. 1728 i-- 1729 } 1730 } 1731 1732 // Resort the ticket pool now that all live ticket pool manipulations 1733 // are done. 1734 sort.Sort(stakeTicketSorter(g.liveTickets)) 1735 1736 // Add new ticket purchases to the immature ticket pool. 1737 g.immatureTickets = append(g.immatureTickets, purchases...) 1738 } 1739 1740 // addMissedVotes adds any of the passed winning tickets as missed votes if the 1741 // passed block does not cast those votes. 1742 func (g *Generator) addMissedVotes(blockHash *chainhash.Hash, stakeTxns []*wire.MsgTx, winners []*stakeTicket) { 1743 // Nothing to do before there are any winning tickets. 1744 if len(winners) == 0 { 1745 return 1746 } 1747 1748 // Assume all of the winning tickets were missed. 1749 missedVotes := make(map[chainhash.Hash]*stakeTicket) 1750 for _, ticket := range winners { 1751 missedVotes[ticket.tx.TxHash()] = ticket 1752 } 1753 1754 // Remove the entries for which the block actually contains votes. 1755 for _, stx := range stakeTxns { 1756 // Ignore all stake transactions that are not votes. 1757 if !isVoteTx(stx) { 1758 continue 1759 } 1760 1761 // Ignore the vote if it is not for one of the winning tickets. 1762 ticketInput := stx.TxIn[1] 1763 ticketHash := ticketInput.PreviousOutPoint.Hash 1764 missedVote, ok := missedVotes[ticketHash] 1765 if !ok || missedVote.blockHeight != ticketInput.BlockHeight || 1766 missedVote.blockIndex != ticketInput.BlockIndex { 1767 1768 continue 1769 } 1770 1771 delete(missedVotes, ticketHash) 1772 } 1773 1774 // Add the missed votes to the generator state so future blocks will 1775 // generate revocations for them. 1776 for ticketHash, missedVote := range missedVotes { 1777 g.missedVotes[ticketHash] = missedVote 1778 } 1779 } 1780 1781 // connectRevocations updates the missed and revoked ticket data structs 1782 // according to the revocations in the passed block. 1783 func (g *Generator) connectRevocations(blockHash *chainhash.Hash, stakeTxns []*wire.MsgTx) { 1784 for _, stx := range stakeTxns { 1785 // Ignore all stake transactions that are not revocations. 1786 if !isRevocationTx(stx) { 1787 continue 1788 } 1789 1790 // Ignore the revocation if it is not for a missed ticket. 1791 ticketInput := stx.TxIn[0] 1792 ticketHash := ticketInput.PreviousOutPoint.Hash 1793 ticket, ok := g.missedVotes[ticketHash] 1794 if !ok || ticket.blockHeight != ticketInput.BlockHeight || 1795 ticket.blockIndex != ticketInput.BlockIndex { 1796 1797 continue 1798 } 1799 1800 // Remove the revoked ticket from the missed votes and add it to the 1801 // list of tickets revoked by the block. 1802 delete(g.missedVotes, ticketHash) 1803 g.revokedTickets[*blockHash] = append(g.revokedTickets[*blockHash], 1804 ticket) 1805 } 1806 } 1807 1808 // connectBlockTickets updates the live ticket pool and associated data structs 1809 // by for the passed block. It will panic if the specified block does not 1810 // connect to the current tip block. 1811 func (g *Generator) connectBlockTickets(b *wire.MsgBlock) { 1812 // Attempt to prevent misuse of this function by ensuring the provided 1813 // block connects to the current tip. 1814 blockHash := b.BlockHash() 1815 if b.Header.PrevBlock != g.tip.BlockHash() { 1816 panic(fmt.Sprintf("attempt to connect block %s with parent %s "+ 1817 "that is not the current tip %s", blockHash, 1818 b.Header.PrevBlock, g.tip.BlockHash())) 1819 } 1820 1821 // Get all of the winning tickets for the block. 1822 numVotes := g.params.TicketsPerBlock 1823 winners, _, err := winningTickets(g.tip, g.liveTickets, numVotes) 1824 if err != nil { 1825 panic(err) 1826 } 1827 1828 // Keep track of any missed votes. 1829 g.addMissedVotes(&blockHash, b.STransactions, winners) 1830 1831 // Keep track of revocations. 1832 g.connectRevocations(&blockHash, b.STransactions) 1833 1834 // Extract the ticket purchases (sstx) from the block. 1835 var purchases []*stakeTicket 1836 blockHeight := g.blockHeight(blockHash) 1837 for txIdx, tx := range b.STransactions { 1838 if isTicketPurchaseTx(tx) { 1839 ticket := &stakeTicket{tx, blockHeight, uint32(txIdx)} 1840 purchases = append(purchases, ticket) 1841 } 1842 } 1843 1844 // Update the live ticket pool and associated data structures. 1845 g.connectLiveTickets(&blockHash, blockHeight, winners, purchases) 1846 } 1847 1848 // disconnectBlockTickets updates the live ticket pool and associated data 1849 // structs by unwinding the passed block, which must be the current tip block. 1850 // It will panic if the specified block is not the current tip block. 1851 func (g *Generator) disconnectBlockTickets(b *wire.MsgBlock) { 1852 // Attempt to prevent misuse of this function by ensuring the provided 1853 // block is the current tip. 1854 blockHash := b.BlockHash() 1855 if b != g.tip { 1856 panic(fmt.Sprintf("attempt to disconnect block %s that is not "+ 1857 "the current tip %s", blockHash, g.tip.BlockHash())) 1858 } 1859 1860 // Move tickets revoked by the block back to the list of missed tickets. 1861 for _, ticket := range g.revokedTickets[blockHash] { 1862 g.missedVotes[ticket.tx.TxHash()] = ticket 1863 } 1864 1865 // Remove any votes missed by the block. 1866 winners := g.wonTickets[blockHash] 1867 for _, ticket := range winners { 1868 delete(g.missedVotes, ticket.tx.TxHash()) 1869 } 1870 1871 // Remove tickets created in the block from the immature ticket pool. 1872 blockHeight := g.blockHeight(blockHash) 1873 for i := 0; i < len(g.immatureTickets); i++ { 1874 ticket := g.immatureTickets[i] 1875 if ticket.blockHeight == blockHeight { 1876 g.immatureTickets = removeTicket(g.immatureTickets, i) 1877 1878 // This is required because the ticket at the current 1879 // offset was just removed from the slice that is being 1880 // iterated, so adjust the offset down one accordingly. 1881 i-- 1882 } 1883 } 1884 1885 // Move tickets that are no longer mature from the live ticket pool to 1886 // the immature ticket pool. 1887 prevBlockHeight := blockHeight - 1 1888 ticketMaturity := uint32(g.params.TicketMaturity) 1889 for i := 0; i < len(g.liveTickets); i++ { 1890 ticket := g.liveTickets[i] 1891 liveHeight := ticket.blockHeight + ticketMaturity 1892 if prevBlockHeight < liveHeight { 1893 g.liveTickets = removeTicket(g.liveTickets, i) 1894 g.immatureTickets = append(g.immatureTickets, ticket) 1895 1896 // This is required because the ticket at the current 1897 // offset was just removed from the slice that is being 1898 // iterated, so adjust the offset down one accordingly. 1899 i-- 1900 } 1901 } 1902 1903 // Move tickets that are no longer expired from the expired ticket pool 1904 // to the live ticket pool. 1905 ticketExpiry := g.params.TicketExpiry 1906 for i := 0; i < len(g.expiredTickets); i++ { 1907 ticket := g.expiredTickets[i] 1908 liveHeight := ticket.blockHeight + ticketMaturity 1909 expireHeight := liveHeight + ticketExpiry 1910 if prevBlockHeight < expireHeight { 1911 g.expiredTickets = removeTicket(g.expiredTickets, i) 1912 g.liveTickets = append(g.liveTickets, ticket) 1913 1914 // This is required because the ticket at the current 1915 // offset was just removed from the slice that is being 1916 // iterated, so adjust the offset down one accordingly. 1917 i-- 1918 } 1919 } 1920 1921 // Add the winning tickets consumed by the block back to the live ticket 1922 // pool. 1923 g.liveTickets = append(g.liveTickets, winners...) 1924 delete(g.wonTickets, blockHash) 1925 1926 // Resort the ticket pool now that all live ticket pool manipulations 1927 // are done. 1928 sort.Sort(stakeTicketSorter(g.liveTickets)) 1929 } 1930 1931 // originalParent returns the original block the passed block was built from. 1932 // This is necessary because callers might change the previous block hash in a 1933 // munger which would cause the like ticket pool to be reconstructed improperly. 1934 func (g *Generator) originalParent(b *wire.MsgBlock) *wire.MsgBlock { 1935 parentHash, ok := g.originalParents[b.BlockHash()] 1936 if !ok { 1937 parentHash = b.Header.PrevBlock 1938 } 1939 return g.BlockByHash(&parentHash) 1940 } 1941 1942 // SetTip changes the tip of the instance to the block with the provided name. 1943 // This is useful since the tip is used for things such as generating subsequent 1944 // blocks. 1945 func (g *Generator) SetTip(blockName string) { 1946 // Nothing to do if already the tip. 1947 if blockName == g.tipName { 1948 return 1949 } 1950 1951 newTip := g.blocksByName[blockName] 1952 if newTip == nil { 1953 panic(fmt.Sprintf("tip block name %s does not exist", blockName)) 1954 } 1955 1956 // Create a list of blocks to disconnect and blocks to connect in order 1957 // to switch to the new tip. 1958 var connect, disconnect []*wire.MsgBlock 1959 oldBranch, newBranch := g.tip, newTip 1960 for oldBranch != newBranch { 1961 oldBranchHeight := g.blockHeight(oldBranch.BlockHash()) 1962 newBranchHeight := g.blockHeight(newBranch.BlockHash()) 1963 if oldBranchHeight > newBranchHeight { 1964 disconnect = append(disconnect, oldBranch) 1965 oldBranch = g.originalParent(oldBranch) 1966 continue 1967 } else if newBranchHeight > oldBranchHeight { 1968 connect = append(connect, newBranch) 1969 newBranch = g.originalParent(newBranch) 1970 continue 1971 } 1972 1973 // At this point the two branches have the same height, so add 1974 // each tip to the appropriate connect or disconnect list and 1975 // the tips to their previous block. 1976 disconnect = append(disconnect, oldBranch) 1977 oldBranch = g.originalParent(oldBranch) 1978 connect = append(connect, newBranch) 1979 newBranch = g.originalParent(newBranch) 1980 } 1981 1982 // Update the live ticket pool and associated data structs by 1983 // disconnecting all blocks back to the fork point. 1984 for _, block := range disconnect { 1985 g.disconnectBlockTickets(block) 1986 g.tip = g.originalParent(block) 1987 } 1988 1989 // Update the live ticket pool and associated data structs by connecting 1990 // all blocks after the fork point up to the new tip. The list of 1991 // blocks to connect is iterated in reverse order, because it was 1992 // constructed in reverse, and the blocks need to be connected in the 1993 // order in which they build the chain. 1994 for i := len(connect) - 1; i >= 0; i-- { 1995 block := connect[i] 1996 g.connectBlockTickets(block) 1997 g.tip = block 1998 } 1999 2000 // Ensure the tip is the expected new tip and set the associated name. 2001 if g.tip != newTip { 2002 panic(fmt.Sprintf("tip %s is not expected new tip %s", 2003 g.tip.BlockHash(), newTip.BlockHash())) 2004 } 2005 g.tipName = blockName 2006 } 2007 2008 // updateVoteCommitments updates all of the votes in the passed block to commit 2009 // to the previous block hash and previous height based on the values specified 2010 // in the header. 2011 func updateVoteCommitments(block *wire.MsgBlock) { 2012 for _, stx := range block.STransactions { 2013 if !isVoteTx(stx) { 2014 continue 2015 } 2016 2017 stx.TxOut[0].PkScript = VoteCommitmentScript(block.Header.PrevBlock, 2018 block.Header.Height-1) 2019 } 2020 } 2021 2022 // NextBlock builds a new block that extends the current tip associated with the 2023 // generator and updates the generator's tip to the newly generated block. 2024 // 2025 // The block will include the following: 2026 // - A coinbase with the following outputs: 2027 // - One that pays the required 10% subsidy to the dev org 2028 // - One that contains a standard coinbase OP_RETURN script 2029 // - Six that pay the required 60% subsidy to an OP_TRUE p2sh script 2030 // - When a spendable output is provided: 2031 // - A transaction that spends from the provided output the following outputs: 2032 // - One that pays the inputs amount minus 1 atom to an OP_TRUE p2sh script 2033 // - Once the coinbase maturity has been reached: 2034 // - A ticket purchase transaction (sstx) for each provided ticket spendable 2035 // output with the following outputs: 2036 // - One OP_SSTX output that grants voting rights to an OP_TRUE p2sh script 2037 // - One OP_RETURN output that contains the required commitment and pays 2038 // the subsidy to an OP_TRUE p2sh script 2039 // - One OP_SSTXCHANGE output that sends change to an OP_TRUE p2sh script 2040 // - Once the stake validation height has been reached: 2041 // - 5 vote transactions (ssgen) as required according to the live ticket 2042 // pool and vote selection rules with the following outputs: 2043 // - One OP_RETURN followed by the block hash and height being voted on 2044 // - One OP_RETURN followed by the vote bits 2045 // - One or more OP_SSGEN outputs with the payouts according to the original 2046 // ticket commitments 2047 // - Revocation transactions (ssrtx) as required according to any missed votes 2048 // with the following outputs: 2049 // - One or more OP_SSRTX outputs with the payouts according to the original 2050 // ticket commitments 2051 // 2052 // Additionally, if one or more munge functions are specified, they will be 2053 // invoked with the block prior to solving it. This provides callers with the 2054 // opportunity to modify the block which is especially useful for testing. 2055 // 2056 // In order to simply the logic in the munge functions, the following rules are 2057 // applied after all munge functions have been invoked: 2058 // - All votes will have their commitments updated if the previous hash or 2059 // height was manually changed after stake validation height has been reached 2060 // - The merkle root will be recalculated unless it was manually changed 2061 // - The stake root will be recalculated unless it was manually changed 2062 // - The size of the block will be recalculated unless it was manually changed 2063 // - The block will be solved unless the nonce was changed 2064 func (g *Generator) NextBlock(blockName string, spend *SpendableOut, ticketSpends []SpendableOut, mungers ...func(*wire.MsgBlock)) *wire.MsgBlock { 2065 // Prevent block name collisions. 2066 if g.blocksByName[blockName] != nil { 2067 panic(fmt.Sprintf("block name %s already exists", blockName)) 2068 } 2069 2070 // Calculate the next required stake difficulty (aka ticket price). 2071 ticketPrice := dcrutil.Amount(g.CalcNextRequiredStakeDifficulty()) 2072 2073 // Generate the appropriate votes and ticket purchases based on the 2074 // current tip block and provided ticket spendable outputs. 2075 var ticketWinners []*stakeTicket 2076 var stakeTxns []*wire.MsgTx 2077 var finalState [6]byte 2078 nextHeight := g.tip.Header.Height + 1 2079 if nextHeight > uint32(g.params.CoinbaseMaturity) { 2080 // Generate votes once the stake validation height has been 2081 // reached. 2082 if int64(nextHeight) >= g.params.StakeValidationHeight { 2083 // Generate and add the vote transactions for the 2084 // winning tickets to the stake tree. 2085 numVotes := g.params.TicketsPerBlock 2086 winners, stateHash, err := winningTickets(g.tip, 2087 g.liveTickets, numVotes) 2088 if err != nil { 2089 panic(err) 2090 } 2091 ticketWinners = winners 2092 for _, ticket := range winners { 2093 voteTx := g.createVoteTxFromTicket(g.tip, ticket) 2094 stakeTxns = append(stakeTxns, voteTx) 2095 } 2096 2097 // Calculate the final lottery state hash for use in the 2098 // block header. 2099 finalState = calcFinalLotteryState(winners, stateHash) 2100 } 2101 2102 // Generate ticket purchases (sstx) using the provided spendable 2103 // outputs. 2104 if ticketSpends != nil { 2105 const ticketFee = dcrutil.Amount(2) 2106 for i := 0; i < len(ticketSpends); i++ { 2107 out := &ticketSpends[i] 2108 purchaseTx := g.CreateTicketPurchaseTx(out, 2109 ticketPrice, ticketFee) 2110 stakeTxns = append(stakeTxns, purchaseTx) 2111 } 2112 } 2113 2114 // Generate and add revocations for any missed tickets. 2115 for _, missedVote := range g.missedVotes { 2116 revocationTx := g.createRevocationTxFromTicket(missedVote) 2117 stakeTxns = append(stakeTxns, revocationTx) 2118 } 2119 } 2120 2121 // Count the ticket purchases (sstx), votes (ssgen, and ticket revocations 2122 // (ssrtx), and calculate the total PoW fees generated by the stake 2123 // transactions. 2124 var numVotes uint16 2125 var numTicketRevocations uint8 2126 var numTicketPurchases uint8 2127 var stakeTreeFees dcrutil.Amount 2128 for _, tx := range stakeTxns { 2129 switch { 2130 case isVoteTx(tx): 2131 numVotes++ 2132 case isTicketPurchaseTx(tx): 2133 numTicketPurchases++ 2134 case isRevocationTx(tx): 2135 numTicketRevocations++ 2136 } 2137 2138 // Calculate any fees for the transaction. 2139 var inputSum, outputSum dcrutil.Amount 2140 for _, txIn := range tx.TxIn { 2141 inputSum += dcrutil.Amount(txIn.ValueIn) 2142 } 2143 for _, txOut := range tx.TxOut { 2144 outputSum += dcrutil.Amount(txOut.Value) 2145 } 2146 stakeTreeFees += (inputSum - outputSum) 2147 } 2148 2149 // Create a standard coinbase and spending transaction. 2150 var regularTxns []*wire.MsgTx 2151 { 2152 // Create coinbase transaction for the block with no additional 2153 // dev or pow subsidy. 2154 coinbaseTx := g.CreateCoinbaseTx(nextHeight, numVotes) 2155 regularTxns = []*wire.MsgTx{coinbaseTx} 2156 2157 // Increase the PoW subsidy to account for any fees in the stake 2158 // tree. 2159 coinbaseTx.TxOut[2].Value += int64(stakeTreeFees) 2160 2161 // Create a transaction to spend the provided utxo if needed. 2162 if spend != nil { 2163 // Create the transaction with a fee of 1 atom for the 2164 // miner and increase the PoW subsidy accordingly. 2165 fee := dcrutil.Amount(1) 2166 coinbaseTx.TxOut[2].Value += int64(fee) 2167 2168 // Create a transaction that spends from the provided 2169 // spendable output and includes an additional unique 2170 // OP_RETURN output to ensure the transaction ends up 2171 // with a unique hash, then add it to the list of 2172 // transactions to include in the block. The script is 2173 // a simple OP_TRUE p2sh script in order to avoid the 2174 // need to track addresses and signature scripts in the 2175 // tests. 2176 spendTx := g.CreateSpendTx(spend, fee) 2177 regularTxns = append(regularTxns, spendTx) 2178 } 2179 } 2180 2181 // Use a timestamp that is 7/8 of target timespan after the previous 2182 // block unless this is the first block in which case the current time 2183 // is used or the proof-of-work difficulty parameters have been adjusted 2184 // such that it's greater than the max 2 hours worth of blocks that can 2185 // be tested in which case one second is used. This helps maintain the 2186 // retarget difficulty low as needed. Also, ensure the timestamp is 2187 // limited to one second precision. 2188 var ts time.Time 2189 if nextHeight == 1 { 2190 ts = time.Now() 2191 } else { 2192 if g.params.WorkDiffWindowSize > 7200 { 2193 ts = g.tip.Header.Timestamp.Add(time.Second) 2194 } else { 2195 addDuration := g.params.TargetTimespan * 7 / 8 2196 ts = g.tip.Header.Timestamp.Add(addDuration) 2197 } 2198 } 2199 ts = time.Unix(ts.Unix(), 0) 2200 2201 // Create the unsolved block. 2202 prevHash := g.tip.BlockHash() 2203 block := wire.MsgBlock{ 2204 Header: wire.BlockHeader{ 2205 Version: 1, 2206 PrevBlock: prevHash, 2207 MerkleRoot: calcMerkleRoot(regularTxns), 2208 StakeRoot: calcMerkleRoot(stakeTxns), 2209 VoteBits: 1, 2210 FinalState: finalState, 2211 Voters: numVotes, 2212 FreshStake: numTicketPurchases, 2213 Revocations: numTicketRevocations, 2214 PoolSize: uint32(len(g.liveTickets)), 2215 Bits: g.CalcNextRequiredDifficulty(), 2216 SBits: int64(ticketPrice), 2217 Height: nextHeight, 2218 Size: 0, // Filled in below. 2219 Timestamp: ts, 2220 Nonce: 0, // To be solved. 2221 ExtraData: [32]byte{}, 2222 StakeVersion: 0, 2223 }, 2224 Transactions: regularTxns, 2225 STransactions: stakeTxns, 2226 } 2227 block.Header.Size = uint32(block.SerializeSize()) 2228 2229 // Perform any block munging just before solving. Once stake validation 2230 // height has been reached, update the vote commitments accordingly if the 2231 // header height or previous hash was manually changed by a munge function. 2232 // Also, only recalculate the merkle roots and block size if they weren't 2233 // manually changed by a munge function. 2234 curMerkleRoot := block.Header.MerkleRoot 2235 curStakeRoot := block.Header.StakeRoot 2236 curSize := block.Header.Size 2237 curNonce := block.Header.Nonce 2238 for _, f := range mungers { 2239 f(&block) 2240 } 2241 if block.Header.Height != nextHeight || block.Header.PrevBlock != prevHash { 2242 if int64(nextHeight) >= g.params.StakeValidationHeight { 2243 updateVoteCommitments(&block) 2244 } 2245 } 2246 if block.Header.MerkleRoot == curMerkleRoot { 2247 block.Header.MerkleRoot = calcMerkleRoot(block.Transactions) 2248 } 2249 if block.Header.StakeRoot == curStakeRoot { 2250 block.Header.StakeRoot = calcMerkleRoot(block.STransactions) 2251 } 2252 if block.Header.Size == curSize { 2253 block.Header.Size = uint32(block.SerializeSize()) 2254 } 2255 2256 // Only solve the block if the nonce wasn't manually changed by a munge 2257 // function. 2258 if block.Header.Nonce == curNonce && !solveBlock(&block.Header) { 2259 panic(fmt.Sprintf("unable to solve block at height %d", 2260 block.Header.Height)) 2261 } 2262 2263 // Create stake tickets for the ticket purchases (sstx) in the block. This 2264 // is done after the mungers to ensure all changes are accurately accounted 2265 // for. 2266 var ticketPurchases []*stakeTicket 2267 for txIdx, tx := range block.STransactions { 2268 if isTicketPurchaseTx(tx) { 2269 ticket := &stakeTicket{tx, nextHeight, uint32(txIdx)} 2270 ticketPurchases = append(ticketPurchases, ticket) 2271 } 2272 } 2273 2274 // Update generator state and return the block. 2275 blockHash := block.BlockHash() 2276 if block.Header.PrevBlock != prevHash { 2277 // Save the orignal block this one was built from if it was 2278 // manually changed in a munger so the code which deals with 2279 // updating the live tickets when changing the tip has access to 2280 // it. 2281 g.originalParents[blockHash] = prevHash 2282 } 2283 g.addMissedVotes(&blockHash, block.STransactions, ticketWinners) 2284 g.connectRevocations(&blockHash, block.STransactions) 2285 g.connectLiveTickets(&blockHash, nextHeight, ticketWinners, 2286 ticketPurchases) 2287 g.blocks[blockHash] = &block 2288 g.blockHeights[blockHash] = nextHeight 2289 g.blocksByName[blockName] = &block 2290 g.tip = &block 2291 g.tipName = blockName 2292 return &block 2293 } 2294 2295 // CreatePremineBlock generates the first block of the chain with the required 2296 // premine payouts. The additional amount parameter can be used to create a 2297 // block that is otherwise a completely valid premine block except it adds the 2298 // extra amount to each payout and thus create a block that violates consensus. 2299 func (g *Generator) CreatePremineBlock(blockName string, additionalAmount dcrutil.Amount, mungers ...func(*wire.MsgBlock)) *wire.MsgBlock { 2300 coinbaseTx := wire.NewMsgTx() 2301 coinbaseTx.AddTxIn(&wire.TxIn{ 2302 PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, 2303 wire.MaxPrevOutIndex, wire.TxTreeRegular), 2304 Sequence: wire.MaxTxInSequenceNum, 2305 ValueIn: 0, // Updated below. 2306 BlockHeight: wire.NullBlockHeight, 2307 BlockIndex: wire.NullBlockIndex, 2308 SignatureScript: coinbaseSigScript, 2309 }) 2310 2311 // Add each required output and tally the total payouts for the coinbase 2312 // in order to set the input value appropriately. 2313 var totalSubsidy dcrutil.Amount 2314 for _, payout := range g.params.BlockOneLedger { 2315 payoutAddr, err := dcrutil.DecodeAddress(payout.Address) 2316 if err != nil { 2317 panic(err) 2318 } 2319 pkScript, err := txscript.PayToAddrScript(payoutAddr) 2320 if err != nil { 2321 panic(err) 2322 } 2323 coinbaseTx.AddTxOut(&wire.TxOut{ 2324 Value: payout.Amount + int64(additionalAmount), 2325 Version: 0, 2326 PkScript: pkScript, 2327 }) 2328 2329 totalSubsidy += dcrutil.Amount(payout.Amount) 2330 } 2331 coinbaseTx.TxIn[0].ValueIn = int64(totalSubsidy) 2332 2333 // Generate the block with the specially created regular transactions. 2334 munger := func(b *wire.MsgBlock) { 2335 b.Transactions = []*wire.MsgTx{coinbaseTx} 2336 } 2337 mungers = append([]func(*wire.MsgBlock){munger}, mungers...) 2338 return g.NextBlock(blockName, nil, nil, mungers...) 2339 } 2340 2341 // UpdateBlockState manually updates the generator state to remove all internal 2342 // map references to a block via its old hash and insert new ones for the new 2343 // block hash. This is useful if the test code has to manually change a block 2344 // after 'NextBlock' has returned. 2345 func (g *Generator) UpdateBlockState(oldBlockName string, oldBlockHash chainhash.Hash, newBlockName string, newBlock *wire.MsgBlock) { 2346 // Remove existing entries. 2347 wonTickets := g.wonTickets[oldBlockHash] 2348 existingHeight := g.blockHeights[oldBlockHash] 2349 delete(g.blocks, oldBlockHash) 2350 delete(g.blockHeights, oldBlockHash) 2351 delete(g.blocksByName, oldBlockName) 2352 delete(g.wonTickets, oldBlockHash) 2353 2354 // Add new entries. 2355 newBlockHash := newBlock.BlockHash() 2356 g.blocks[newBlockHash] = newBlock 2357 g.blockHeights[newBlockHash] = existingHeight 2358 g.blocksByName[newBlockName] = newBlock 2359 g.wonTickets[newBlockHash] = wonTickets 2360 } 2361 2362 // OldestCoinbaseOuts removes the oldest set of coinbase proof-of-work outputs 2363 // that was previously saved to the generator and returns the set as a slice. 2364 func (g *Generator) OldestCoinbaseOuts() []SpendableOut { 2365 outs := g.spendableOuts[0] 2366 g.spendableOuts = g.spendableOuts[1:] 2367 return outs 2368 } 2369 2370 // NumSpendableCoinbaseOuts returns the number of proof-of-work outputs that 2371 // were previously saved to the generated but have not yet been collected. 2372 func (g *Generator) NumSpendableCoinbaseOuts() int { 2373 return len(g.spendableOuts) 2374 } 2375 2376 // saveCoinbaseOuts adds the proof-of-work outputs of the coinbase tx in the 2377 // passed block to the list of spendable outputs. 2378 func (g *Generator) saveCoinbaseOuts(b *wire.MsgBlock) { 2379 g.spendableOuts = append(g.spendableOuts, []SpendableOut{ 2380 MakeSpendableOut(b, 0, 2), 2381 MakeSpendableOut(b, 0, 3), 2382 MakeSpendableOut(b, 0, 4), 2383 MakeSpendableOut(b, 0, 5), 2384 MakeSpendableOut(b, 0, 6), 2385 MakeSpendableOut(b, 0, 7), 2386 }) 2387 g.prevCollectedHash = b.BlockHash() 2388 } 2389 2390 // SaveTipCoinbaseOuts adds the proof-of-work outputs of the coinbase tx in the 2391 // current tip block to the list of spendable outputs. 2392 func (g *Generator) SaveTipCoinbaseOuts() { 2393 g.saveCoinbaseOuts(g.tip) 2394 } 2395 2396 // SaveSpendableCoinbaseOuts adds all proof-of-work coinbase outputs starting 2397 // from the block after the last block that had its coinbase outputs collected 2398 // and ending at the current tip. This is useful to batch the collection of the 2399 // outputs once the tests reach a stable point so they don't have to manually 2400 // add them for the right tests which will ultimately end up being the best 2401 // chain. 2402 func (g *Generator) SaveSpendableCoinbaseOuts() { 2403 // Loop through the ancestors of the current tip until the 2404 // reaching the block that has already had the coinbase outputs 2405 // collected. 2406 var collectBlocks []*wire.MsgBlock 2407 for b := g.tip; b != nil; b = g.blocks[b.Header.PrevBlock] { 2408 if b.BlockHash() == g.prevCollectedHash { 2409 break 2410 } 2411 collectBlocks = append(collectBlocks, b) 2412 } 2413 for i := range collectBlocks { 2414 g.saveCoinbaseOuts(collectBlocks[len(collectBlocks)-1-i]) 2415 } 2416 } 2417 2418 // AssertTipHeight panics if the current tip block associated with the generator 2419 // does not have the specified height. 2420 func (g *Generator) AssertTipHeight(expected uint32) { 2421 height := g.tip.Header.Height 2422 if height != expected { 2423 panic(fmt.Sprintf("height for block %q is %d instead of "+ 2424 "expected %d", g.tipName, height, expected)) 2425 } 2426 } 2427 2428 // AssertScriptSigOpsCount panics if the provided script does not have the 2429 // specified number of signature operations. 2430 func (g *Generator) AssertScriptSigOpsCount(script []byte, expected int) { 2431 numSigOps := txscript.GetSigOpCount(script) 2432 if numSigOps != expected { 2433 _, file, line, _ := runtime.Caller(1) 2434 panic(fmt.Sprintf("assertion failed at %s:%d: generated number "+ 2435 "of sigops for script is %d instead of expected %d", 2436 file, line, numSigOps, expected)) 2437 } 2438 } 2439 2440 // countBlockSigOps returns the number of legacy signature operations in the 2441 // scripts in the passed block. 2442 func countBlockSigOps(block *wire.MsgBlock) int { 2443 totalSigOps := 0 2444 for _, tx := range block.Transactions { 2445 for _, txIn := range tx.TxIn { 2446 numSigOps := txscript.GetSigOpCount(txIn.SignatureScript) 2447 totalSigOps += numSigOps 2448 } 2449 for _, txOut := range tx.TxOut { 2450 numSigOps := txscript.GetSigOpCount(txOut.PkScript) 2451 totalSigOps += numSigOps 2452 } 2453 } 2454 2455 return totalSigOps 2456 } 2457 2458 // AssertTipBlockSigOpsCount panics if the current tip block associated with the 2459 // generator does not have the specified number of signature operations. 2460 func (g *Generator) AssertTipBlockSigOpsCount(expected int) { 2461 numSigOps := countBlockSigOps(g.tip) 2462 if numSigOps != expected { 2463 panic(fmt.Sprintf("generated number of sigops for block %q "+ 2464 "(height %d) is %d instead of expected %d", g.tipName, 2465 g.tip.Header.Height, numSigOps, expected)) 2466 } 2467 } 2468 2469 // AssertTipBlockSize panics if the if the current tip block associated with the 2470 // generator does not have the specified size when serialized. 2471 func (g *Generator) AssertTipBlockSize(expected int) { 2472 serializeSize := g.tip.SerializeSize() 2473 if serializeSize != expected { 2474 panic(fmt.Sprintf("block size of block %q (height %d) is %d "+ 2475 "instead of expected %d", g.tipName, 2476 g.tip.Header.Height, serializeSize, expected)) 2477 } 2478 } 2479 2480 // AssertTipBlockNumTxns panics if the number of transactions in the current tip 2481 // block associated with the generator does not match the specified value. 2482 func (g *Generator) AssertTipBlockNumTxns(expected int) { 2483 numTxns := len(g.tip.Transactions) 2484 if numTxns != expected { 2485 panic(fmt.Sprintf("number of txns in block %q (height %d) is "+ 2486 "%d instead of expected %d", g.tipName, 2487 g.tip.Header.Height, numTxns, expected)) 2488 } 2489 } 2490 2491 // AssertTipBlockHash panics if the current tip block associated with the 2492 // generator does not match the specified hash. 2493 func (g *Generator) AssertTipBlockHash(expected chainhash.Hash) { 2494 hash := g.tip.BlockHash() 2495 if hash != expected { 2496 panic(fmt.Sprintf("block hash of block %q (height %d) is %v "+ 2497 "instead of expected %v", g.tipName, 2498 g.tip.Header.Height, hash, expected)) 2499 } 2500 } 2501 2502 // AssertTipBlockMerkleRoot panics if the merkle root in header of the current 2503 // tip block associated with the generator does not match the specified hash. 2504 func (g *Generator) AssertTipBlockMerkleRoot(expected chainhash.Hash) { 2505 hash := g.tip.Header.MerkleRoot 2506 if hash != expected { 2507 panic(fmt.Sprintf("merkle root of block %q (height %d) is %v "+ 2508 "instead of expected %v", g.tipName, 2509 g.tip.Header.Height, hash, expected)) 2510 } 2511 } 2512 2513 // AssertTipBlockStakeRoot panics if the stake root in header of the current 2514 // tip block associated with the generator does not match the specified hash. 2515 func (g *Generator) AssertTipBlockStakeRoot(expected chainhash.Hash) { 2516 hash := g.tip.Header.StakeRoot 2517 if hash != expected { 2518 panic(fmt.Sprintf("stake root of block %q (height %d) is %v "+ 2519 "instead of expected %v", g.tipName, 2520 g.tip.Header.Height, hash, expected)) 2521 } 2522 } 2523 2524 // AssertTipBlockTxOutOpReturn panics if the current tip block associated with 2525 // the generator does not have an OP_RETURN script for the transaction output at 2526 // the provided tx index and output index. 2527 func (g *Generator) AssertTipBlockTxOutOpReturn(txIndex, txOutIndex uint32) { 2528 if txIndex >= uint32(len(g.tip.Transactions)) { 2529 panic(fmt.Sprintf("transaction index %d in block %q "+ 2530 "(height %d) does not exist", txIndex, g.tipName, 2531 g.tip.Header.Height)) 2532 } 2533 2534 tx := g.tip.Transactions[txIndex] 2535 if txOutIndex >= uint32(len(tx.TxOut)) { 2536 panic(fmt.Sprintf("transaction index %d output %d in block %q "+ 2537 "(height %d) does not exist", txIndex, txOutIndex, 2538 g.tipName, g.tip.Header.Height)) 2539 } 2540 2541 txOut := tx.TxOut[txOutIndex] 2542 if txOut.PkScript[0] != txscript.OP_RETURN { 2543 panic(fmt.Sprintf("transaction index %d output %d in block %q "+ 2544 "(height %d) is not an OP_RETURN", txIndex, txOutIndex, 2545 g.tipName, g.tip.Header.Height)) 2546 } 2547 } 2548 2549 // AssertStakeVersion panics if the current tip block associated with the 2550 // generator does not have the specified stake version in the header. 2551 func (g *Generator) AssertStakeVersion(expected uint32) { 2552 stakeVersion := g.tip.Header.StakeVersion 2553 if stakeVersion != expected { 2554 panic(fmt.Sprintf("stake version for block %q is %d instead of "+ 2555 "expected %d", g.tipName, stakeVersion, expected)) 2556 } 2557 } 2558 2559 // AssertBlockVersion panics if the current tip block associated with the 2560 // generator does not have the specified block version in the header. 2561 func (g *Generator) AssertBlockVersion(expected int32) { 2562 blockVersion := g.tip.Header.Version 2563 if blockVersion != expected { 2564 panic(fmt.Sprintf("block version for block %q is %d instead of "+ 2565 "expected %d", g.tipName, blockVersion, expected)) 2566 } 2567 } 2568 2569 // AssertPoolSize panics if the current tip block associated with the generator 2570 // does not indicate the specified pool size. 2571 func (g *Generator) AssertPoolSize(expected uint32) { 2572 poolSize := g.tip.Header.PoolSize 2573 if poolSize != expected { 2574 panic(fmt.Sprintf("pool size for block %q is %d instead of expected "+ 2575 "%d", g.tipName, poolSize, expected)) 2576 } 2577 } 2578 2579 // AssertBlockRevocationTx panics if the current tip block associated with the 2580 // generator does not have a revocation at the specified transaction index 2581 // provided. 2582 func (g *Generator) AssertBlockRevocationTx(b *wire.MsgBlock, txIndex uint32) { 2583 if !isRevocationTx(b.STransactions[txIndex]) { 2584 panic(fmt.Sprintf("stake transaction at index %d in block %q is "+ 2585 " not a revocation", txIndex, g.tipName)) 2586 } 2587 } 2588 2589 // AssertTipNumRevocations panics if the number of revocations in header of the 2590 // current tip block associated with the generator does not match the specified 2591 // value. 2592 func (g *Generator) AssertTipNumRevocations(expected uint8) { 2593 numRevocations := g.tip.Header.Revocations 2594 if numRevocations != expected { 2595 panic(fmt.Sprintf("number of revocations in block %q (height "+ 2596 "%d) is %d instead of expected %d", g.tipName, 2597 g.tip.Header.Height, numRevocations, expected)) 2598 } 2599 } 2600 2601 // AssertTipDisapprovesPrevious panics if the current tip block associated with 2602 // the generator does not disapprove the previous block. 2603 func (g *Generator) AssertTipDisapprovesPrevious() { 2604 if g.tip.Header.VoteBits&voteBitYes == 1 { 2605 panic(fmt.Sprintf("block %q (height %d) does not disapprove prev block", 2606 g.tipName, g.tip.Header.Height)) 2607 } 2608 }