github.com/decred/dcrd/blockchain@v1.2.1/validate.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Copyright (c) 2015-2019 The Decred developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain 7 8 import ( 9 "bytes" 10 "encoding/binary" 11 "fmt" 12 "math" 13 "math/big" 14 "time" 15 16 "github.com/decred/dcrd/blockchain/stake" 17 "github.com/decred/dcrd/blockchain/standalone" 18 "github.com/decred/dcrd/chaincfg" 19 "github.com/decred/dcrd/chaincfg/chainhash" 20 "github.com/decred/dcrd/database" 21 "github.com/decred/dcrd/dcrutil" 22 "github.com/decred/dcrd/txscript" 23 "github.com/decred/dcrd/wire" 24 ) 25 26 const ( 27 // MaxSigOpsPerBlock is the maximum number of signature operations 28 // allowed for a block. This really should be based upon the max 29 // allowed block size for a network and any votes that might change it, 30 // however, since it was not updated to be based upon it before 31 // release, it will require a hard fork and associated vote agenda to 32 // change it. The original max block size for the protocol was 1MiB, 33 // so that is what this is based on. 34 MaxSigOpsPerBlock = 1000000 / 200 35 36 // MaxTimeOffsetSeconds is the maximum number of seconds a block time 37 // is allowed to be ahead of the current time. This is currently 2 38 // hours. 39 MaxTimeOffsetSeconds = 2 * 60 * 60 40 41 // MinCoinbaseScriptLen is the minimum length a coinbase script can be. 42 MinCoinbaseScriptLen = 2 43 44 // MaxCoinbaseScriptLen is the maximum length a coinbase script can be. 45 MaxCoinbaseScriptLen = 100 46 47 // maxUniqueCoinbaseNullDataSize is the maximum number of bytes allowed 48 // in the pushed data output of the coinbase output that is used to 49 // ensure the coinbase has a unique hash. 50 maxUniqueCoinbaseNullDataSize = 256 51 52 // medianTimeBlocks is the number of previous blocks which should be 53 // used to calculate the median time used to validate block timestamps. 54 medianTimeBlocks = 11 55 56 // earlyVoteBitsValue is the only value of VoteBits allowed in a block 57 // header before stake validation height. 58 earlyVoteBitsValue = 0x0001 59 60 // maxRevocationsPerBlock is the maximum number of revocations that are 61 // allowed per block. 62 maxRevocationsPerBlock = 255 63 64 // A ticket commitment output is an OP_RETURN script with a 30-byte data 65 // push that consists of a 20-byte hash for the payment hash, 8 bytes 66 // for the amount to commit to (with the upper bit flag set to indicate 67 // the hash is for a pay-to-script-hash address, otherwise the hash is a 68 // pay-to-pubkey-hash), and 2 bytes for the fee limits. Thus, 1 byte 69 // for the OP_RETURN + 1 byte for the data push + 20 bytes for the 70 // payment hash means the encoded amount is at offset 22. Then, 8 bytes 71 // for the amount means the encoded fee limits are at offset 30. 72 commitHashStartIdx = 2 73 commitHashEndIdx = commitHashStartIdx + 20 74 commitAmountStartIdx = commitHashEndIdx 75 commitAmountEndIdx = commitAmountStartIdx + 8 76 commitFeeLimitStartIdx = commitAmountEndIdx 77 commitFeeLimitEndIdx = commitFeeLimitStartIdx + 2 78 79 // commitP2SHFlag specifies the bitmask to apply to an amount decoded from 80 // a ticket commitment in order to determine if it is a pay-to-script-hash 81 // commitment. The value is derived from the fact it is encoded as the most 82 // significant bit in the amount. 83 commitP2SHFlag = uint64(1 << 63) 84 85 // submissionOutputIdx is the index of the stake submission output of a 86 // ticket transaction. 87 submissionOutputIdx = 0 88 ) 89 90 var ( 91 // zeroHash is the zero value for a chainhash.Hash and is defined as a 92 // package level variable to avoid the need to create a new instance 93 // every time a check is needed. 94 zeroHash = &chainhash.Hash{} 95 96 // earlyFinalState is the only value of the final state allowed in a 97 // block header before stake validation height. 98 earlyFinalState = [6]byte{0x00} 99 ) 100 101 // voteBitsApproveParent returns whether or not the passed vote bits indicate 102 // the regular transaction tree of the parent block should be considered valid. 103 func voteBitsApproveParent(voteBits uint16) bool { 104 return dcrutil.IsFlagSet16(voteBits, dcrutil.BlockValid) 105 } 106 107 // headerApprovesParent returns whether or not the vote bits in the passed 108 // header indicate the regular transaction tree of the parent block should be 109 // considered valid. 110 func headerApprovesParent(header *wire.BlockHeader) bool { 111 return voteBitsApproveParent(header.VoteBits) 112 } 113 114 // isNullOutpoint determines whether or not a previous transaction output point 115 // is set. 116 func isNullOutpoint(outpoint *wire.OutPoint) bool { 117 if outpoint.Index == math.MaxUint32 && 118 outpoint.Hash.IsEqual(zeroHash) && 119 outpoint.Tree == wire.TxTreeRegular { 120 return true 121 } 122 return false 123 } 124 125 // isNullFraudProof determines whether or not a previous transaction fraud 126 // proof is set. 127 func isNullFraudProof(txIn *wire.TxIn) bool { 128 switch { 129 case txIn.BlockHeight != wire.NullBlockHeight: 130 return false 131 case txIn.BlockIndex != wire.NullBlockIndex: 132 return false 133 } 134 135 return true 136 } 137 138 // IsCoinBaseTx determines whether or not a transaction is a coinbase. A 139 // coinbase is a special transaction created by miners that has no inputs. 140 // This is represented in the block chain by a transaction with a single input 141 // that has a previous output transaction index set to the maximum value along 142 // with a zero hash. 143 // 144 // This function only differs from IsCoinBase in that it works with a raw wire 145 // transaction as opposed to a higher level util transaction. 146 // 147 // Deprecated: Use standalone.IsCoinBaseTx instead. 148 func IsCoinBaseTx(msgTx *wire.MsgTx) bool { 149 return standalone.IsCoinBaseTx(msgTx) 150 } 151 152 // IsCoinBase determines whether or not a transaction is a coinbase. A 153 // coinbase is a special transaction created by miners that has no inputs. 154 // This is represented in the block chain by a transaction with a single input 155 // that has a previous output transaction index set to the maximum value along 156 // with a zero hash. 157 // 158 // This function only differs from IsCoinBaseTx in that it works with a higher 159 // level util transaction as opposed to a raw wire transaction. 160 // 161 // Deprecated: Use standalone.IsCoinBaseTx instead. 162 func IsCoinBase(tx *dcrutil.Tx) bool { 163 return standalone.IsCoinBaseTx(tx.MsgTx()) 164 } 165 166 // IsExpiredTx returns where or not the passed transaction is expired according 167 // to the given block height. 168 // 169 // This function only differs from IsExpired in that it works with a raw wire 170 // transaction as opposed to a higher level util transaction. 171 func IsExpiredTx(tx *wire.MsgTx, blockHeight int64) bool { 172 expiry := tx.Expiry 173 return expiry != wire.NoExpiryValue && blockHeight >= int64(expiry) 174 } 175 176 // IsExpired returns where or not the passed transaction is expired according to 177 // the given block height. 178 // 179 // This function only differs from IsExpiredTx in that it works with a higher 180 // level util transaction as opposed to a raw wire transaction. 181 func IsExpired(tx *dcrutil.Tx, blockHeight int64) bool { 182 return IsExpiredTx(tx.MsgTx(), blockHeight) 183 } 184 185 // SequenceLockActive determines if all of the inputs to a given transaction 186 // have achieved a relative age that surpasses the requirements specified by 187 // their respective sequence locks as calculated by CalcSequenceLock. A single 188 // sequence lock is sufficient because the calculated lock selects the minimum 189 // required time and block height from all of the non-disabled inputs after 190 // which the transaction can be included. 191 func SequenceLockActive(lock *SequenceLock, blockHeight int64, medianTime time.Time) bool { 192 // The transaction is not yet mature if it has not yet reached the 193 // required minimum time and block height according to its sequence 194 // locks. 195 if blockHeight <= lock.MinHeight || medianTime.Unix() <= lock.MinTime { 196 return false 197 } 198 199 return true 200 } 201 202 // IsFinalizedTransaction determines whether or not a transaction is finalized. 203 func IsFinalizedTransaction(tx *dcrutil.Tx, blockHeight int64, blockTime time.Time) bool { 204 // Lock time of zero means the transaction is finalized. 205 msgTx := tx.MsgTx() 206 lockTime := msgTx.LockTime 207 if lockTime == 0 { 208 return true 209 } 210 211 // The lock time field of a transaction is either a block height at 212 // which the transaction is finalized or a timestamp depending on if the 213 // value is before the txscript.LockTimeThreshold. When it is under the 214 // threshold it is a block height. 215 var blockTimeOrHeight int64 216 if lockTime < txscript.LockTimeThreshold { 217 blockTimeOrHeight = blockHeight 218 } else { 219 blockTimeOrHeight = blockTime.Unix() 220 } 221 if int64(lockTime) < blockTimeOrHeight { 222 return true 223 } 224 225 // At this point, the transaction's lock time hasn't occurred yet, but 226 // the transaction might still be finalized if the sequence number 227 // for all transaction inputs is maxed out. 228 for _, txIn := range msgTx.TxIn { 229 if txIn.Sequence != math.MaxUint32 { 230 return false 231 } 232 } 233 return true 234 } 235 236 // CheckTransactionSanity performs some preliminary checks on a transaction to 237 // ensure it is sane. These checks are context free. 238 func CheckTransactionSanity(tx *wire.MsgTx, params *chaincfg.Params) error { 239 // A transaction must have at least one input. 240 if len(tx.TxIn) == 0 { 241 return ruleError(ErrNoTxInputs, "transaction has no inputs") 242 } 243 244 // A transaction must have at least one output. 245 if len(tx.TxOut) == 0 { 246 return ruleError(ErrNoTxOutputs, "transaction has no outputs") 247 } 248 249 // A transaction must not exceed the maximum allowed size when 250 // serialized. 251 serializedTxSize := tx.SerializeSize() 252 if serializedTxSize > params.MaxTxSize { 253 str := fmt.Sprintf("serialized transaction is too big - got "+ 254 "%d, max %d", serializedTxSize, params.MaxTxSize) 255 return ruleError(ErrTxTooBig, str) 256 } 257 258 // Coinbase script length must be between min and max length. 259 isVote := stake.IsSSGen(tx) 260 if standalone.IsCoinBaseTx(tx) { 261 // The referenced outpoint must be null. 262 if !isNullOutpoint(&tx.TxIn[0].PreviousOutPoint) { 263 str := fmt.Sprintf("coinbase transaction did not use " + 264 "a null outpoint") 265 return ruleError(ErrBadCoinbaseOutpoint, str) 266 } 267 268 // The fraud proof must also be null. 269 if !isNullFraudProof(tx.TxIn[0]) { 270 str := fmt.Sprintf("coinbase transaction fraud proof " + 271 "was non-null") 272 return ruleError(ErrBadCoinbaseFraudProof, str) 273 } 274 275 slen := len(tx.TxIn[0].SignatureScript) 276 if slen < MinCoinbaseScriptLen || slen > MaxCoinbaseScriptLen { 277 str := fmt.Sprintf("coinbase transaction script "+ 278 "length of %d is out of range (min: %d, max: "+ 279 "%d)", slen, MinCoinbaseScriptLen, 280 MaxCoinbaseScriptLen) 281 return ruleError(ErrBadCoinbaseScriptLen, str) 282 } 283 } else if isVote { 284 // Check script length of stake base signature. 285 slen := len(tx.TxIn[0].SignatureScript) 286 if slen < MinCoinbaseScriptLen || slen > MaxCoinbaseScriptLen { 287 str := fmt.Sprintf("stakebase transaction script "+ 288 "length of %d is out of range (min: %d, max: "+ 289 "%d)", slen, MinCoinbaseScriptLen, 290 MaxCoinbaseScriptLen) 291 return ruleError(ErrBadStakebaseScriptLen, str) 292 } 293 294 // The script must be set to the one specified by the network. 295 // Check script length of stake base signature. 296 if !bytes.Equal(tx.TxIn[0].SignatureScript, 297 params.StakeBaseSigScript) { 298 str := fmt.Sprintf("stakebase transaction signature "+ 299 "script was set to disallowed value (got %x, "+ 300 "want %x)", tx.TxIn[0].SignatureScript, 301 params.StakeBaseSigScript) 302 return ruleError(ErrBadStakebaseScrVal, str) 303 } 304 305 // The ticket reference hash in an SSGen tx must not be null. 306 ticketHash := &tx.TxIn[1].PreviousOutPoint 307 if isNullOutpoint(ticketHash) { 308 return ruleError(ErrBadTxInput, "ssgen tx ticket input"+ 309 " refers to previous output that is null") 310 } 311 } else { 312 // Previous transaction outputs referenced by the inputs to 313 // this transaction must not be null except in the case of 314 // stakebases for votes. 315 for _, txIn := range tx.TxIn { 316 prevOut := &txIn.PreviousOutPoint 317 if isNullOutpoint(prevOut) { 318 return ruleError(ErrBadTxInput, "transaction "+ 319 "input refers to previous output that "+ 320 "is null") 321 } 322 } 323 } 324 325 // Ensure the transaction amounts are in range. Each transaction output 326 // must not be negative or more than the max allowed per transaction. Also, 327 // the total of all outputs must abide by the same restrictions. All 328 // amounts in a transaction are in a unit value known as an atom. One 329 // Decred is a quantity of atoms as defined by the AtomsPerCoin constant. 330 // 331 // Also ensure that non-stake transaction output scripts do not contain any 332 // stake opcodes. 333 isTicket := !isVote && stake.IsSStx(tx) 334 isRevocation := !isVote && !isTicket && stake.IsSSRtx(tx) 335 isStakeTx := isVote || isTicket || isRevocation 336 var totalAtom int64 337 for txOutIdx, txOut := range tx.TxOut { 338 atom := txOut.Value 339 if atom < 0 { 340 str := fmt.Sprintf("transaction output has negative value of %v", 341 atom) 342 return ruleError(ErrBadTxOutValue, str) 343 } 344 if atom > dcrutil.MaxAmount { 345 str := fmt.Sprintf("transaction output value of %v is higher than "+ 346 "max allowed value of %v", atom, dcrutil.MaxAmount) 347 return ruleError(ErrBadTxOutValue, str) 348 } 349 350 // Two's complement int64 overflow guarantees that any overflow is 351 // detected and reported. This is impossible for Decred, but perhaps 352 // possible if an alt increases the total money supply. 353 totalAtom += atom 354 if totalAtom < 0 { 355 str := fmt.Sprintf("total value of all transaction outputs "+ 356 "exceeds max allowed value of %v", dcrutil.MaxAmount) 357 return ruleError(ErrBadTxOutValue, str) 358 } 359 if totalAtom > dcrutil.MaxAmount { 360 str := fmt.Sprintf("total value of all transaction outputs is %v "+ 361 "which is higher than max allowed value of %v", totalAtom, 362 dcrutil.MaxAmount) 363 return ruleError(ErrBadTxOutValue, str) 364 } 365 366 // Ensure that non-stake transactions have no outputs with opcodes 367 // OP_SSTX, OP_SSRTX, OP_SSGEN, or OP_SSTX_CHANGE. 368 if !isStakeTx { 369 hasOp, err := txscript.ContainsStakeOpCodes(txOut.PkScript) 370 if err != nil { 371 return ruleError(ErrScriptMalformed, err.Error()) 372 } 373 if hasOp { 374 str := fmt.Sprintf("non-stake transaction output %d contains "+ 375 "stake opcode", txOutIdx) 376 return ruleError(ErrRegTxCreateStakeOut, str) 377 } 378 } 379 } 380 381 // Check for duplicate transaction inputs. 382 existingTxOut := make(map[wire.OutPoint]struct{}) 383 for _, txIn := range tx.TxIn { 384 if _, exists := existingTxOut[txIn.PreviousOutPoint]; exists { 385 return ruleError(ErrDuplicateTxInputs, "transaction "+ 386 "contains duplicate inputs") 387 } 388 existingTxOut[txIn.PreviousOutPoint] = struct{}{} 389 } 390 391 return nil 392 } 393 394 // checkProofOfStake ensures that all ticket purchases in the block pay at least 395 // the amount required by the block header stake bits which indicate the target 396 // stake difficulty (aka ticket price) as claimed. 397 func checkProofOfStake(block *dcrutil.Block, posLimit int64) error { 398 msgBlock := block.MsgBlock() 399 for _, staketx := range block.STransactions() { 400 msgTx := staketx.MsgTx() 401 if stake.IsSStx(msgTx) { 402 commitValue := msgTx.TxOut[0].Value 403 404 // Check for underflow block sbits. 405 if commitValue < msgBlock.Header.SBits { 406 errStr := fmt.Sprintf("Stake tx %v has a "+ 407 "commitment value less than the "+ 408 "minimum stake difficulty specified in"+ 409 " the block (%v)", staketx.Hash(), 410 msgBlock.Header.SBits) 411 return ruleError(ErrNotEnoughStake, errStr) 412 } 413 414 // Check if it's above the PoS limit. 415 if commitValue < posLimit { 416 errStr := fmt.Sprintf("Stake tx %v has a "+ 417 "commitment value less than the "+ 418 "minimum stake difficulty for the "+ 419 "network (%v)", staketx.Hash(), 420 posLimit) 421 return ruleError(ErrStakeBelowMinimum, errStr) 422 } 423 } 424 } 425 426 return nil 427 } 428 429 // CheckProofOfStake ensures that all ticket purchases in the block pay at least 430 // the amount required by the block header stake bits which indicate the target 431 // stake difficulty (aka ticket price) as claimed. 432 func CheckProofOfStake(block *dcrutil.Block, posLimit int64) error { 433 return checkProofOfStake(block, posLimit) 434 } 435 436 // standaloneToChainRuleError attempts to convert the passed error from a 437 // standalone.RuleError to a blockchain.RuleError with the equivalent code. The 438 // error is simply passed through without modification if it is not a 439 // standalone.RuleError, not one of the specifically recognized error codes, or 440 // nil. 441 func standaloneToChainRuleError(err error) error { 442 // Convert standalone package rule errors to blockchain rule errors. 443 if rErr, ok := err.(standalone.RuleError); ok { 444 switch rErr.ErrorCode { 445 case standalone.ErrUnexpectedDifficulty: 446 return ruleError(ErrUnexpectedDifficulty, rErr.Description) 447 case standalone.ErrHighHash: 448 return ruleError(ErrHighHash, rErr.Description) 449 } 450 } 451 452 return err 453 } 454 455 // checkProofOfWork ensures the block header bits which indicate the target 456 // difficulty is in min/max range and that the block hash is less than the 457 // target difficulty as claimed. 458 // 459 // The flags modify the behavior of this function as follows: 460 // - BFNoPoWCheck: The check to ensure the block hash is less than the target 461 // difficulty is not performed. 462 func checkProofOfWork(header *wire.BlockHeader, powLimit *big.Int, flags BehaviorFlags) error { 463 // Only ensure the target difficulty bits are in the valid range when the 464 // the flag to avoid proof of work checks is set. 465 if flags&BFNoPoWCheck == BFNoPoWCheck { 466 err := standalone.CheckProofOfWorkRange(header.Bits, powLimit) 467 return standaloneToChainRuleError(err) 468 } 469 470 // Perform all proof of work checks when the flag is not set: 471 // 472 // - The target difficulty must be larger than zero. 473 // - The target difficulty must be less than the maximum allowed. 474 // - The block hash must be less than the claimed target. 475 blockHash := header.BlockHash() 476 err := standalone.CheckProofOfWork(&blockHash, header.Bits, powLimit) 477 return standaloneToChainRuleError(err) 478 } 479 480 // CheckProofOfWork ensures the block header bits which indicate the target 481 // difficulty is in min/max range and that the block hash is less than the 482 // target difficulty as claimed. This is equivalent to the function in the 483 // standalone package with the exception that that any error is converted to a 484 // RuleError. 485 // 486 // Deprecated: Use standalone.CheckProofOfWork instead. 487 func CheckProofOfWork(header *wire.BlockHeader, powLimit *big.Int) error { 488 return checkProofOfWork(header, powLimit, BFNone) 489 } 490 491 // checkBlockHeaderSanity performs some preliminary checks on a block header to 492 // ensure it is sane before continuing with processing. These checks are 493 // context free. 494 // 495 // The flags do not modify the behavior of this function directly, however they 496 // are needed to pass along to checkProofOfWork. 497 func checkBlockHeaderSanity(header *wire.BlockHeader, timeSource MedianTimeSource, flags BehaviorFlags, chainParams *chaincfg.Params) error { 498 // The stake validation height should always be at least stake enabled 499 // height, so assert it because the code below relies on that assumption. 500 stakeValidationHeight := uint32(chainParams.StakeValidationHeight) 501 stakeEnabledHeight := uint32(chainParams.StakeEnabledHeight) 502 if stakeEnabledHeight > stakeValidationHeight { 503 return AssertError(fmt.Sprintf("checkBlockHeaderSanity called "+ 504 "with stake enabled height %d after stake validation "+ 505 "height %d", stakeEnabledHeight, stakeValidationHeight)) 506 } 507 508 // Ensure the proof of work bits in the block header is in min/max 509 // range and the block hash is less than the target value described by 510 // the bits. 511 err := checkProofOfWork(header, chainParams.PowLimit, flags) 512 if err != nil { 513 return err 514 } 515 516 // A block timestamp must not have a greater precision than one second. 517 // This check is necessary because Go time.Time values support 518 // nanosecond precision whereas the consensus rules only apply to 519 // seconds and it's much nicer to deal with standard Go time values 520 // instead of converting to seconds everywhere. 521 if !header.Timestamp.Equal(time.Unix(header.Timestamp.Unix(), 0)) { 522 str := fmt.Sprintf("block timestamp of %v has a higher "+ 523 "precision than one second", header.Timestamp) 524 return ruleError(ErrInvalidTime, str) 525 } 526 527 // Ensure the block time is not too far in the future. 528 maxTimestamp := timeSource.AdjustedTime().Add(time.Second * 529 MaxTimeOffsetSeconds) 530 if header.Timestamp.After(maxTimestamp) { 531 str := fmt.Sprintf("block timestamp of %v is too far in the "+ 532 "future", header.Timestamp) 533 return ruleError(ErrTimeTooNew, str) 534 } 535 536 // A block must not contain any votes or revocations, its vote bits 537 // must be 0x0001, and its final state must be all zeroes before 538 // stake validation begins. 539 if header.Height < stakeValidationHeight { 540 if header.Voters > 0 { 541 errStr := fmt.Sprintf("block at height %d commits to "+ 542 "%d votes before stake validation height %d", 543 header.Height, header.Voters, 544 stakeValidationHeight) 545 return ruleError(ErrInvalidEarlyStakeTx, errStr) 546 } 547 548 if header.Revocations > 0 { 549 errStr := fmt.Sprintf("block at height %d commits to "+ 550 "%d revocations before stake validation height %d", 551 header.Height, header.Revocations, 552 stakeValidationHeight) 553 return ruleError(ErrInvalidEarlyStakeTx, errStr) 554 } 555 556 if header.VoteBits != earlyVoteBitsValue { 557 errStr := fmt.Sprintf("block at height %d commits to "+ 558 "invalid vote bits before stake validation "+ 559 "height %d (expected %x, got %x)", 560 header.Height, stakeValidationHeight, 561 earlyVoteBitsValue, header.VoteBits) 562 return ruleError(ErrInvalidEarlyVoteBits, errStr) 563 } 564 565 if header.FinalState != earlyFinalState { 566 errStr := fmt.Sprintf("block at height %d commits to "+ 567 "invalid final state before stake validation "+ 568 "height %d (expected %x, got %x)", 569 header.Height, stakeValidationHeight, 570 earlyFinalState, header.FinalState) 571 return ruleError(ErrInvalidEarlyFinalState, errStr) 572 } 573 } 574 575 // A block must not contain fewer votes than the minimum required to 576 // reach majority once stake validation height has been reached. 577 if header.Height >= stakeValidationHeight { 578 majority := (chainParams.TicketsPerBlock / 2) + 1 579 if header.Voters < majority { 580 errStr := fmt.Sprintf("block does not commit to enough "+ 581 "votes (min: %d, got %d)", majority, 582 header.Voters) 583 return ruleError(ErrNotEnoughVotes, errStr) 584 } 585 } 586 587 // The block header must not claim to contain more votes than the 588 // maximum allowed. 589 if header.Voters > chainParams.TicketsPerBlock { 590 errStr := fmt.Sprintf("block commits to too many votes (max: "+ 591 "%d, got %d)", chainParams.TicketsPerBlock, header.Voters) 592 return ruleError(ErrTooManyVotes, errStr) 593 } 594 595 // The block must not contain more ticket purchases than the maximum 596 // allowed. 597 if header.FreshStake > chainParams.MaxFreshStakePerBlock { 598 errStr := fmt.Sprintf("block commits to too many ticket "+ 599 "purchases (max: %d, got %d)", 600 chainParams.MaxFreshStakePerBlock, header.FreshStake) 601 return ruleError(ErrTooManySStxs, errStr) 602 } 603 604 return nil 605 } 606 607 // checkBlockSanity performs some preliminary checks on a block to ensure it is 608 // sane before continuing with block processing. These checks are context 609 // free. 610 // 611 // The flags do not modify the behavior of this function directly, however they 612 // are needed to pass along to checkBlockHeaderSanity. 613 func checkBlockSanity(block *dcrutil.Block, timeSource MedianTimeSource, flags BehaviorFlags, chainParams *chaincfg.Params) error { 614 msgBlock := block.MsgBlock() 615 header := &msgBlock.Header 616 err := checkBlockHeaderSanity(header, timeSource, flags, chainParams) 617 if err != nil { 618 return err 619 } 620 621 // All ticket purchases must meet the difficulty specified by the block 622 // header. 623 err = checkProofOfStake(block, chainParams.MinimumStakeDiff) 624 if err != nil { 625 return err 626 } 627 628 // A block must have at least one regular transaction. 629 numTx := len(msgBlock.Transactions) 630 if numTx == 0 { 631 return ruleError(ErrNoTransactions, "block does not contain "+ 632 "any transactions") 633 } 634 635 // A block must not exceed the maximum allowed block payload when 636 // serialized. 637 // 638 // This is a quick and context-free sanity check of the maximum block 639 // size according to the wire protocol. Even though the wire protocol 640 // already prevents blocks bigger than this limit, there are other 641 // methods of receiving a block that might not have been checked 642 // already. A separate block size is enforced later that takes into 643 // account the network-specific block size and the results of block 644 // size votes. Typically that block size is more restrictive than this 645 // one. 646 serializedSize := msgBlock.SerializeSize() 647 if serializedSize > wire.MaxBlockPayload { 648 str := fmt.Sprintf("serialized block is too big - got %d, "+ 649 "max %d", serializedSize, wire.MaxBlockPayload) 650 return ruleError(ErrBlockTooBig, str) 651 } 652 if header.Size != uint32(serializedSize) { 653 str := fmt.Sprintf("serialized block is not size indicated in "+ 654 "header - got %d, expected %d", header.Size, 655 serializedSize) 656 return ruleError(ErrWrongBlockSize, str) 657 } 658 659 // The first transaction in a block's regular tree must be a coinbase. 660 transactions := block.Transactions() 661 if !standalone.IsCoinBaseTx(transactions[0].MsgTx()) { 662 return ruleError(ErrFirstTxNotCoinbase, "first transaction in "+ 663 "block is not a coinbase") 664 } 665 666 // A block must not have more than one coinbase. 667 for i, tx := range transactions[1:] { 668 if standalone.IsCoinBaseTx(tx.MsgTx()) { 669 str := fmt.Sprintf("block contains second coinbase at "+ 670 "index %d", i+1) 671 return ruleError(ErrMultipleCoinbases, str) 672 } 673 } 674 675 // Do some preliminary checks on each regular transaction to ensure they 676 // are sane before continuing. 677 for i, tx := range transactions { 678 // A block must not have stake transactions in the regular 679 // transaction tree. 680 msgTx := tx.MsgTx() 681 txType := stake.DetermineTxType(msgTx) 682 if txType != stake.TxTypeRegular { 683 errStr := fmt.Sprintf("block contains a stake "+ 684 "transaction in the regular transaction tree at "+ 685 "index %d", i) 686 return ruleError(ErrStakeTxInRegularTree, errStr) 687 } 688 689 err := CheckTransactionSanity(msgTx, chainParams) 690 if err != nil { 691 return err 692 } 693 } 694 695 // Do some preliminary checks on each stake transaction to ensure they 696 // are sane while tallying each type before continuing. 697 stakeValidationHeight := uint32(chainParams.StakeValidationHeight) 698 var totalTickets, totalVotes, totalRevocations int64 699 var totalYesVotes int64 700 for txIdx, stx := range msgBlock.STransactions { 701 err := CheckTransactionSanity(stx, chainParams) 702 if err != nil { 703 return err 704 } 705 706 // A block must not have regular transactions in the stake 707 // transaction tree. 708 txType := stake.DetermineTxType(stx) 709 if txType == stake.TxTypeRegular { 710 errStr := fmt.Sprintf("block contains regular "+ 711 "transaction in stake transaction tree at "+ 712 "index %d", txIdx) 713 return ruleError(ErrRegTxInStakeTree, errStr) 714 } 715 716 switch txType { 717 case stake.TxTypeSStx: 718 totalTickets++ 719 720 case stake.TxTypeSSGen: 721 totalVotes++ 722 723 // All votes in a block must commit to the parent of the 724 // block once stake validation height has been reached. 725 if header.Height >= stakeValidationHeight { 726 votedHash, votedHeight := stake.SSGenBlockVotedOn(stx) 727 if (votedHash != header.PrevBlock) || (votedHeight != 728 header.Height-1) { 729 730 errStr := fmt.Sprintf("vote %s at index %d is "+ 731 "for parent block %s (height %d) versus "+ 732 "expected parent block %s (height %d)", 733 stx.TxHash(), txIdx, votedHash, 734 votedHeight, header.PrevBlock, 735 header.Height-1) 736 return ruleError(ErrVotesOnWrongBlock, errStr) 737 } 738 739 // Tally how many votes approve the previous block for use 740 // when validating the header commitment. 741 if voteBitsApproveParent(stake.SSGenVoteBits(stx)) { 742 totalYesVotes++ 743 } 744 } 745 746 case stake.TxTypeSSRtx: 747 totalRevocations++ 748 } 749 } 750 751 // A block must not contain more than the maximum allowed number of 752 // revocations. 753 if totalRevocations > maxRevocationsPerBlock { 754 errStr := fmt.Sprintf("block contains %d revocations which "+ 755 "exceeds the maximum allowed amount of %d", 756 totalRevocations, maxRevocationsPerBlock) 757 return ruleError(ErrTooManyRevocations, errStr) 758 } 759 760 // A block must only contain stake transactions of the the allowed 761 // types. 762 // 763 // NOTE: This is not possible to hit at the time this comment was 764 // written because all transactions which are not specifically one of 765 // the recognized stake transaction forms are considered regular 766 // transactions and those are rejected above. However, if a new stake 767 // transaction type is added, that implicit condition would no longer 768 // hold and therefore an explicit check is performed here. 769 numStakeTx := int64(len(msgBlock.STransactions)) 770 calcStakeTx := totalTickets + totalVotes + totalRevocations 771 if numStakeTx != calcStakeTx { 772 errStr := fmt.Sprintf("block contains an unexpected number "+ 773 "of stake transactions (contains %d, expected %d)", 774 numStakeTx, calcStakeTx) 775 return ruleError(ErrNonstandardStakeTx, errStr) 776 } 777 778 // A block header must commit to the actual number of tickets purchases that 779 // are in the block. 780 if int64(header.FreshStake) != totalTickets { 781 errStr := fmt.Sprintf("block header commitment to %d ticket "+ 782 "purchases does not match %d contained in the block", 783 header.FreshStake, totalTickets) 784 return ruleError(ErrFreshStakeMismatch, errStr) 785 } 786 787 // A block header must commit to the the actual number of votes that are 788 // in the block. 789 if int64(header.Voters) != totalVotes { 790 errStr := fmt.Sprintf("block header commitment to %d votes "+ 791 "does not match %d contained in the block", 792 header.Voters, totalVotes) 793 return ruleError(ErrVotesMismatch, errStr) 794 } 795 796 // A block header must commit to the actual number of revocations that 797 // are in the block. 798 if int64(header.Revocations) != totalRevocations { 799 errStr := fmt.Sprintf("block header commitment to %d revocations "+ 800 "does not match %d contained in the block", 801 header.Revocations, totalRevocations) 802 return ruleError(ErrRevocationsMismatch, errStr) 803 } 804 805 // A block header must commit to the same previous block acceptance 806 // semantics expressed by the votes once stake validation height has 807 // been reached. 808 if header.Height >= stakeValidationHeight { 809 totalNoVotes := totalVotes - totalYesVotes 810 headerApproves := headerApprovesParent(header) 811 votesApprove := totalYesVotes > totalNoVotes 812 if headerApproves != votesApprove { 813 errStr := fmt.Sprintf("block header commitment to previous "+ 814 "block approval does not match votes (header claims: %v, "+ 815 "votes: %v)", headerApproves, votesApprove) 816 return ruleError(ErrIncongruentVotebit, errStr) 817 } 818 } 819 820 // A block must not contain anything other than ticket purchases prior to 821 // stake validation height. 822 // 823 // NOTE: This case is impossible to hit at this point at the time this 824 // comment was written since the votes and revocations have already been 825 // proven to be zero before stake validation height and the only other 826 // type at the current time is ticket purchases, however, if another 827 // stake type is ever added, consensus would break without this check. 828 // It's better to be safe and it's a cheap check. 829 if header.Height < stakeValidationHeight { 830 if int64(len(msgBlock.STransactions)) != totalTickets { 831 errStr := fmt.Sprintf("block contains stake "+ 832 "transactions other than ticket purchases before "+ 833 "stake validation height %d (total: %d, expected %d)", 834 uint32(chainParams.StakeValidationHeight), 835 len(msgBlock.STransactions), header.FreshStake) 836 return ruleError(ErrInvalidEarlyStakeTx, errStr) 837 } 838 } 839 840 // Build merkle tree and ensure the calculated merkle root matches the 841 // entry in the block header. This also has the effect of caching all 842 // of the transaction hashes in the block to speed up future hash 843 // checks. Bitcoind builds the tree here and checks the merkle root 844 // after the following checks, but there is no reason not to check the 845 // merkle root matches here. 846 wantMerkleRoot := standalone.CalcTxTreeMerkleRoot(msgBlock.Transactions) 847 if header.MerkleRoot != wantMerkleRoot { 848 str := fmt.Sprintf("block merkle root is invalid - block "+ 849 "header indicates %v, but calculated value is %v", 850 header.MerkleRoot, wantMerkleRoot) 851 return ruleError(ErrBadMerkleRoot, str) 852 } 853 854 // Build the stake tx tree merkle root too and check it. 855 wantStakeRoot := standalone.CalcTxTreeMerkleRoot(msgBlock.STransactions) 856 if header.StakeRoot != wantStakeRoot { 857 str := fmt.Sprintf("block stake merkle root is invalid - block"+ 858 " header indicates %v, but calculated value is %v", 859 header.StakeRoot, wantStakeRoot) 860 return ruleError(ErrBadMerkleRoot, str) 861 } 862 863 // Check for duplicate transactions. This check will be fairly quick 864 // since the transaction hashes are already cached due to building the 865 // merkle trees above. 866 existingTxHashes := make(map[chainhash.Hash]struct{}) 867 stakeTransactions := block.STransactions() 868 allTransactions := append(transactions, stakeTransactions...) 869 870 for _, tx := range allTransactions { 871 hash := tx.Hash() 872 if _, exists := existingTxHashes[*hash]; exists { 873 str := fmt.Sprintf("block contains duplicate "+ 874 "transaction %v", hash) 875 return ruleError(ErrDuplicateTx, str) 876 } 877 existingTxHashes[*hash] = struct{}{} 878 } 879 880 // The number of signature operations must be less than the maximum 881 // allowed per block. 882 totalSigOps := 0 883 for _, tx := range allTransactions { 884 // We could potentially overflow the accumulator so check for 885 // overflow. 886 lastSigOps := totalSigOps 887 888 msgTx := tx.MsgTx() 889 isCoinBase := standalone.IsCoinBaseTx(msgTx) 890 isSSGen := stake.IsSSGen(msgTx) 891 totalSigOps += CountSigOps(tx, isCoinBase, isSSGen) 892 if totalSigOps < lastSigOps || totalSigOps > MaxSigOpsPerBlock { 893 str := fmt.Sprintf("block contains too many signature "+ 894 "operations - got %v, max %v", totalSigOps, 895 MaxSigOpsPerBlock) 896 return ruleError(ErrTooManySigOps, str) 897 } 898 } 899 900 return nil 901 } 902 903 // CheckBlockSanity performs some preliminary checks on a block to ensure it is 904 // sane before continuing with block processing. These checks are context 905 // free. 906 func CheckBlockSanity(block *dcrutil.Block, timeSource MedianTimeSource, chainParams *chaincfg.Params) error { 907 return checkBlockSanity(block, timeSource, BFNone, chainParams) 908 } 909 910 // checkBlockHeaderPositional performs several validation checks on the block 911 // header which depend on its position within the block chain and having the 912 // headers of all ancestors available. These checks do not, and must not, rely 913 // on having the full block data of all ancestors available. 914 // 915 // The flags modify the behavior of this function as follows: 916 // - BFFastAdd: All checks except those involving comparing the header against 917 // the checkpoints and expected height are not performed. 918 // 919 // This function MUST be called with the chain state lock held (for reads). 920 func (b *BlockChain) checkBlockHeaderPositional(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { 921 // The genesis block is valid by definition. 922 if prevNode == nil { 923 return nil 924 } 925 926 fastAdd := flags&BFFastAdd == BFFastAdd 927 if !fastAdd { 928 // Ensure the difficulty specified in the block header matches 929 // the calculated difficulty based on the previous block and 930 // difficulty retarget rules. 931 expDiff, err := b.calcNextRequiredDifficulty(prevNode, 932 header.Timestamp) 933 if err != nil { 934 return err 935 } 936 blockDifficulty := header.Bits 937 if blockDifficulty != expDiff { 938 str := fmt.Sprintf("block difficulty of %d is not the"+ 939 " expected value of %d", blockDifficulty, 940 expDiff) 941 return ruleError(ErrUnexpectedDifficulty, str) 942 } 943 944 // Ensure the timestamp for the block header is after the 945 // median time of the last several blocks (medianTimeBlocks). 946 medianTime := prevNode.CalcPastMedianTime() 947 if !header.Timestamp.After(medianTime) { 948 str := "block timestamp of %v is not after expected %v" 949 str = fmt.Sprintf(str, header.Timestamp, medianTime) 950 return ruleError(ErrTimeTooOld, str) 951 } 952 } 953 954 // The height of this block is one more than the referenced previous 955 // block. 956 blockHeight := prevNode.height + 1 957 958 // Ensure the header commits to the correct height based on the height it 959 // actually connects in the blockchain. 960 if int64(header.Height) != blockHeight { 961 errStr := fmt.Sprintf("block header commitment to height %d "+ 962 "does not match chain height %d", header.Height, 963 blockHeight) 964 return ruleError(ErrBadBlockHeight, errStr) 965 } 966 967 // Ensure chain matches up to predetermined checkpoints. 968 blockHash := header.BlockHash() 969 if !b.verifyCheckpoint(blockHeight, &blockHash) { 970 str := fmt.Sprintf("block at height %d does not match "+ 971 "checkpoint hash", blockHeight) 972 return ruleError(ErrBadCheckpoint, str) 973 } 974 975 // Find the previous checkpoint and prevent blocks which fork the main 976 // chain before it. This prevents storage of new, otherwise valid, 977 // blocks which build off of old blocks that are likely at a much easier 978 // difficulty and therefore could be used to waste cache and disk space. 979 checkpointNode, err := b.findPreviousCheckpoint() 980 if err != nil { 981 return err 982 } 983 if checkpointNode != nil && blockHeight < checkpointNode.height { 984 str := fmt.Sprintf("block at height %d forks the main chain "+ 985 "before the previous checkpoint at height %d", 986 blockHeight, checkpointNode.height) 987 return ruleError(ErrForkTooOld, str) 988 } 989 990 if !fastAdd { 991 // Reject version 6 blocks for networks other than the main 992 // network once a majority of the network has upgraded. 993 if b.chainParams.Net != wire.MainNet && header.Version < 7 && 994 b.isMajorityVersion(7, prevNode, b.chainParams.BlockRejectNumRequired) { 995 996 str := "new blocks with version %d are no longer valid" 997 str = fmt.Sprintf(str, header.Version) 998 return ruleError(ErrBlockVersionTooOld, str) 999 } 1000 1001 // Reject version 5 blocks once a majority of the network has 1002 // upgraded. 1003 if header.Version < 6 && b.isMajorityVersion(6, prevNode, 1004 b.chainParams.BlockRejectNumRequired) { 1005 1006 str := "new blocks with version %d are no longer valid" 1007 str = fmt.Sprintf(str, header.Version) 1008 return ruleError(ErrBlockVersionTooOld, str) 1009 } 1010 1011 // Reject version 4 blocks once a majority of the network has 1012 // upgraded. 1013 if header.Version < 5 && b.isMajorityVersion(5, prevNode, 1014 b.chainParams.BlockRejectNumRequired) { 1015 1016 str := "new blocks with version %d are no longer valid" 1017 str = fmt.Sprintf(str, header.Version) 1018 return ruleError(ErrBlockVersionTooOld, str) 1019 } 1020 1021 // Reject version 3 blocks once a majority of the network has 1022 // upgraded. 1023 if header.Version < 4 && b.isMajorityVersion(4, prevNode, 1024 b.chainParams.BlockRejectNumRequired) { 1025 1026 str := "new blocks with version %d are no longer valid" 1027 str = fmt.Sprintf(str, header.Version) 1028 return ruleError(ErrBlockVersionTooOld, str) 1029 } 1030 1031 // Reject version 2 blocks once a majority of the network has 1032 // upgraded. 1033 if header.Version < 3 && b.isMajorityVersion(3, prevNode, 1034 b.chainParams.BlockRejectNumRequired) { 1035 1036 str := "new blocks with version %d are no longer valid" 1037 str = fmt.Sprintf(str, header.Version) 1038 return ruleError(ErrBlockVersionTooOld, str) 1039 } 1040 1041 // Reject version 1 blocks once a majority of the network has 1042 // upgraded. 1043 if header.Version < 2 && b.isMajorityVersion(2, prevNode, 1044 b.chainParams.BlockRejectNumRequired) { 1045 1046 str := "new blocks with version %d are no longer valid" 1047 str = fmt.Sprintf(str, header.Version) 1048 return ruleError(ErrBlockVersionTooOld, str) 1049 } 1050 } 1051 1052 return nil 1053 } 1054 1055 // checkBlockPositional performs several validation checks on the block which 1056 // depend on its position within the block chain and having the headers of all 1057 // ancestors available. These checks do not, and must not, rely on having the 1058 // full block data of all ancestors available. 1059 // 1060 // The flags modify the behavior of this function as follows: 1061 // - BFFastAdd: The transactions are not checked to see if they are expired and 1062 // the coinbae height check is not performed. 1063 // 1064 // The flags are also passed to checkBlockHeaderPositional. See its 1065 // documentation for how the flags modify its behavior. 1066 func (b *BlockChain) checkBlockPositional(block *dcrutil.Block, prevNode *blockNode, flags BehaviorFlags) error { 1067 // The genesis block is valid by definition. 1068 if prevNode == nil { 1069 return nil 1070 } 1071 1072 // Perform all block header related validation checks that depend on its 1073 // position within the block chain and having the headers of all 1074 // ancestors available, but do not rely on having the full block data of 1075 // all ancestors available. 1076 header := &block.MsgBlock().Header 1077 err := b.checkBlockHeaderPositional(header, prevNode, flags) 1078 if err != nil { 1079 return err 1080 } 1081 1082 fastAdd := flags&BFFastAdd == BFFastAdd 1083 if !fastAdd { 1084 // The height of this block is one more than the referenced 1085 // previous block. 1086 blockHeight := prevNode.height + 1 1087 1088 // Ensure all transactions in the block are not expired. 1089 for _, tx := range block.Transactions() { 1090 if IsExpired(tx, blockHeight) { 1091 errStr := fmt.Sprintf("block contains expired regular "+ 1092 "transaction %v (expiration height %d)", tx.Hash(), 1093 tx.MsgTx().Expiry) 1094 return ruleError(ErrExpiredTx, errStr) 1095 } 1096 } 1097 for _, stx := range block.STransactions() { 1098 if IsExpired(stx, blockHeight) { 1099 errStr := fmt.Sprintf("block contains expired stake "+ 1100 "transaction %v (expiration height %d)", stx.Hash(), 1101 stx.MsgTx().Expiry) 1102 return ruleError(ErrExpiredTx, errStr) 1103 } 1104 } 1105 1106 // Check that the coinbase contains at minimum the block 1107 // height in output 1. 1108 if blockHeight > 1 { 1109 err := checkCoinbaseUniqueHeight(blockHeight, block) 1110 if err != nil { 1111 return err 1112 } 1113 } 1114 } 1115 1116 return nil 1117 } 1118 1119 // checkBlockHeaderContext performs several validation checks on the block 1120 // header which depend on having the full block data for all of its ancestors 1121 // available. This includes checks which depend on tallying the results of 1122 // votes, because votes are part of the block data. 1123 // 1124 // It should be noted that rule changes that have become buried deep enough 1125 // typically will eventually be transitioned to using well-known activation 1126 // points for efficiency purposes at which point the associated checks no longer 1127 // require having direct access to the historical votes, and therefore may be 1128 // transitioned to checkBlockHeaderPositional at that time. Conversely, any 1129 // checks in that function which become conditional based on the results of a 1130 // vote will necessarily need to be transitioned to this function. 1131 // 1132 // The flags modify the behavior of this function as follows: 1133 // - BFFastAdd: No check are performed. 1134 // 1135 // This function MUST be called with the chain state lock held (for writes). 1136 func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { 1137 // The genesis block is valid by definition. 1138 if prevNode == nil { 1139 return nil 1140 } 1141 1142 fastAdd := flags&BFFastAdd == BFFastAdd 1143 if !fastAdd { 1144 // Ensure the stake difficulty specified in the block header 1145 // matches the calculated difficulty based on the previous block 1146 // and difficulty retarget rules. 1147 expSDiff, err := b.calcNextRequiredStakeDifficulty(prevNode) 1148 if err != nil { 1149 return err 1150 } 1151 if header.SBits != expSDiff { 1152 errStr := fmt.Sprintf("block stake difficulty of %d "+ 1153 "is not the expected value of %d", header.SBits, 1154 expSDiff) 1155 return ruleError(ErrUnexpectedDifficulty, errStr) 1156 } 1157 1158 // Enforce the stake version in the header once a majority of 1159 // the network has upgraded to version 3 blocks. 1160 if header.Version >= 3 && b.isMajorityVersion(3, prevNode, 1161 b.chainParams.BlockEnforceNumRequired) { 1162 1163 expectedStakeVer := b.calcStakeVersion(prevNode) 1164 if header.StakeVersion != expectedStakeVer { 1165 str := fmt.Sprintf("block stake version of %d "+ 1166 "is not the expected version of %d", 1167 header.StakeVersion, expectedStakeVer) 1168 return ruleError(ErrBadStakeVersion, str) 1169 } 1170 } 1171 1172 // Ensure the header commits to the correct pool size based on 1173 // its position within the chain. 1174 parentStakeNode, err := b.fetchStakeNode(prevNode) 1175 if err != nil { 1176 return err 1177 } 1178 calcPoolSize := uint32(parentStakeNode.PoolSize()) 1179 if header.PoolSize != calcPoolSize { 1180 errStr := fmt.Sprintf("block header commitment to "+ 1181 "pool size %d does not match expected size %d", 1182 header.PoolSize, calcPoolSize) 1183 return ruleError(ErrPoolSize, errStr) 1184 } 1185 1186 // Ensure the header commits to the correct final state of the 1187 // ticket lottery. 1188 calcFinalState := parentStakeNode.FinalState() 1189 if header.FinalState != calcFinalState { 1190 errStr := fmt.Sprintf("block header commitment to "+ 1191 "final state of the ticket lottery %x does not "+ 1192 "match expected value %x", header.FinalState, 1193 calcFinalState) 1194 return ruleError(ErrInvalidFinalState, errStr) 1195 } 1196 } 1197 1198 return nil 1199 } 1200 1201 // checkCoinbaseUniqueHeight checks to ensure that for all blocks height > 1 the 1202 // coinbase contains the height encoding to make coinbase hash collisions 1203 // impossible. 1204 func checkCoinbaseUniqueHeight(blockHeight int64, block *dcrutil.Block) error { 1205 // Coinbase output 0 is the project subsidy, and output 1 is height + 1206 // extranonce, so at least two outputs must exist. 1207 const minReqOutputs = 2 1208 coinbaseTx := block.MsgBlock().Transactions[0] 1209 if len(coinbaseTx.TxOut) < minReqOutputs { 1210 str := fmt.Sprintf("block %s is missing required coinbase outputs ("+ 1211 "num outputs: %d, min required: %d)", block.Hash(), 1212 len(coinbaseTx.TxOut), minReqOutputs) 1213 return ruleError(ErrFirstTxNotCoinbase, str) 1214 } 1215 1216 // Only version 0 scripts are currently valid. 1217 const scriptVersion = 0 1218 nullDataOut := coinbaseTx.TxOut[1] 1219 if nullDataOut.Version != scriptVersion { 1220 str := fmt.Sprintf("block %s coinbase output 1 script version %d is "+ 1221 "not the required version %d", block.Hash(), nullDataOut.Version, 1222 scriptVersion) 1223 return ruleError(ErrFirstTxNotCoinbase, str) 1224 } 1225 1226 // The nulldata in the coinbase must be a single OP_RETURN followed by a 1227 // data push up to maxUniqueCoinbaseNullDataSize bytes and the first 4 bytes 1228 // of that data must be the encoded height of the block so that every 1229 // coinbase created has a unique transaction hash. 1230 // 1231 // NOTE: This is intentionally not using GetScriptClass and the related 1232 // functions because those are specifically for standardness checks which 1233 // can change over time and this function is enforces consensus rules. 1234 // 1235 // Also of note is that technically normal nulldata scripts support encoding 1236 // numbers via small opcodes, however, for legacy reasons, the consensus 1237 // rules require the block height to be encoded as a 4-byte little-endian 1238 // uint32 pushed via a normal data push, as opposed to using the normal 1239 // number handling semantics of scripts, so this is specialized to 1240 // accommodate that. 1241 var nullData []byte 1242 pkScript := nullDataOut.PkScript 1243 if len(pkScript) > 1 && pkScript[0] == txscript.OP_RETURN { 1244 tokenizer := txscript.MakeScriptTokenizer(scriptVersion, pkScript[1:]) 1245 if tokenizer.Next() && tokenizer.Done() && tokenizer.Opcode() <= 1246 txscript.OP_PUSHDATA4 { 1247 1248 nullData = tokenizer.Data() 1249 } 1250 } 1251 if len(nullData) > maxUniqueCoinbaseNullDataSize { 1252 str := fmt.Sprintf("block %s coinbase output 1 pushes %d bytes which "+ 1253 "is more than allowed value of %d", block.Hash(), len(nullData), 1254 maxUniqueCoinbaseNullDataSize) 1255 return ruleError(ErrFirstTxNotCoinbase, str) 1256 } 1257 if len(nullData) < 4 { 1258 str := fmt.Sprintf("block %s coinbase output 1 pushes %d bytes which "+ 1259 "is too short to encode height", block.Hash(), len(nullData)) 1260 return ruleError(ErrFirstTxNotCoinbase, str) 1261 } 1262 1263 // Check the height and ensure it is correct. 1264 cbHeight := binary.LittleEndian.Uint32(nullData[0:4]) 1265 if cbHeight != uint32(blockHeight) { 1266 header := &block.MsgBlock().Header 1267 str := fmt.Sprintf("block %s coinbase output 1 encodes height %d "+ 1268 "instead of expected height %d (prev block: %s, header height %d)", 1269 block.Hash(), cbHeight, uint32(blockHeight), header.PrevBlock, 1270 header.Height) 1271 return ruleError(ErrCoinbaseHeight, str) 1272 } 1273 1274 return nil 1275 } 1276 1277 // checkAllowedVotes performs validation of all votes in the block to ensure 1278 // they spend tickets that are actually allowed to vote per the lottery. 1279 // 1280 // This function is safe for concurrent access. 1281 func (b *BlockChain) checkAllowedVotes(parentStakeNode *stake.Node, block *wire.MsgBlock) error { 1282 // Determine the winning ticket hashes and create a map for faster lookup. 1283 ticketsPerBlock := int(b.chainParams.TicketsPerBlock) 1284 winningHashes := make(map[chainhash.Hash]struct{}, ticketsPerBlock) 1285 for _, ticketHash := range parentStakeNode.Winners() { 1286 winningHashes[ticketHash] = struct{}{} 1287 } 1288 1289 for _, stx := range block.STransactions { 1290 // Ignore non-vote stake transactions. 1291 if !stake.IsSSGen(stx) { 1292 continue 1293 } 1294 1295 // Ensure the ticket being spent is actually eligible to vote in 1296 // this block. 1297 ticketHash := stx.TxIn[1].PreviousOutPoint.Hash 1298 if _, ok := winningHashes[ticketHash]; !ok { 1299 errStr := fmt.Sprintf("block contains vote for "+ 1300 "ineligible ticket %s (eligible tickets: %s)", 1301 ticketHash, winningHashes) 1302 return ruleError(ErrTicketUnavailable, errStr) 1303 } 1304 } 1305 1306 return nil 1307 } 1308 1309 // checkAllowedRevocations performs validation of all revocations in the block 1310 // to ensure they spend tickets that are actually allowed to be revoked per the 1311 // lottery. Tickets are only eligible to be revoked if they were missed or have 1312 // expired. 1313 // 1314 // This function is safe for concurrent access. 1315 func (b *BlockChain) checkAllowedRevocations(parentStakeNode *stake.Node, block *wire.MsgBlock) error { 1316 for _, stx := range block.STransactions { 1317 // Ignore non-revocation stake transactions. 1318 if !stake.IsSSRtx(stx) { 1319 continue 1320 } 1321 1322 // Ensure the ticket being spent is actually eligible to be 1323 // revoked in this block. 1324 ticketHash := stx.TxIn[0].PreviousOutPoint.Hash 1325 if !parentStakeNode.ExistsMissedTicket(ticketHash) { 1326 errStr := fmt.Sprintf("block contains revocation of "+ 1327 "ineligible ticket %s", ticketHash) 1328 return ruleError(ErrInvalidSSRtx, errStr) 1329 } 1330 } 1331 1332 return nil 1333 } 1334 1335 // checkBlockContext performs several validation checks on the block which depend 1336 // on having the full block data for all of its ancestors available. This 1337 // includes checks which depend on tallying the results of votes, because votes 1338 // are part of the block data. 1339 // 1340 // It should be noted that rule changes that have become buried deep enough 1341 // typically will eventually be transitioned to using well-known activation 1342 // points for efficiency purposes at which point the associated checks no longer 1343 // require having direct access to the historical votes, and therefore may be 1344 // transitioned to checkBlockPositional at that time. Conversely, any checks 1345 // in that function which become conditional based on the results of a vote will 1346 // necessarily need to be transitioned to this function. 1347 // 1348 // The flags modify the behavior of this function as follows: 1349 // - BFFastAdd: The max block size is not checked, transactions are not checked 1350 // to see if they are finalized, and the included votes and revocations are 1351 // not verified to be allowed. 1352 // 1353 // The flags are also passed to checkBlockHeaderContext. See its documentation 1354 // for how the flags modify its behavior. 1355 func (b *BlockChain) checkBlockContext(block *dcrutil.Block, prevNode *blockNode, flags BehaviorFlags) error { 1356 // The genesis block is valid by definition. 1357 if prevNode == nil { 1358 return nil 1359 } 1360 1361 // Perform all block header related validation checks which depend on 1362 // having the full block data for all of its ancestors available. 1363 header := &block.MsgBlock().Header 1364 err := b.checkBlockHeaderContext(header, prevNode, flags) 1365 if err != nil { 1366 return err 1367 } 1368 1369 fastAdd := flags&BFFastAdd == BFFastAdd 1370 if !fastAdd { 1371 // A block must not exceed the maximum allowed size as defined 1372 // by the network parameters and the current status of any hard 1373 // fork votes to change it when serialized. 1374 maxBlockSize, err := b.maxBlockSize(prevNode) 1375 if err != nil { 1376 return err 1377 } 1378 serializedSize := int64(block.MsgBlock().Header.Size) 1379 if serializedSize > maxBlockSize { 1380 str := fmt.Sprintf("serialized block is too big - "+ 1381 "got %d, max %d", serializedSize, 1382 maxBlockSize) 1383 return ruleError(ErrBlockTooBig, str) 1384 } 1385 1386 // Switch to using the past median time of the block prior to 1387 // the block being checked for all checks related to lock times 1388 // once the stake vote for the agenda is active. 1389 blockTime := header.Timestamp 1390 lnFeaturesActive, err := b.isLNFeaturesAgendaActive(prevNode) 1391 if err != nil { 1392 return err 1393 } 1394 if lnFeaturesActive { 1395 blockTime = prevNode.CalcPastMedianTime() 1396 } 1397 1398 // The height of this block is one more than the referenced 1399 // previous block. 1400 blockHeight := prevNode.height + 1 1401 1402 // Ensure all transactions in the block are finalized. 1403 for _, tx := range block.Transactions() { 1404 if !IsFinalizedTransaction(tx, blockHeight, blockTime) { 1405 str := fmt.Sprintf("block contains unfinalized regular "+ 1406 "transaction %v", tx.Hash()) 1407 return ruleError(ErrUnfinalizedTx, str) 1408 } 1409 } 1410 for _, stx := range block.STransactions() { 1411 if !IsFinalizedTransaction(stx, blockHeight, blockTime) { 1412 str := fmt.Sprintf("block contains unfinalized stake "+ 1413 "transaction %v", stx.Hash()) 1414 return ruleError(ErrUnfinalizedTx, str) 1415 } 1416 } 1417 1418 // Ensure that all votes are only for winning tickets and all 1419 // revocations are actually eligible to be revoked once stake 1420 // validation height has been reached. 1421 if blockHeight >= b.chainParams.StakeValidationHeight { 1422 parentStakeNode, err := b.fetchStakeNode(prevNode) 1423 if err != nil { 1424 return err 1425 } 1426 err = b.checkAllowedVotes(parentStakeNode, block.MsgBlock()) 1427 if err != nil { 1428 return err 1429 } 1430 1431 err = b.checkAllowedRevocations(parentStakeNode, 1432 block.MsgBlock()) 1433 if err != nil { 1434 return err 1435 } 1436 } 1437 } 1438 1439 return nil 1440 } 1441 1442 // checkDupTxs ensures blocks do not contain duplicate transactions which 1443 // 'overwrite' older transactions that are not fully spent. This prevents an 1444 // attack where a coinbase and all of its dependent transactions could be 1445 // duplicated to effectively revert the overwritten transactions to a single 1446 // confirmation thereby making them vulnerable to a double spend. 1447 // 1448 // For more details, see https://en.bitcoin.it/wiki/BIP_0030 and 1449 // http://r6.ca/blog/20120206T005236Z.html. 1450 // 1451 // Decred: Check the stake transactions to make sure they don't have this txid 1452 // too. 1453 func (b *BlockChain) checkDupTxs(txSet []*dcrutil.Tx, view *UtxoViewpoint) error { 1454 if !chaincfg.CheckForDuplicateHashes { 1455 return nil 1456 } 1457 1458 // Fetch utxo details for all of the transactions in this block. 1459 // Typically, there will not be any utxos for any of the transactions. 1460 filteredSet := make(viewFilteredSet) 1461 for _, tx := range txSet { 1462 filteredSet.add(view, tx.Hash()) 1463 } 1464 err := view.fetchUtxosMain(b.db, filteredSet) 1465 if err != nil { 1466 return err 1467 } 1468 1469 // Duplicate transactions are only allowed if the previous transaction 1470 // is fully spent. 1471 for _, tx := range txSet { 1472 txEntry := view.LookupEntry(tx.Hash()) 1473 if txEntry != nil && !txEntry.IsFullySpent() { 1474 str := fmt.Sprintf("tried to overwrite transaction %v "+ 1475 "at block height %d that is not fully spent", 1476 tx.Hash(), txEntry.BlockHeight()) 1477 return ruleError(ErrOverwriteTx, str) 1478 } 1479 } 1480 1481 return nil 1482 } 1483 1484 // extractStakePubKeyHash extracts a pubkey hash from the passed public key 1485 // script if it is a standard pay-to-pubkey-hash script tagged with the provided 1486 // stake opcode. It will return nil otherwise. 1487 func extractStakePubKeyHash(script []byte, stakeOpcode byte) []byte { 1488 if len(script) == 26 && 1489 script[0] == stakeOpcode && 1490 script[1] == txscript.OP_DUP && 1491 script[2] == txscript.OP_HASH160 && 1492 script[3] == txscript.OP_DATA_20 && 1493 script[24] == txscript.OP_EQUALVERIFY && 1494 script[25] == txscript.OP_CHECKSIG { 1495 1496 return script[4:24] 1497 } 1498 1499 return nil 1500 } 1501 1502 // isStakePubKeyHash returns whether or not the passed public key script is a 1503 // standard pay-to-pubkey-hash script tagged with the provided stake opcode. 1504 func isStakePubKeyHash(script []byte, stakeOpcode byte) bool { 1505 return extractStakePubKeyHash(script, stakeOpcode) != nil 1506 } 1507 1508 // extractStakeScriptHash extracts a script hash from the passed public key 1509 // script if it is a standard pay-to-script-hash script tagged with the provided 1510 // stake opcode. It will return nil otherwise. 1511 func extractStakeScriptHash(script []byte, stakeOpcode byte) []byte { 1512 if len(script) == 24 && 1513 script[0] == stakeOpcode && 1514 script[1] == txscript.OP_HASH160 && 1515 script[2] == txscript.OP_DATA_20 && 1516 script[23] == txscript.OP_EQUAL { 1517 1518 return script[3:23] 1519 } 1520 1521 return nil 1522 } 1523 1524 // isStakeScriptHash returns whether or not the passed public key script is a 1525 // standard pay-to-script-hash script tagged with the provided stake opcode. 1526 func isStakeScriptHash(script []byte, stakeOpcode byte) bool { 1527 return extractStakeScriptHash(script, stakeOpcode) != nil 1528 } 1529 1530 // isAllowedTicketInputScriptForm returns whether or not the passed public key 1531 // script is a one of the allowed forms for a ticket input. 1532 func isAllowedTicketInputScriptForm(script []byte) bool { 1533 return isPubKeyHash(script) || isScriptHash(script) || 1534 isStakePubKeyHash(script, txscript.OP_SSGEN) || 1535 isStakeScriptHash(script, txscript.OP_SSGEN) || 1536 isStakePubKeyHash(script, txscript.OP_SSRTX) || 1537 isStakeScriptHash(script, txscript.OP_SSRTX) || 1538 isStakePubKeyHash(script, txscript.OP_SSTXCHANGE) || 1539 isStakeScriptHash(script, txscript.OP_SSTXCHANGE) 1540 } 1541 1542 // extractTicketCommitAmount extracts and decodes the amount from a ticket 1543 // output commitment script. 1544 // 1545 // NOTE: The caller MUST have already determined that the provided script is 1546 // a commitment output script or the function may panic. 1547 func extractTicketCommitAmount(script []byte) int64 { 1548 // Extract the encoded amount from the commitment output associated with 1549 // the input. The MSB of the encoded amount specifies if the output is 1550 // P2SH, so it must be cleared to get the decoded amount. 1551 amtBytes := script[commitAmountStartIdx:commitAmountEndIdx] 1552 amtEncoded := binary.LittleEndian.Uint64(amtBytes) 1553 return int64(amtEncoded & ^commitP2SHFlag) 1554 } 1555 1556 // checkTicketPurchaseInputs performs a series of checks on the inputs to a 1557 // ticket purchase transaction. An example of some of the checks include 1558 // verifying all inputs exist, ensuring the input type requirements are met, 1559 // and validating the output commitments coincide with the inputs. 1560 // 1561 // NOTE: The caller MUST have already determined that the provided transaction 1562 // is a ticket purchase. 1563 func checkTicketPurchaseInputs(msgTx *wire.MsgTx, view *UtxoViewpoint) error { 1564 // Assert there are two outputs for each input to the ticket as well as the 1565 // additional voting rights output. 1566 if (len(msgTx.TxIn)*2 + 1) != len(msgTx.TxOut) { 1567 panicf("attempt to check ticket purchase inputs on tx %s which does "+ 1568 "not appear to be a ticket purchase (%d inputs, %d outputs)", 1569 msgTx.TxHash(), len(msgTx.TxIn), len(msgTx.TxOut)) 1570 } 1571 1572 for txInIdx := 0; txInIdx < len(msgTx.TxIn); txInIdx++ { 1573 txIn := msgTx.TxIn[txInIdx] 1574 originTxHash := &txIn.PreviousOutPoint.Hash 1575 originTxIndex := txIn.PreviousOutPoint.Index 1576 entry := view.LookupEntry(originTxHash) 1577 if entry == nil || entry.IsOutputSpent(originTxIndex) { 1578 str := fmt.Sprintf("output %v referenced from transaction %s:%d "+ 1579 "either does not exist or has already been spent", 1580 txIn.PreviousOutPoint, msgTx.TxHash(), txInIdx) 1581 return ruleError(ErrMissingTxOut, str) 1582 } 1583 1584 // Ensure the output being spent is one of the allowed script forms. In 1585 // particular, the allowed forms are pay-to-pubkey-hash and 1586 // pay-to-script-hash either in the standard form (without a stake 1587 // opcode) or their stake-tagged variant (with a stake opcode). 1588 pkScriptVer := entry.ScriptVersionByIndex(originTxIndex) 1589 if pkScriptVer != 0 { 1590 str := fmt.Sprintf("output %v script version %d referenced by "+ 1591 "ticket %s:%d is not supported", txIn.PreviousOutPoint, 1592 pkScriptVer, msgTx.TxHash(), txInIdx) 1593 return ruleError(ErrTicketInputScript, str) 1594 } 1595 pkScript := entry.PkScriptByIndex(originTxIndex) 1596 if !isAllowedTicketInputScriptForm(pkScript) { 1597 str := fmt.Sprintf("output %v referenced from ticket %s:%d "+ 1598 "is not pay-to-pubkey-hash or pay-to-script-hash (script: %x)", 1599 txIn.PreviousOutPoint, msgTx.TxHash(), txInIdx, pkScript) 1600 return ruleError(ErrTicketInputScript, str) 1601 } 1602 1603 // Extract the amount from the commitment output associated with the 1604 // input and ensure it matches the expected amount calculated from the 1605 // actual input amount and change. 1606 commitmentOutIdx := txInIdx*2 + 1 1607 commitmentScript := msgTx.TxOut[commitmentOutIdx].PkScript 1608 commitmentAmount := extractTicketCommitAmount(commitmentScript) 1609 inputAmount := entry.AmountByIndex(originTxIndex) 1610 change := msgTx.TxOut[commitmentOutIdx+1].Value 1611 adjustedAmount := commitmentAmount + change 1612 if adjustedAmount != inputAmount { 1613 str := fmt.Sprintf("ticket output %d pays a different amount than "+ 1614 "the associated input %d (input: %v, commitment: %v, change: "+ 1615 "%v)", commitmentOutIdx, txInIdx, inputAmount, commitmentAmount, 1616 change) 1617 return ruleError(ErrTicketCommitment, str) 1618 } 1619 } 1620 1621 return nil 1622 } 1623 1624 // isStakeSubmission returns whether or not the passed public key script is a 1625 // standard pay-to-script-hash or pay-to-script-hash script tagged with the 1626 // stake submission opcode. 1627 func isStakeSubmission(script []byte) bool { 1628 return isStakePubKeyHash(script, txscript.OP_SSTX) || 1629 isStakeScriptHash(script, txscript.OP_SSTX) 1630 } 1631 1632 // extractTicketCommitHash extracts the commitment hash from a ticket output 1633 // commitment script. 1634 // 1635 // NOTE: The caller MUST have already determined that the provided script is 1636 // a commitment output script or the function may panic. 1637 func extractTicketCommitHash(script []byte) []byte { 1638 return script[commitHashStartIdx:commitHashEndIdx] 1639 } 1640 1641 // isTicketCommitP2SH returns whether or not the passed ticket output commitment 1642 // script commits to a hash which represents a pay-to-script-hash output. When 1643 // false, it commits to a hash which represents a pay-to-pubkey-hash output. 1644 // 1645 // NOTE: The caller MUST have already determined that the provided script is 1646 // a commitment output script or the function may panic. 1647 func isTicketCommitP2SH(script []byte) bool { 1648 // The MSB of the encoded amount specifies if the output is P2SH. Since 1649 // it is encoded with little endian, the MSB is in final byte in the encoded 1650 // amount. 1651 // 1652 // This is a faster equivalent of: 1653 // 1654 // amtBytes := script[commitAmountStartIdx:commitAmountEndIdx] 1655 // amtEncoded := binary.LittleEndian.Uint64(amtBytes) 1656 // return (amtEncoded & commitP2SHFlag) != 0 1657 // 1658 return script[commitAmountEndIdx-1]&0x80 != 0 1659 } 1660 1661 // calcTicketReturnAmount calculates the required amount to return from a ticket 1662 // for a given original contribution amount, the price the ticket was purchased 1663 // for, the vote subsidy (if any) to include, and the sum of all contributions 1664 // used to purchase the ticket. 1665 // 1666 // Since multiple inputs can be used to purchase a ticket, each one contributes 1667 // a portion of the overall ticket purchase, including the transaction fee. 1668 // Thus, when claiming the ticket, either due to it being selected to vote, or 1669 // being revoked, each output must receive the same proportion of the total 1670 // amount returned. 1671 // 1672 // The vote subsidy must be 0 for revocations since, unlike votes, they do not 1673 // produce any additional subsidy. 1674 func calcTicketReturnAmount(contribAmount, ticketPurchaseAmount, voteSubsidy int64, contributionSumBig *big.Int) int64 { 1675 // This is effectively equivalent to: 1676 // 1677 // total output amount 1678 // return amount = ------------------- * contribution amount 1679 // total contributions 1680 // 1681 // However, in order to avoid floating point math, it uses 64.32 fixed point 1682 // integer division to perform: 1683 // 1684 // -- -- 1685 // | total output amount * contribution amount * 2^32 | 1686 // | ------------------------------------------------ | 1687 // return amount = | total contributions | 1688 // -- -- 1689 // ---------------------------------------------------- 1690 // 2^32 1691 // 1692 totalOutputAmtBig := big.NewInt(ticketPurchaseAmount + voteSubsidy) 1693 returnAmtBig := big.NewInt(contribAmount) 1694 returnAmtBig.Mul(returnAmtBig, totalOutputAmtBig) 1695 returnAmtBig.Lsh(returnAmtBig, 32) 1696 returnAmtBig.Div(returnAmtBig, contributionSumBig) 1697 returnAmtBig.Rsh(returnAmtBig, 32) 1698 return returnAmtBig.Int64() 1699 } 1700 1701 // extractTicketCommitFeeLimits extracts the encoded fee limits from a ticket 1702 // output commitment script. 1703 // 1704 // NOTE: The caller MUST have already determined that the provided script is 1705 // a commitment output script or the function may panic. 1706 func extractTicketCommitFeeLimits(script []byte) uint16 { 1707 encodedLimits := script[commitFeeLimitStartIdx:commitFeeLimitEndIdx] 1708 return binary.LittleEndian.Uint16(encodedLimits) 1709 } 1710 1711 // checkTicketSubmissionInput ensures the provided unspent transaction output is 1712 // a supported ticket submission output in terms of the script version and type 1713 // as well as ensuring the transaction that houses the output is a ticket. 1714 // 1715 // Note that the returned error is not a RuleError, so the it is up to the 1716 // caller convert it accordingly. 1717 func checkTicketSubmissionInput(ticketUtxo *UtxoEntry) error { 1718 submissionScriptVer := ticketUtxo.ScriptVersionByIndex(submissionOutputIdx) 1719 if submissionScriptVer != 0 { 1720 return fmt.Errorf("script version %d is not supported", 1721 submissionScriptVer) 1722 } 1723 submissionScript := ticketUtxo.PkScriptByIndex(submissionOutputIdx) 1724 if !isStakeSubmission(submissionScript) { 1725 return fmt.Errorf("not a supported stake submission script (script: "+ 1726 "%x)", submissionScript) 1727 } 1728 1729 // Ensure the referenced output is from a ticket. This also proves the form 1730 // of the transaction and its outputs are as expected so subsequent code is 1731 // able to avoid a lot of additional overhead rechecking things. 1732 if ticketUtxo.TransactionType() != stake.TxTypeSStx { 1733 return fmt.Errorf("not a submission script") 1734 } 1735 1736 return nil 1737 } 1738 1739 // checkTicketRedeemerCommitments ensures the outputs of the provided 1740 // transaction, which MUST be either a vote or revocation, adhere to the 1741 // commitments in the provided ticket outputs. The vote subsidy MUST be zero 1742 // for revocations since they do not produce any additional subsidy. 1743 // 1744 // NOTE: This is only intended to be a helper to refactor out common code from 1745 // checkVoteInputs and checkRevocationInputs. 1746 func checkTicketRedeemerCommitments(ticketHash *chainhash.Hash, ticketOuts []*stake.MinimalOutput, msgTx *wire.MsgTx, isVote bool, voteSubsidy int64) error { 1747 // Make an initial pass over the ticket commitments to calculate the overall 1748 // contribution sum. This is necessary because the output amounts are 1749 // required to be scaled to maintain the same proportions as the original 1750 // contributions to the ticket, and the overall contribution sum is needed 1751 // to calculate those proportions. 1752 // 1753 // The calculations also require more than 64-bits, so convert it to a big 1754 // integer here to avoid multiple conversions later. 1755 var contributionSum int64 1756 for i := 1; i < len(ticketOuts); i += 2 { 1757 contributionSum += extractTicketCommitAmount(ticketOuts[i].PkScript) 1758 } 1759 contributionSumBig := big.NewInt(contributionSum) 1760 1761 // The outputs that satisify the commitments of the ticket start at offset 1762 // 2 for votes while they start at 0 for revocations. Also, the payments 1763 // must be tagged with the appropriate stake opcode depending on whether it 1764 // is a vote or a revocation. Finally, the fee limits in the original 1765 // ticket commitment differ for votes and revocations, so choose the correct 1766 // bit flag and mask accordingly. 1767 startIdx := 2 1768 reqStakeOpcode := byte(txscript.OP_SSGEN) 1769 hasFeeLimitFlag := uint16(stake.SStxVoteFractionFlag) 1770 feeLimitMask := uint16(stake.SStxVoteReturnFractionMask) 1771 if !isVote { 1772 startIdx = 0 1773 reqStakeOpcode = txscript.OP_SSRTX 1774 hasFeeLimitFlag = stake.SStxRevFractionFlag 1775 feeLimitMask = stake.SStxRevReturnFractionMask 1776 } 1777 ticketPaidAmt := ticketOuts[submissionOutputIdx].Value 1778 for txOutIdx := startIdx; txOutIdx < len(msgTx.TxOut); txOutIdx++ { 1779 // Ensure the output is paying to the address and type specified by the 1780 // original commitment in the ticket and is a version 0 script. 1781 // 1782 // Note that this specifically limits the types of allowed outputs to 1783 // P2PKH and P2SH, since the original commitment has the same 1784 // limitation. 1785 txOut := msgTx.TxOut[txOutIdx] 1786 if txOut.Version != 0 { 1787 str := fmt.Sprintf("output %s:%d script version %d is not "+ 1788 "supported", msgTx.TxHash(), txOutIdx, txOut.Version) 1789 return ruleError(ErrBadPayeeScriptVersion, str) 1790 } 1791 1792 commitmentOutIdx := (txOutIdx-startIdx)*2 + 1 1793 commitmentScript := ticketOuts[commitmentOutIdx].PkScript 1794 var paymentHash []byte 1795 if isTicketCommitP2SH(commitmentScript) { 1796 paymentHash = extractStakeScriptHash(txOut.PkScript, reqStakeOpcode) 1797 if paymentHash == nil { 1798 str := fmt.Sprintf("output %s:%d payment script type is not "+ 1799 "pay-to-script-hash as required by ticket output "+ 1800 "commitment %s:%d", msgTx.TxHash(), txOutIdx, ticketHash, 1801 commitmentOutIdx) 1802 return ruleError(ErrBadPayeeScriptType, str) 1803 } 1804 } else { 1805 paymentHash = extractStakePubKeyHash(txOut.PkScript, reqStakeOpcode) 1806 if paymentHash == nil { 1807 str := fmt.Sprintf("output %s:%d payment script type is not "+ 1808 "pay-to-pubkey-hash as required by ticket output "+ 1809 "commitment %s:%d", msgTx.TxHash(), txOutIdx, ticketHash, 1810 commitmentOutIdx) 1811 return ruleError(ErrBadPayeeScriptType, str) 1812 } 1813 } 1814 commitmentHash := extractTicketCommitHash(commitmentScript) 1815 if !bytes.Equal(paymentHash, commitmentHash) { 1816 str := fmt.Sprintf("output %s:%d does not pay to the hash "+ 1817 "specified by ticket output commitment %s:%d (ticket commits "+ 1818 "to %x, output pays %x)", msgTx.TxHash(), txOutIdx, ticketHash, 1819 commitmentOutIdx, commitmentHash, paymentHash) 1820 return ruleError(ErrMismatchedPayeeHash, str) 1821 } 1822 1823 // Calculate the required payment amount for the output based on the 1824 // relative percentage of the associated contribution to the original 1825 // ticket and any additional subsidy produced by the vote (must be 0 for 1826 // revocations). 1827 // 1828 // It should be noted that, due to the scaling, the sum of the generated 1829 // amounts for mult-participant votes might be a few atoms less than 1830 // the full amount and the difference is treated as a standard 1831 // transaction fee. 1832 commitmentAmt := extractTicketCommitAmount(commitmentScript) 1833 expectedOutAmt := calcTicketReturnAmount(commitmentAmt, ticketPaidAmt, 1834 voteSubsidy, contributionSumBig) 1835 1836 // Ensure the amount paid adheres to the commitment while taking into 1837 // account any fee limits that might be imposed. The output amount must 1838 // exactly match the calculated amount when when not encumbered with a 1839 // fee limit. On the other hand, when it is encumbered, it must be 1840 // between the minimum amount imposed by the fee limit and the 1841 // calculated amount. 1842 feeLimitsEncoded := extractTicketCommitFeeLimits(commitmentScript) 1843 hasFeeLimit := feeLimitsEncoded&hasFeeLimitFlag != 0 1844 if !hasFeeLimit { 1845 // The output amount must exactly match the calculated amount when 1846 // not encumbered with a fee limit. 1847 if txOut.Value != expectedOutAmt { 1848 str := fmt.Sprintf("output %s:%d does not pay the expected "+ 1849 "amount per ticket output commitment %s:%d (expected %d, "+ 1850 "output pays %d)", msgTx.TxHash(), txOutIdx, ticketHash, // PROBLEM: ticketHash... 1851 commitmentOutIdx, expectedOutAmt, txOut.Value) 1852 return ruleError(ErrBadPayeeValue, str) 1853 } 1854 } else { 1855 // Calculate the minimum allowed amount based on the fee limit. 1856 // 1857 // Notice that, since the fee limit is in terms of a log2 value, and 1858 // amounts are int64, anything greater than or equal to 63 is 1859 // interpreted to mean allow spending the entire amount as a fee. 1860 // This allows fast left shifts to be used to calculate the fee 1861 // limit while preventing degenerate cases such as negative numbers 1862 // for 63. 1863 var amtLimitLow int64 1864 feeLimitLog2 := feeLimitsEncoded & feeLimitMask 1865 if feeLimitLog2 < 63 { 1866 feeLimit := int64(1 << uint64(feeLimitLog2)) 1867 if feeLimit < expectedOutAmt { 1868 amtLimitLow = expectedOutAmt - feeLimit 1869 } 1870 } 1871 1872 // The output must not be less than the minimum amount. 1873 if txOut.Value < amtLimitLow { 1874 str := fmt.Sprintf("output %s:%d pays less than the expected "+ 1875 "expected amount per ticket output commitment %s:%d "+ 1876 "(lowest allowed %d, output pays %d)", msgTx.TxHash(), 1877 txOutIdx, ticketHash, commitmentOutIdx, amtLimitLow, // PROBLEM: ticketHash... 1878 txOut.Value) 1879 return ruleError(ErrBadPayeeValue, str) 1880 } 1881 1882 // The output must not be more than the expected amount. 1883 if txOut.Value > expectedOutAmt { 1884 str := fmt.Sprintf("output %s:%d pays more than the expected "+ 1885 "amount per ticket output commitment %s:%d (expected %d, "+ 1886 "output pays %d)", msgTx.TxHash(), txOutIdx, ticketHash, 1887 commitmentOutIdx, expectedOutAmt, txOut.Value) 1888 return ruleError(ErrBadPayeeValue, str) 1889 } 1890 } 1891 } 1892 1893 return nil 1894 } 1895 1896 // checkVoteInputs performs a series of checks on the inputs to a vote 1897 // transaction. An example of some of the checks include verifying the 1898 // referenced ticket exists, the stakebase input commits to correct subsidy, 1899 // the output amounts adhere to the commitments of the referenced ticket, and 1900 // the ticket maturity requirements are met. 1901 // 1902 // NOTE: The caller MUST have already determined that the provided transaction 1903 // is a vote. 1904 func checkVoteInputs(subsidyCache *standalone.SubsidyCache, tx *dcrutil.Tx, txHeight int64, view *UtxoViewpoint, params *chaincfg.Params) error { 1905 ticketMaturity := int64(params.TicketMaturity) 1906 voteHash := tx.Hash() 1907 msgTx := tx.MsgTx() 1908 1909 // Calculate the theoretical stake vote subsidy by extracting the vote 1910 // height. 1911 // 1912 // WARNING: This really should be calculating the subsidy based on the 1913 // height of the block the vote is contained in as opposed to the block it 1914 // is voting on. Unfortunately, this is now part of consensus, so changing 1915 // it requires a hard fork vote. 1916 _, heightVotingOn := stake.SSGenBlockVotedOn(msgTx) 1917 voteSubsidy := subsidyCache.CalcStakeVoteSubsidy(int64(heightVotingOn)) 1918 1919 // The input amount specified by the stakebase must commit to the subsidy 1920 // generated by the vote. 1921 stakebase := msgTx.TxIn[0] 1922 if stakebase.ValueIn != voteSubsidy { 1923 str := fmt.Sprintf("vote subsidy input value of %v is not %v", 1924 stakebase.ValueIn, voteSubsidy) 1925 return ruleError(ErrBadStakebaseAmountIn, str) 1926 } 1927 1928 // The second input to a vote must be the first output of the ticket the 1929 // vote is associated with. 1930 const ticketInIdx = 1 1931 ticketIn := msgTx.TxIn[ticketInIdx] 1932 if ticketIn.PreviousOutPoint.Index != submissionOutputIdx { 1933 str := fmt.Sprintf("vote %s:%d references output %d instead of the "+ 1934 "first output", voteHash, ticketInIdx, 1935 ticketIn.PreviousOutPoint.Index) 1936 return ruleError(ErrInvalidVoteInput, str) 1937 } 1938 1939 // Ensure the referenced ticket is available. 1940 ticketHash := &ticketIn.PreviousOutPoint.Hash 1941 ticketUtxo := view.LookupEntry(ticketHash) 1942 if ticketUtxo == nil || ticketUtxo.IsFullySpent() { 1943 str := fmt.Sprintf("ticket output %v referenced by vote %s:%d either "+ 1944 "does not exist or has already been spent", 1945 ticketIn.PreviousOutPoint, voteHash, ticketInIdx) 1946 return ruleError(ErrMissingTxOut, str) 1947 } 1948 1949 // Ensure the referenced transaction output is a supported ticket submission 1950 // output in terms of the script version and type as well as ensuring the 1951 // transaction that houses the output is a ticket. This also proves the 1952 // form of the transaction and its outputs are as expected so subsequent 1953 // code is able to avoid a lot of additional overhead rechecking things. 1954 if err := checkTicketSubmissionInput(ticketUtxo); err != nil { 1955 str := fmt.Sprintf("output %v referenced by vote %s:%d consensus "+ 1956 "violation: %s", ticketIn.PreviousOutPoint, voteHash, ticketInIdx, 1957 err.Error()) 1958 return ruleError(ErrInvalidVoteInput, str) 1959 } 1960 1961 // Ensure the vote is not spending a ticket which has not yet reached the 1962 // required ticket maturity. 1963 // 1964 // NOTE: A ticket stake submission (OP_SSTX tagged output) can only be spent 1965 // in the block AFTER the entire ticket maturity has passed, hence the +1. 1966 originHeight := ticketUtxo.BlockHeight() 1967 blocksSincePrev := txHeight - originHeight 1968 if blocksSincePrev < ticketMaturity+1 { 1969 str := fmt.Sprintf("tried to spend ticket output from transaction "+ 1970 "%v from height %d at height %d before required ticket maturity "+ 1971 "of %d+1 blocks", ticketHash, originHeight, txHeight, 1972 ticketMaturity) 1973 return ruleError(ErrImmatureTicketSpend, str) 1974 } 1975 1976 ticketOuts := ConvertUtxosToMinimalOutputs(ticketUtxo) 1977 if len(ticketOuts) == 0 { 1978 panicf("missing extra stake data for ticket %v -- probable database "+ 1979 "corruption", ticketHash) 1980 } 1981 1982 // Ensure the number of payment outputs matches the number of commitments 1983 // made by the associated ticket. 1984 // 1985 // The vote transaction outputs must consist of an OP_RETURN output that 1986 // indicates the block being voted on, an OP_RETURN with the user-provided 1987 // vote bits, and an output that corresponds to every commitment output in 1988 // the ticket associated with the vote. The associated ticket outputs 1989 // consist of a stake submission output, and two outputs for each payment 1990 // commitment such that the first one of the pair is a commitment amount and 1991 // the second one is the amount of change sent back to the contributor to 1992 // the ticket based on their original funding amount. 1993 numVotePayments := len(msgTx.TxOut) - 2 1994 if numVotePayments*2 != len(ticketOuts)-1 { 1995 str := fmt.Sprintf("vote %s makes %d payments when input ticket %s "+ 1996 "has %d commitments", voteHash, numVotePayments, ticketHash, 1997 len(ticketOuts)-1) 1998 return ruleError(ErrBadNumPayees, str) 1999 } 2000 2001 // Ensure the outputs adhere to the ticket commitments. 2002 return checkTicketRedeemerCommitments(ticketHash, ticketOuts, msgTx, true, 2003 voteSubsidy) 2004 } 2005 2006 // checkRevocationInputs performs a series of checks on the inputs to a 2007 // revocation transaction. An example of some of the checks include verifying 2008 // the referenced ticket exists, the output amounts adhere to the commitments of 2009 // the ticket, and the ticket maturity requirements are met. 2010 // 2011 // NOTE: The caller MUST have already determined that the provided transaction 2012 // is a revocation. 2013 func checkRevocationInputs(tx *dcrutil.Tx, txHeight int64, view *UtxoViewpoint, params *chaincfg.Params) error { 2014 ticketMaturity := int64(params.TicketMaturity) 2015 revokeHash := tx.Hash() 2016 msgTx := tx.MsgTx() 2017 2018 // The first input to a revocation must be the first output of the ticket 2019 // the revocation is associated with. 2020 const ticketInIdx = 0 2021 ticketIn := msgTx.TxIn[ticketInIdx] 2022 if ticketIn.PreviousOutPoint.Index != submissionOutputIdx { 2023 str := fmt.Sprintf("revocation %s:%d references output %d instead of "+ 2024 "the first output", revokeHash, ticketInIdx, 2025 ticketIn.PreviousOutPoint.Index) 2026 return ruleError(ErrInvalidRevokeInput, str) 2027 } 2028 2029 // Ensure the referenced ticket is available. 2030 ticketHash := &ticketIn.PreviousOutPoint.Hash 2031 ticketUtxo := view.LookupEntry(ticketHash) 2032 if ticketUtxo == nil || ticketUtxo.IsFullySpent() { 2033 str := fmt.Sprintf("ticket output %v referenced from revocation %s:%d "+ 2034 "either does not exist or has already been spent", 2035 ticketIn.PreviousOutPoint, revokeHash, ticketInIdx) 2036 return ruleError(ErrMissingTxOut, str) 2037 } 2038 2039 // Ensure the referenced transaction output is a supported ticket submission 2040 // output in terms of the script version and type as well as ensuring the 2041 // transaction that houses the output is a ticket. This also proves the 2042 // form of the transaction and its outputs are as expected so subsequent 2043 // code is able to avoid a lot of additional overhead rechecking things. 2044 if err := checkTicketSubmissionInput(ticketUtxo); err != nil { 2045 str := fmt.Sprintf("output %v referenced by revocation %s:%d consensus "+ 2046 "violation: %s", ticketIn.PreviousOutPoint, revokeHash, ticketInIdx, 2047 err.Error()) 2048 return ruleError(ErrInvalidRevokeInput, str) 2049 } 2050 2051 // Ensure the revocation is not spending a ticket which has not yet reached 2052 // the required ticket maturity. 2053 // 2054 // NOTE: A ticket stake submission (OP_SSTX tagged output) can only be spent 2055 // in the block AFTER the entire ticket maturity has passed, and, in order 2056 // to be revoked, the ticket must have been missed which can't possibly 2057 // happen for another block after that, hence the +2. 2058 originHeight := ticketUtxo.BlockHeight() 2059 blocksSincePrev := txHeight - originHeight 2060 if blocksSincePrev < ticketMaturity+2 { 2061 str := fmt.Sprintf("tried to spend ticket output from transaction "+ 2062 "%v from height %d at height %d before required ticket maturity "+ 2063 "of %d+2 blocks", ticketHash, originHeight, txHeight, 2064 ticketMaturity) 2065 return ruleError(ErrImmatureTicketSpend, str) 2066 } 2067 2068 ticketOuts := ConvertUtxosToMinimalOutputs(ticketUtxo) 2069 if len(ticketOuts) == 0 { 2070 panicf("missing extra stake data for ticket %v -- probable database "+ 2071 "corruption", ticketHash) 2072 } 2073 2074 // Ensure the number of payment outputs matches the number of commitments 2075 // made by the associated ticket. 2076 // 2077 // The revocation transaction outputs must consist of an output that 2078 // corresponds to every commitment output in the ticket associated with the 2079 // revocation. The associated ticket outputs consist of a stake submission 2080 // output, and two outputs for each payment commitment such that the first 2081 // one of the pair is a commitment amount and the second one is the amount 2082 // of change sent back to the contributor to the ticket based on their 2083 // original funding amount. 2084 numRevocationPayments := len(msgTx.TxOut) 2085 if numRevocationPayments*2 != len(ticketOuts)-1 { 2086 str := fmt.Sprintf("revocation %s makes %d payments when input ticket "+ 2087 "%s has %d commitments", revokeHash, numRevocationPayments, 2088 ticketHash, len(ticketOuts)-1) 2089 return ruleError(ErrBadNumPayees, str) 2090 } 2091 2092 // Ensure the outputs adhere to the ticket commitments. Zero is passed for 2093 // the vote subsidy since revocations do not produce any subsidy. 2094 return checkTicketRedeemerCommitments(ticketHash, ticketOuts, msgTx, false, 2095 0) 2096 } 2097 2098 // CheckTransactionInputs performs a series of checks on the inputs to a 2099 // transaction to ensure they are valid. An example of some of the checks 2100 // include verifying all inputs exist, ensuring the coinbase seasoning 2101 // requirements are met, detecting double spends, validating all values and 2102 // fees are in the legal range and the total output amount doesn't exceed the 2103 // input amount, and verifying the signatures to prove the spender was the 2104 // owner of the Decred and therefore allowed to spend them. As it checks the 2105 // inputs, it also calculates the total fees for the transaction and returns 2106 // that value. 2107 // 2108 // NOTE: The transaction MUST have already been sanity checked with the 2109 // CheckTransactionSanity function prior to calling this function. 2110 func CheckTransactionInputs(subsidyCache *standalone.SubsidyCache, tx *dcrutil.Tx, txHeight int64, view *UtxoViewpoint, checkFraudProof bool, chainParams *chaincfg.Params) (int64, error) { 2111 // Coinbase transactions have no inputs. 2112 msgTx := tx.MsgTx() 2113 if standalone.IsCoinBaseTx(msgTx) { 2114 return 0, nil 2115 } 2116 2117 // ------------------------------------------------------------------- 2118 // Decred stake transaction testing. 2119 // ------------------------------------------------------------------- 2120 2121 // Perform additional checks on ticket purchase transactions such as 2122 // ensuring the input type requirements are met and the output commitments 2123 // coincide with the inputs. 2124 isTicket := stake.IsSStx(msgTx) 2125 if isTicket { 2126 if err := checkTicketPurchaseInputs(msgTx, view); err != nil { 2127 return 0, err 2128 } 2129 } 2130 2131 // Perform additional checks on vote transactions such as verying that the 2132 // referenced ticket exists, the stakebase input commits to correct subsidy, 2133 // the output amounts adhere to the commitments of the referenced ticket, 2134 // and the ticket maturity requirements are met. 2135 // 2136 // Also keep track of whether or not it is a vote since some inputs need 2137 // to be skipped later. 2138 isVote := stake.IsSSGen(msgTx) 2139 if isVote { 2140 err := checkVoteInputs(subsidyCache, tx, txHeight, view, chainParams) 2141 if err != nil { 2142 return 0, err 2143 } 2144 } 2145 2146 // Perform additional checks on revocation transactions such as verifying 2147 // the referenced ticket exists, the output amounts adhere to the 2148 // commitments of the ticket, and the ticket maturity requirements are met. 2149 // 2150 // Also keep track of whether or not it is a revocation since some inputs 2151 // need to be skipped later. 2152 isRevocation := stake.IsSSRtx(msgTx) 2153 if isRevocation { 2154 err := checkRevocationInputs(tx, txHeight, view, chainParams) 2155 if err != nil { 2156 return 0, err 2157 } 2158 } 2159 2160 // ------------------------------------------------------------------- 2161 // Decred general transaction testing (and a few stake exceptions). 2162 // ------------------------------------------------------------------- 2163 2164 txHash := tx.Hash() 2165 var totalAtomIn int64 2166 for idx, txIn := range msgTx.TxIn { 2167 // Inputs won't exist for stakebase tx, so ignore them. 2168 if isVote && idx == 0 { 2169 // However, do add the reward amount. 2170 _, heightVotingOn := stake.SSGenBlockVotedOn(msgTx) 2171 stakeVoteSubsidy := subsidyCache.CalcStakeVoteSubsidy( 2172 int64(heightVotingOn)) 2173 totalAtomIn += stakeVoteSubsidy 2174 continue 2175 } 2176 2177 txInHash := &txIn.PreviousOutPoint.Hash 2178 originTxIndex := txIn.PreviousOutPoint.Index 2179 utxoEntry := view.LookupEntry(txInHash) 2180 if utxoEntry == nil || utxoEntry.IsOutputSpent(originTxIndex) { 2181 str := fmt.Sprintf("output %v referenced from "+ 2182 "transaction %s:%d either does not exist or "+ 2183 "has already been spent", txIn.PreviousOutPoint, 2184 txHash, idx) 2185 return 0, ruleError(ErrMissingTxOut, str) 2186 } 2187 2188 // Check fraud proof witness data. 2189 2190 // Using zero value outputs as inputs is banned. 2191 if utxoEntry.AmountByIndex(originTxIndex) == 0 { 2192 str := fmt.Sprintf("tried to spend zero value output "+ 2193 "from input %v, idx %v", txInHash, 2194 originTxIndex) 2195 return 0, ruleError(ErrZeroValueOutputSpend, str) 2196 } 2197 2198 if checkFraudProof { 2199 if txIn.ValueIn != 2200 utxoEntry.AmountByIndex(originTxIndex) { 2201 str := fmt.Sprintf("bad fraud check value in "+ 2202 "(expected %v, given %v) for txIn %v", 2203 utxoEntry.AmountByIndex(originTxIndex), 2204 txIn.ValueIn, idx) 2205 return 0, ruleError(ErrFraudAmountIn, str) 2206 } 2207 2208 if int64(txIn.BlockHeight) != utxoEntry.BlockHeight() { 2209 str := fmt.Sprintf("bad fraud check block "+ 2210 "height (expected %v, given %v) for "+ 2211 "txIn %v", utxoEntry.BlockHeight(), 2212 txIn.BlockHeight, idx) 2213 return 0, ruleError(ErrFraudBlockHeight, str) 2214 } 2215 2216 if txIn.BlockIndex != utxoEntry.BlockIndex() { 2217 str := fmt.Sprintf("bad fraud check block "+ 2218 "index (expected %v, given %v) for "+ 2219 "txIn %v", utxoEntry.BlockIndex(), 2220 txIn.BlockIndex, idx) 2221 return 0, ruleError(ErrFraudBlockIndex, str) 2222 } 2223 } 2224 2225 // Ensure the transaction is not spending coins which have not 2226 // yet reached the required coinbase maturity. 2227 coinbaseMaturity := int64(chainParams.CoinbaseMaturity) 2228 if utxoEntry.IsCoinBase() { 2229 originHeight := utxoEntry.BlockHeight() 2230 blocksSincePrev := txHeight - originHeight 2231 if blocksSincePrev < coinbaseMaturity { 2232 str := fmt.Sprintf("tx %v tried to spend "+ 2233 "coinbase transaction %v from height "+ 2234 "%v at height %v before required "+ 2235 "maturity of %v blocks", txHash, 2236 txInHash, originHeight, txHeight, 2237 coinbaseMaturity) 2238 return 0, ruleError(ErrImmatureSpend, str) 2239 } 2240 } 2241 2242 // Ensure that the transaction is not spending coins from a 2243 // transaction that included an expiry but which has not yet 2244 // reached coinbase maturity many blocks. 2245 if utxoEntry.HasExpiry() { 2246 originHeight := utxoEntry.BlockHeight() 2247 blocksSincePrev := txHeight - originHeight 2248 if blocksSincePrev < coinbaseMaturity { 2249 str := fmt.Sprintf("tx %v tried to spend "+ 2250 "transaction %v including an expiry "+ 2251 "from height %v at height %v before "+ 2252 "required maturity of %v blocks", 2253 txHash, txInHash, originHeight, 2254 txHeight, coinbaseMaturity) 2255 return 0, ruleError(ErrExpiryTxSpentEarly, str) 2256 } 2257 } 2258 2259 // Ensure that the outpoint's tx tree makes sense. 2260 originTxOPTree := txIn.PreviousOutPoint.Tree 2261 originTxType := utxoEntry.TransactionType() 2262 indicatedTree := wire.TxTreeRegular 2263 if originTxType != stake.TxTypeRegular { 2264 indicatedTree = wire.TxTreeStake 2265 } 2266 if indicatedTree != originTxOPTree { 2267 errStr := fmt.Sprintf("tx %v attempted to spend from "+ 2268 "a %v tx tree (hash %v), yet the outpoint "+ 2269 "specified a %v tx tree instead", txHash, 2270 indicatedTree, txIn.PreviousOutPoint.Hash, 2271 originTxOPTree) 2272 return 0, ruleError(ErrDiscordantTxTree, errStr) 2273 } 2274 2275 // The only transaction types that are allowed to spend from OP_SSTX 2276 // tagged outputs are votes and revocations. So, check all the inputs 2277 // from non votes and revocations and make sure that they spend no 2278 // OP_SSTX tagged outputs. 2279 if !(isVote || isRevocation) { 2280 if txscript.GetScriptClass( 2281 utxoEntry.ScriptVersionByIndex(originTxIndex), 2282 utxoEntry.PkScriptByIndex(originTxIndex)) == 2283 txscript.StakeSubmissionTy { 2284 2285 errSSGen := stake.CheckSSGen(msgTx) 2286 errSSRtx := stake.CheckSSRtx(msgTx) 2287 errStr := fmt.Sprintf("Tx %v attempted to "+ 2288 "spend an OP_SSTX tagged output, "+ 2289 "however it was not an SSGen or SSRtx"+ 2290 " tx; SSGen err: %v, SSRtx err: %v", 2291 txHash, errSSGen.Error(), 2292 errSSRtx.Error()) 2293 return 0, ruleError(ErrTxSStxOutSpend, errStr) 2294 } 2295 } 2296 2297 // OP_SSGEN and OP_SSRTX tagged outputs can only be spent after 2298 // coinbase maturity many blocks. 2299 scriptClass := txscript.GetScriptClass( 2300 utxoEntry.ScriptVersionByIndex(originTxIndex), 2301 utxoEntry.PkScriptByIndex(originTxIndex)) 2302 if scriptClass == txscript.StakeGenTy || 2303 scriptClass == txscript.StakeRevocationTy { 2304 originHeight := utxoEntry.BlockHeight() 2305 blocksSincePrev := txHeight - originHeight 2306 if blocksSincePrev < 2307 int64(chainParams.SStxChangeMaturity) { 2308 str := fmt.Sprintf("tried to spend OP_SSGEN or"+ 2309 " OP_SSRTX output from tx %v from "+ 2310 "height %v at height %v before "+ 2311 "required maturity of %v blocks", 2312 txInHash, originHeight, txHeight, 2313 coinbaseMaturity) 2314 return 0, ruleError(ErrImmatureSpend, str) 2315 } 2316 } 2317 2318 // Ticket change outputs may only be spent after ticket change 2319 // maturity many blocks. 2320 if scriptClass == txscript.StakeSubChangeTy { 2321 originHeight := utxoEntry.BlockHeight() 2322 blocksSincePrev := txHeight - originHeight 2323 if blocksSincePrev < 2324 int64(chainParams.SStxChangeMaturity) { 2325 str := fmt.Sprintf("tried to spend ticket change"+ 2326 " output from tx %v from height %v at "+ 2327 "height %v before required maturity "+ 2328 "of %v blocks", txInHash, originHeight, 2329 txHeight, chainParams.SStxChangeMaturity) 2330 return 0, ruleError(ErrImmatureSpend, str) 2331 } 2332 } 2333 2334 // Ensure the transaction amounts are in range. Each of the 2335 // output values of the input transactions must not be negative 2336 // or more than the max allowed per transaction. All amounts 2337 // in a transaction are in a unit value known as an atom. One 2338 // Decred is a quantity of atoms as defined by the AtomPerCoin 2339 // constant. 2340 originTxAtom := utxoEntry.AmountByIndex(originTxIndex) 2341 if originTxAtom < 0 { 2342 str := fmt.Sprintf("transaction output has negative "+ 2343 "value of %v", originTxAtom) 2344 return 0, ruleError(ErrBadTxOutValue, str) 2345 } 2346 if originTxAtom > dcrutil.MaxAmount { 2347 str := fmt.Sprintf("transaction output value of %v is "+ 2348 "higher than max allowed value of %v", 2349 originTxAtom, dcrutil.MaxAmount) 2350 return 0, ruleError(ErrBadTxOutValue, str) 2351 } 2352 2353 // The total of all outputs must not be more than the max 2354 // allowed per transaction. Also, we could potentially 2355 // overflow the accumulator so check for overflow. 2356 lastAtomIn := totalAtomIn 2357 totalAtomIn += originTxAtom 2358 if totalAtomIn < lastAtomIn || 2359 totalAtomIn > dcrutil.MaxAmount { 2360 str := fmt.Sprintf("total value of all transaction "+ 2361 "inputs is %v which is higher than max "+ 2362 "allowed value of %v", totalAtomIn, 2363 dcrutil.MaxAmount) 2364 return 0, ruleError(ErrBadTxOutValue, str) 2365 } 2366 } 2367 2368 // Calculate the total output amount for this transaction. It is safe 2369 // to ignore overflow and out of range errors here because those error 2370 // conditions would have already been caught by checkTransactionSanity. 2371 var totalAtomOut int64 2372 for _, txOut := range tx.MsgTx().TxOut { 2373 totalAtomOut += txOut.Value 2374 } 2375 2376 // Ensure the transaction does not spend more than its inputs. 2377 if totalAtomIn < totalAtomOut { 2378 str := fmt.Sprintf("total value of all transaction inputs for "+ 2379 "transaction %v is %v which is less than the amount "+ 2380 "spent of %v", txHash, totalAtomIn, totalAtomOut) 2381 return 0, ruleError(ErrSpendTooHigh, str) 2382 } 2383 2384 txFeeInAtom := totalAtomIn - totalAtomOut 2385 return txFeeInAtom, nil 2386 } 2387 2388 // CountSigOps returns the number of signature operations for all transaction 2389 // input and output scripts in the provided transaction. This uses the 2390 // quicker, but imprecise, signature operation counting mechanism from 2391 // txscript. 2392 func CountSigOps(tx *dcrutil.Tx, isCoinBaseTx bool, isSSGen bool) int { 2393 msgTx := tx.MsgTx() 2394 2395 // Accumulate the number of signature operations in all transaction 2396 // inputs. 2397 totalSigOps := 0 2398 for i, txIn := range msgTx.TxIn { 2399 // Skip coinbase inputs. 2400 if isCoinBaseTx { 2401 continue 2402 } 2403 // Skip stakebase inputs. 2404 if isSSGen && i == 0 { 2405 continue 2406 } 2407 2408 numSigOps := txscript.GetSigOpCount(txIn.SignatureScript) 2409 totalSigOps += numSigOps 2410 } 2411 2412 // Accumulate the number of signature operations in all transaction 2413 // outputs. 2414 for _, txOut := range msgTx.TxOut { 2415 numSigOps := txscript.GetSigOpCount(txOut.PkScript) 2416 totalSigOps += numSigOps 2417 } 2418 2419 return totalSigOps 2420 } 2421 2422 // CountP2SHSigOps returns the number of signature operations for all input 2423 // transactions which are of the pay-to-script-hash type. This uses the 2424 // precise, signature operation counting mechanism from the script engine which 2425 // requires access to the input transaction scripts. 2426 func CountP2SHSigOps(tx *dcrutil.Tx, isCoinBaseTx bool, isStakeBaseTx bool, view *UtxoViewpoint) (int, error) { 2427 // Coinbase transactions have no interesting inputs. 2428 if isCoinBaseTx { 2429 return 0, nil 2430 } 2431 2432 // Stakebase (SSGen) transactions have no P2SH inputs. Same with SSRtx, 2433 // but they will still pass the checks below. 2434 if isStakeBaseTx { 2435 return 0, nil 2436 } 2437 2438 // Accumulate the number of signature operations in all transaction 2439 // inputs. 2440 msgTx := tx.MsgTx() 2441 totalSigOps := 0 2442 for txInIndex, txIn := range msgTx.TxIn { 2443 // Ensure the referenced input transaction is available. 2444 originTxHash := &txIn.PreviousOutPoint.Hash 2445 originTxIndex := txIn.PreviousOutPoint.Index 2446 utxoEntry := view.LookupEntry(originTxHash) 2447 if utxoEntry == nil || utxoEntry.IsOutputSpent(originTxIndex) { 2448 str := fmt.Sprintf("output %v referenced from "+ 2449 "transaction %s:%d either does not exist or "+ 2450 "has already been spent", txIn.PreviousOutPoint, 2451 tx.Hash(), txInIndex) 2452 return 0, ruleError(ErrMissingTxOut, str) 2453 } 2454 2455 // We're only interested in pay-to-script-hash types, so skip 2456 // this input if it's not one. 2457 pkScript := utxoEntry.PkScriptByIndex(originTxIndex) 2458 if !txscript.IsPayToScriptHash(pkScript) { 2459 continue 2460 } 2461 2462 // Count the precise number of signature operations in the 2463 // referenced public key script. 2464 sigScript := txIn.SignatureScript 2465 numSigOps := txscript.GetPreciseSigOpCount(sigScript, pkScript, 2466 true) 2467 2468 // We could potentially overflow the accumulator so check for 2469 // overflow. 2470 lastSigOps := totalSigOps 2471 totalSigOps += numSigOps 2472 if totalSigOps < lastSigOps { 2473 str := fmt.Sprintf("the public key script from output "+ 2474 "%v contains too many signature operations - "+ 2475 "overflow", txIn.PreviousOutPoint) 2476 return 0, ruleError(ErrTooManySigOps, str) 2477 } 2478 } 2479 2480 return totalSigOps, nil 2481 } 2482 2483 // createLegacySeqLockView returns a view to use when calculating sequence locks 2484 // for the transactions in the regular tree that preserves the same incorrect 2485 // semantics that were present in previous versions of the software. 2486 func (b *BlockChain) createLegacySeqLockView(block, parent *dcrutil.Block, view *UtxoViewpoint) (*UtxoViewpoint, error) { 2487 // Clone the real view to avoid mutating it. 2488 seqLockView := view.clone() 2489 2490 // Ensure all of the inputs referenced by the transactions in the regular 2491 // tree of the parent block and the parent block outputs are available in 2492 // the legacy view so long as it has not been disapproved. 2493 if headerApprovesParent(&block.MsgBlock().Header) { 2494 err := seqLockView.fetchRegularInputUtxos(b.db, parent) 2495 if err != nil { 2496 return nil, err 2497 } 2498 2499 for txInIdx, tx := range parent.Transactions() { 2500 seqLockView.AddTxOuts(tx, parent.Height(), uint32(txInIdx)) 2501 } 2502 } 2503 2504 // Ensure all of the inputs referenced by the transactions in the stake tree 2505 // of the current block are available in the legacy view. 2506 filteredSet := make(viewFilteredSet) 2507 for _, stx := range block.STransactions() { 2508 isVote := stake.IsSSGen(stx.MsgTx()) 2509 for txInIdx, txIn := range stx.MsgTx().TxIn { 2510 // Ignore stakebase since it has no input. 2511 if txInIdx == 0 && isVote { 2512 continue 2513 } 2514 2515 // Only request entries that are not already in the view from the 2516 // database. 2517 originHash := &txIn.PreviousOutPoint.Hash 2518 filteredSet.add(seqLockView, originHash) 2519 } 2520 } 2521 err := seqLockView.fetchUtxosMain(b.db, filteredSet) 2522 if err != nil { 2523 return nil, err 2524 } 2525 2526 // Connect all of the transactions in the stake tree of the current block. 2527 for txIdx, stx := range block.STransactions() { 2528 err := seqLockView.connectTransaction(stx, block.Height(), 2529 uint32(txIdx), nil) 2530 if err != nil { 2531 return nil, err 2532 } 2533 } 2534 2535 return seqLockView, nil 2536 } 2537 2538 // checkNumSigOps Checks the number of P2SH signature operations to make 2539 // sure they don't overflow the limits. It takes a cumulative number of sig 2540 // ops as an argument and increments will each call. 2541 // TxTree true == Regular, false == Stake 2542 func checkNumSigOps(tx *dcrutil.Tx, view *UtxoViewpoint, index int, txTree bool, cumulativeSigOps int) (int, error) { 2543 msgTx := tx.MsgTx() 2544 isSSGen := stake.IsSSGen(msgTx) 2545 numsigOps := CountSigOps(tx, (index == 0) && txTree, isSSGen) 2546 2547 // Since the first (and only the first) transaction has already been 2548 // verified to be a coinbase transaction, use (i == 0) && TxTree as an 2549 // optimization for the flag to countP2SHSigOps for whether or not the 2550 // transaction is a coinbase transaction rather than having to do a 2551 // full coinbase check again. 2552 numP2SHSigOps, err := CountP2SHSigOps(tx, (index == 0) && txTree, 2553 isSSGen, view) 2554 if err != nil { 2555 log.Tracef("CountP2SHSigOps failed; error returned %v", err) 2556 return 0, err 2557 } 2558 2559 startCumSigOps := cumulativeSigOps 2560 cumulativeSigOps += numsigOps 2561 cumulativeSigOps += numP2SHSigOps 2562 2563 // Check for overflow or going over the limits. We have to do 2564 // this on every loop iteration to avoid overflow. 2565 if cumulativeSigOps < startCumSigOps || 2566 cumulativeSigOps > MaxSigOpsPerBlock { 2567 str := fmt.Sprintf("block contains too many signature "+ 2568 "operations - got %v, max %v", cumulativeSigOps, 2569 MaxSigOpsPerBlock) 2570 return 0, ruleError(ErrTooManySigOps, str) 2571 } 2572 2573 return cumulativeSigOps, nil 2574 } 2575 2576 // checkStakeBaseAmounts calculates the total amount given as subsidy from 2577 // single stakebase transactions (votes) within a block. This function skips a 2578 // ton of checks already performed by CheckTransactionInputs. 2579 func checkStakeBaseAmounts(subsidyCache *standalone.SubsidyCache, height int64, params *chaincfg.Params, txs []*dcrutil.Tx, view *UtxoViewpoint) error { 2580 for _, tx := range txs { 2581 msgTx := tx.MsgTx() 2582 if stake.IsSSGen(msgTx) { 2583 // Ensure the input is available. 2584 txInHash := &msgTx.TxIn[1].PreviousOutPoint.Hash 2585 utxoEntry, exists := view.entries[*txInHash] 2586 if !exists || utxoEntry == nil { 2587 str := fmt.Sprintf("couldn't find input tx %v "+ 2588 "for stakebase amounts check", txInHash) 2589 return ruleError(ErrTicketUnavailable, str) 2590 } 2591 2592 originTxIndex := msgTx.TxIn[1].PreviousOutPoint.Index 2593 originTxAtom := utxoEntry.AmountByIndex(originTxIndex) 2594 2595 totalOutputs := int64(0) 2596 // Sum up the outputs. 2597 for _, out := range msgTx.TxOut { 2598 totalOutputs += out.Value 2599 } 2600 2601 difference := totalOutputs - originTxAtom 2602 2603 // Subsidy aligns with the height we're voting on, not 2604 // with the height of the current block. 2605 calcSubsidy := subsidyCache.CalcStakeVoteSubsidy(height - 1) 2606 2607 if difference > calcSubsidy { 2608 str := fmt.Sprintf("ssgen tx %v spent more "+ 2609 "than allowed (spent %v, allowed %v)", 2610 tx.Hash(), difference, calcSubsidy) 2611 return ruleError(ErrSSGenSubsidy, str) 2612 } 2613 } 2614 } 2615 2616 return nil 2617 } 2618 2619 // getStakeBaseAmounts calculates the total amount given as subsidy from the 2620 // collective stakebase transactions (votes) within a block. This function 2621 // skips a ton of checks already performed by CheckTransactionInputs. 2622 func getStakeBaseAmounts(txs []*dcrutil.Tx, view *UtxoViewpoint) (int64, error) { 2623 totalInputs := int64(0) 2624 totalOutputs := int64(0) 2625 for _, tx := range txs { 2626 msgTx := tx.MsgTx() 2627 if stake.IsSSGen(msgTx) { 2628 // Ensure the input is available. 2629 txInHash := &msgTx.TxIn[1].PreviousOutPoint.Hash 2630 utxoEntry, exists := view.entries[*txInHash] 2631 if !exists || utxoEntry == nil { 2632 str := fmt.Sprintf("couldn't find input tx %v "+ 2633 "for stakebase amounts get", txInHash) 2634 return 0, ruleError(ErrTicketUnavailable, str) 2635 } 2636 2637 originTxIndex := msgTx.TxIn[1].PreviousOutPoint.Index 2638 originTxAtom := utxoEntry.AmountByIndex(originTxIndex) 2639 2640 totalInputs += originTxAtom 2641 2642 // Sum up the outputs. 2643 for _, out := range msgTx.TxOut { 2644 totalOutputs += out.Value 2645 } 2646 } 2647 } 2648 2649 return totalOutputs - totalInputs, nil 2650 } 2651 2652 // getStakeTreeFees determines the amount of fees for in the stake tx tree of 2653 // some node given a transaction store. 2654 func getStakeTreeFees(subsidyCache *standalone.SubsidyCache, height int64, params *chaincfg.Params, txs []*dcrutil.Tx, view *UtxoViewpoint) (dcrutil.Amount, error) { 2655 totalInputs := int64(0) 2656 totalOutputs := int64(0) 2657 for _, tx := range txs { 2658 msgTx := tx.MsgTx() 2659 isSSGen := stake.IsSSGen(msgTx) 2660 2661 for i, in := range msgTx.TxIn { 2662 // Ignore stakebases. 2663 if isSSGen && i == 0 { 2664 continue 2665 } 2666 2667 txInHash := &in.PreviousOutPoint.Hash 2668 utxoEntry, exists := view.entries[*txInHash] 2669 if !exists || utxoEntry == nil { 2670 str := fmt.Sprintf("couldn't find input tx "+ 2671 "%v for stake tree fee calculation", 2672 txInHash) 2673 return 0, ruleError(ErrTicketUnavailable, str) 2674 } 2675 2676 originTxIndex := in.PreviousOutPoint.Index 2677 originTxAtom := utxoEntry.AmountByIndex(originTxIndex) 2678 2679 totalInputs += originTxAtom 2680 } 2681 2682 for _, out := range msgTx.TxOut { 2683 totalOutputs += out.Value 2684 } 2685 2686 // For votes, subtract the subsidy to determine actual fees. 2687 if isSSGen { 2688 // Subsidy aligns with the height we're voting on, not 2689 // with the height of the current block. 2690 totalOutputs -= subsidyCache.CalcStakeVoteSubsidy(height - 1) 2691 } 2692 } 2693 2694 if totalInputs < totalOutputs { 2695 str := fmt.Sprintf("negative cumulative fees found in stake " + 2696 "tx tree") 2697 return 0, ruleError(ErrStakeFees, str) 2698 } 2699 2700 return dcrutil.Amount(totalInputs - totalOutputs), nil 2701 } 2702 2703 // checkTransactionsAndConnect is the local function used to check the 2704 // transaction inputs for a transaction list given a predetermined TxStore. 2705 // After ensuring the transaction is valid, the transaction is connected to the 2706 // UTXO viewpoint. TxTree true == Regular, false == Stake 2707 func (b *BlockChain) checkTransactionsAndConnect(inputFees dcrutil.Amount, node *blockNode, txs []*dcrutil.Tx, view *UtxoViewpoint, stxos *[]spentTxOut, txTree bool) error { 2708 // Perform several checks on the inputs for each transaction. Also 2709 // accumulate the total fees. This could technically be combined with 2710 // the loop above instead of running another loop over the 2711 // transactions, but by separating it we can avoid running the more 2712 // expensive (though still relatively cheap as compared to running the 2713 // scripts) checks against all the inputs when the signature operations 2714 // are out of bounds. 2715 totalFees := int64(inputFees) // Stake tx tree carry forward 2716 var cumulativeSigOps int 2717 for idx, tx := range txs { 2718 // Ensure that the number of signature operations is not beyond 2719 // the consensus limit. 2720 var err error 2721 cumulativeSigOps, err = checkNumSigOps(tx, view, idx, txTree, 2722 cumulativeSigOps) 2723 if err != nil { 2724 return err 2725 } 2726 2727 // This step modifies the txStore and marks the tx outs used 2728 // spent, so be aware of this. 2729 txFee, err := CheckTransactionInputs(b.subsidyCache, tx, 2730 node.height, view, true, /* check fraud proofs */ 2731 b.chainParams) 2732 if err != nil { 2733 log.Tracef("CheckTransactionInputs failed; error "+ 2734 "returned: %v", err) 2735 return err 2736 } 2737 2738 // Sum the total fees and ensure we don't overflow the 2739 // accumulator. 2740 lastTotalFees := totalFees 2741 totalFees += txFee 2742 if totalFees < lastTotalFees { 2743 return ruleError(ErrBadFees, "total fees for block "+ 2744 "overflows accumulator") 2745 } 2746 2747 // Connect the transaction to the UTXO viewpoint, so that in 2748 // flight transactions may correctly validate. 2749 err = view.connectTransaction(tx, node.height, uint32(idx), 2750 stxos) 2751 if err != nil { 2752 return err 2753 } 2754 } 2755 2756 // The total output values of the coinbase transaction must not exceed 2757 // the expected subsidy value plus total transaction fees gained from 2758 // mining the block. It is safe to ignore overflow and out of range 2759 // errors here because those error conditions would have already been 2760 // caught by checkTransactionSanity. 2761 if txTree { //TxTreeRegular 2762 // Apply penalty to fees if we're at stake validation height. 2763 if node.height >= b.chainParams.StakeValidationHeight { 2764 totalFees *= int64(node.voters) 2765 totalFees /= int64(b.chainParams.TicketsPerBlock) 2766 } 2767 2768 var totalAtomOutRegular int64 2769 2770 for _, txOut := range txs[0].MsgTx().TxOut { 2771 totalAtomOutRegular += txOut.Value 2772 } 2773 2774 var expAtomOut int64 2775 if node.height == 1 { 2776 expAtomOut = b.subsidyCache.CalcBlockSubsidy(node.height) 2777 } else { 2778 subsidyWork := b.subsidyCache.CalcWorkSubsidy(node.height, 2779 node.voters) 2780 subsidyTax := b.subsidyCache.CalcTreasurySubsidy(node.height, 2781 node.voters) 2782 expAtomOut = subsidyWork + subsidyTax + totalFees 2783 } 2784 2785 // AmountIn for the input should be equal to the subsidy. 2786 coinbaseIn := txs[0].MsgTx().TxIn[0] 2787 subsidyWithoutFees := expAtomOut - totalFees 2788 if (coinbaseIn.ValueIn != subsidyWithoutFees) && 2789 (node.height > 0) { 2790 errStr := fmt.Sprintf("bad coinbase subsidy in input;"+ 2791 " got %v, expected %v", coinbaseIn.ValueIn, 2792 subsidyWithoutFees) 2793 return ruleError(ErrBadCoinbaseAmountIn, errStr) 2794 } 2795 2796 if totalAtomOutRegular > expAtomOut { 2797 str := fmt.Sprintf("coinbase transaction for block %v"+ 2798 " pays %v which is more than expected value "+ 2799 "of %v", node.hash, totalAtomOutRegular, 2800 expAtomOut) 2801 return ruleError(ErrBadCoinbaseValue, str) 2802 } 2803 } else { // TxTreeStake 2804 if len(txs) == 0 && 2805 node.height < b.chainParams.StakeValidationHeight { 2806 return nil 2807 } 2808 if len(txs) == 0 && 2809 node.height >= b.chainParams.StakeValidationHeight { 2810 str := fmt.Sprintf("empty tx tree stake in block " + 2811 "after stake validation height") 2812 return ruleError(ErrNoStakeTx, str) 2813 } 2814 2815 err := checkStakeBaseAmounts(b.subsidyCache, node.height, 2816 b.chainParams, txs, view) 2817 if err != nil { 2818 return err 2819 } 2820 2821 totalAtomOutStake, err := getStakeBaseAmounts(txs, view) 2822 if err != nil { 2823 return err 2824 } 2825 2826 var expAtomOut int64 2827 if node.height >= b.chainParams.StakeValidationHeight { 2828 // Subsidy aligns with the height we're voting on, not 2829 // with the height of the current block. 2830 expAtomOut = b.subsidyCache.CalcStakeVoteSubsidy(node.height-1) * 2831 int64(node.voters) 2832 } else { 2833 expAtomOut = totalFees 2834 } 2835 2836 if totalAtomOutStake > expAtomOut { 2837 str := fmt.Sprintf("stakebase transactions for block "+ 2838 "pays %v which is more than expected value "+ 2839 "of %v", totalAtomOutStake, expAtomOut) 2840 return ruleError(ErrBadStakebaseValue, str) 2841 } 2842 } 2843 2844 return nil 2845 } 2846 2847 // consensusScriptVerifyFlags returns the script flags that must be used when 2848 // executing transaction scripts to enforce the consensus rules. This includes 2849 // any flags required as the result of any agendas that have passed and become 2850 // active. 2851 func (b *BlockChain) consensusScriptVerifyFlags(node *blockNode) (txscript.ScriptFlags, error) { 2852 scriptFlags := txscript.ScriptVerifyCleanStack | 2853 txscript.ScriptVerifyCheckLockTimeVerify 2854 2855 // Enable enforcement of OP_CSV and OP_SHA256 if the stake vote 2856 // for the agenda is active. 2857 lnFeaturesActive, err := b.isLNFeaturesAgendaActive(node.parent) 2858 if err != nil { 2859 return 0, err 2860 } 2861 if lnFeaturesActive { 2862 scriptFlags |= txscript.ScriptVerifyCheckSequenceVerify 2863 scriptFlags |= txscript.ScriptVerifySHA256 2864 } 2865 return scriptFlags, err 2866 } 2867 2868 // checkConnectBlock performs several checks to confirm connecting the passed 2869 // block to the chain represented by the passed view does not violate any 2870 // rules. In addition, the passed view is updated to spend all of the 2871 // referenced outputs and add all of the new utxos created by block. Thus, the 2872 // view will represent the state of the chain as if the block were actually 2873 // connected and consequently the best hash for the view is also updated to 2874 // passed block. 2875 // 2876 // An example of some of the checks performed are ensuring connecting the block 2877 // would not cause any duplicate transaction hashes for old transactions that 2878 // aren't already fully spent, double spends, exceeding the maximum allowed 2879 // signature operations per block, invalid values in relation to the expected 2880 // block subsidy, or fail transaction script validation. 2881 // 2882 // The CheckConnectBlockTemplate function makes use of this function to perform 2883 // the bulk of its work. 2884 // 2885 // This function MUST be called with the chain state lock held (for writes). 2886 func (b *BlockChain) checkConnectBlock(node *blockNode, block, parent *dcrutil.Block, view *UtxoViewpoint, stxos *[]spentTxOut) error { 2887 // If the side chain blocks end up in the database, a call to 2888 // CheckBlockSanity should be done here in case a previous version 2889 // allowed a block that is no longer valid. However, since the 2890 // implementation only currently uses memory for the side chain blocks, 2891 // it isn't currently necessary. 2892 2893 // Ensure the view is for the node being checked. 2894 parentHash := &block.MsgBlock().Header.PrevBlock 2895 if !view.BestHash().IsEqual(parentHash) { 2896 return AssertError(fmt.Sprintf("inconsistent view when "+ 2897 "checking block connection: best hash is %v instead "+ 2898 "of expected %v", view.BestHash(), parentHash)) 2899 } 2900 2901 // Check that the coinbase pays the treasury, if applicable. 2902 err := coinbasePaysTreasury(b.subsidyCache, block.Transactions()[0], 2903 node.height, node.voters, b.chainParams) 2904 if err != nil { 2905 return err 2906 } 2907 2908 // Don't run scripts if this node is before the latest known good 2909 // checkpoint since the validity is verified via the checkpoints (all 2910 // transactions are included in the merkle root hash and any changes 2911 // will therefore be detected by the next checkpoint). This is a huge 2912 // optimization because running the scripts is the most time consuming 2913 // portion of block handling. 2914 checkpoint := b.latestCheckpoint() 2915 runScripts := !b.noVerify 2916 if checkpoint != nil && node.height <= checkpoint.Height { 2917 runScripts = false 2918 } 2919 var scriptFlags txscript.ScriptFlags 2920 if runScripts { 2921 var err error 2922 scriptFlags, err = b.consensusScriptVerifyFlags(node) 2923 if err != nil { 2924 return err 2925 } 2926 } 2927 2928 // Create a view which preserves the expected consensus semantics for 2929 // relative lock times via sequence numbers once the stake vote for the 2930 // agenda is active. 2931 legacySeqLockView := view 2932 lnFeaturesActive, err := b.isLNFeaturesAgendaActive(node.parent) 2933 if err != nil { 2934 return err 2935 } 2936 fixSeqLocksActive, err := b.isFixSeqLocksAgendaActive(node.parent) 2937 if err != nil { 2938 return err 2939 } 2940 if lnFeaturesActive && !fixSeqLocksActive { 2941 var err error 2942 legacySeqLockView, err = b.createLegacySeqLockView(block, parent, 2943 view) 2944 if err != nil { 2945 return err 2946 } 2947 } 2948 2949 // Disconnect all of the transactions in the regular transaction tree of 2950 // the parent if the block being checked votes against it. 2951 if node.height > 1 && !voteBitsApproveParent(node.voteBits) { 2952 err := view.disconnectDisapprovedBlock(b.db, parent) 2953 if err != nil { 2954 return err 2955 } 2956 } 2957 2958 // Ensure the stake transaction tree does not contain any transactions 2959 // that 'overwrite' older transactions which are not fully spent. 2960 err = b.checkDupTxs(block.STransactions(), view) 2961 if err != nil { 2962 log.Tracef("checkDupTxs failed for cur TxTreeStake: %v", err) 2963 return err 2964 } 2965 2966 // Load all of the utxos referenced by the inputs for all transactions 2967 // in the block don't already exist in the utxo view from the database. 2968 // 2969 // These utxo entries are needed for verification of things such as 2970 // transaction inputs, counting pay-to-script-hashes, and scripts. 2971 err = view.fetchInputUtxos(b.db, block) 2972 if err != nil { 2973 return err 2974 } 2975 2976 err = b.checkTransactionsAndConnect(0, node, block.STransactions(), 2977 view, stxos, false) 2978 if err != nil { 2979 log.Tracef("checkTransactionsAndConnect failed for "+ 2980 "TxTreeStake: %v", err) 2981 return err 2982 } 2983 2984 stakeTreeFees, err := getStakeTreeFees(b.subsidyCache, node.height, 2985 b.chainParams, block.STransactions(), view) 2986 if err != nil { 2987 log.Tracef("getStakeTreeFees failed for TxTreeStake: %v", err) 2988 return err 2989 } 2990 2991 // Enforce all relative lock times via sequence numbers for the stake 2992 // transaction tree once the stake vote for the agenda is active. 2993 var prevMedianTime time.Time 2994 if lnFeaturesActive { 2995 // Use the past median time of the *previous* block in order 2996 // to determine if the transactions in the current block are 2997 // final. 2998 prevMedianTime = node.parent.CalcPastMedianTime() 2999 3000 for _, stx := range block.STransactions() { 3001 sequenceLock, err := b.calcSequenceLock(node, stx, 3002 view, true) 3003 if err != nil { 3004 return err 3005 } 3006 if !SequenceLockActive(sequenceLock, node.height, 3007 prevMedianTime) { 3008 3009 str := fmt.Sprintf("block contains " + 3010 "stake transaction whose input " + 3011 "sequence locks are not met") 3012 return ruleError(ErrUnfinalizedTx, str) 3013 } 3014 } 3015 } 3016 3017 if runScripts { 3018 err = checkBlockScripts(block, view, false, scriptFlags, 3019 b.sigCache) 3020 if err != nil { 3021 log.Tracef("checkBlockScripts failed; error returned "+ 3022 "on txtreestake of cur block: %v", err) 3023 return err 3024 } 3025 } 3026 3027 // Ensure the regular transaction tree does not contain any transactions 3028 // that 'overwrite' older transactions which are not fully spent. 3029 err = b.checkDupTxs(block.Transactions(), view) 3030 if err != nil { 3031 log.Tracef("checkDupTxs failed for cur TxTreeRegular: %v", err) 3032 return err 3033 } 3034 3035 err = b.checkTransactionsAndConnect(stakeTreeFees, node, 3036 block.Transactions(), view, stxos, true) 3037 if err != nil { 3038 log.Tracef("checkTransactionsAndConnect failed for cur "+ 3039 "TxTreeRegular: %v", err) 3040 return err 3041 } 3042 3043 // Enforce all relative lock times via sequence numbers for the regular 3044 // transaction tree once the stake vote for the agenda is active. 3045 if lnFeaturesActive { 3046 // Skip the coinbase since it does not have any inputs and thus 3047 // lock times do not apply. 3048 for _, tx := range block.Transactions()[1:] { 3049 sequenceLock, err := b.calcSequenceLock(node, tx, 3050 legacySeqLockView, true) 3051 if err != nil { 3052 return err 3053 } 3054 if !SequenceLockActive(sequenceLock, node.height, 3055 prevMedianTime) { 3056 3057 str := fmt.Sprintf("block contains " + 3058 "transaction whose input sequence " + 3059 "locks are not met") 3060 return ruleError(ErrUnfinalizedTx, str) 3061 } 3062 } 3063 } 3064 3065 if runScripts { 3066 err = checkBlockScripts(block, view, true, scriptFlags, 3067 b.sigCache) 3068 if err != nil { 3069 log.Tracef("checkBlockScripts failed; error returned "+ 3070 "on txtreeregular of cur block: %v", err) 3071 return err 3072 } 3073 } 3074 3075 // First block has special rules concerning the ledger. 3076 if node.height == 1 { 3077 err := blockOneCoinbasePaysTokens(block.Transactions()[0], 3078 b.chainParams) 3079 if err != nil { 3080 return err 3081 } 3082 } 3083 3084 // Update the best hash for view to include this block since all of its 3085 // transactions have been connected. 3086 view.SetBestHash(&node.hash) 3087 3088 return nil 3089 } 3090 3091 // CheckConnectBlockTemplate fully validates that connecting the passed block to 3092 // either the tip of the main chain or its parent does not violate any consensus 3093 // rules, aside from the proof of work requirement. The block must connect to 3094 // the current tip of the main chain or its parent. 3095 // 3096 // This function is safe for concurrent access. 3097 func (b *BlockChain) CheckConnectBlockTemplate(block *dcrutil.Block) error { 3098 b.chainLock.Lock() 3099 defer b.chainLock.Unlock() 3100 3101 // Skip the proof of work check as this is just a block template. 3102 flags := BFNoPoWCheck 3103 3104 // The block template must build off the current tip of the main chain 3105 // or its parent. 3106 tip := b.bestChain.Tip() 3107 var prevNode *blockNode 3108 parentHash := block.MsgBlock().Header.PrevBlock 3109 if parentHash == tip.hash { 3110 prevNode = tip 3111 } else if tip.parent != nil && parentHash == tip.parent.hash { 3112 prevNode = tip.parent 3113 } 3114 if prevNode == nil { 3115 var str string 3116 if tip.parent != nil { 3117 str = fmt.Sprintf("previous block must be the current chain tip "+ 3118 "%s or its parent %s, but got %s", tip.hash, tip.parent.hash, 3119 parentHash) 3120 } else { 3121 str = fmt.Sprintf("previous block must be the current chain tip "+ 3122 "%s, but got %s", tip.hash, parentHash) 3123 } 3124 return ruleError(ErrInvalidTemplateParent, str) 3125 } 3126 3127 // Perform context-free sanity checks on the block and its transactions. 3128 err := checkBlockSanity(block, b.timeSource, flags, b.chainParams) 3129 if err != nil { 3130 return err 3131 } 3132 3133 // The block must pass all of the validation rules which depend on having 3134 // the headers of all ancestors available, but do not rely on having the 3135 // full block data of all ancestors available. 3136 err = b.checkBlockPositional(block, prevNode, flags) 3137 if err != nil { 3138 return err 3139 } 3140 3141 // The block must pass all of the validation rules which depend on having 3142 // the full block data for all of its ancestors available. 3143 err = b.checkBlockContext(block, prevNode, flags) 3144 if err != nil { 3145 return err 3146 } 3147 3148 newNode := newBlockNode(&block.MsgBlock().Header, prevNode) 3149 newNode.populateTicketInfo(stake.FindSpentTicketsInBlock(block.MsgBlock())) 3150 3151 // Use the chain state as is when extending the main (best) chain. 3152 if prevNode.hash == tip.hash { 3153 // Grab the parent block since it is required throughout the block 3154 // connection process. 3155 parent, err := b.fetchMainChainBlockByNode(prevNode) 3156 if err != nil { 3157 return ruleError(ErrMissingParent, err.Error()) 3158 } 3159 3160 view := NewUtxoViewpoint() 3161 view.SetBestHash(&tip.hash) 3162 3163 return b.checkConnectBlock(newNode, block, parent, view, nil) 3164 } 3165 3166 // At this point, the block template must be building on the parent of the 3167 // current tip due to the previous checks, so undo the transactions and 3168 // spend information for the tip block to reach the point of view of the 3169 // block template. 3170 view := NewUtxoViewpoint() 3171 view.SetBestHash(&tip.hash) 3172 tipBlock, err := b.fetchMainChainBlockByNode(tip) 3173 if err != nil { 3174 return err 3175 } 3176 parent, err := b.fetchMainChainBlockByNode(tip.parent) 3177 if err != nil { 3178 return err 3179 } 3180 3181 // Load all of the spent txos for the tip block from the spend journal. 3182 var stxos []spentTxOut 3183 err = b.db.View(func(dbTx database.Tx) error { 3184 stxos, err = dbFetchSpendJournalEntry(dbTx, tipBlock) 3185 return err 3186 }) 3187 if err != nil { 3188 return err 3189 } 3190 3191 // Update the view to unspend all of the spent txos and remove the utxos 3192 // created by the tip block. Also, if the block votes against its parent, 3193 // reconnect all of the regular transactions. 3194 err = view.disconnectBlock(b.db, tipBlock, parent, stxos) 3195 if err != nil { 3196 return err 3197 } 3198 3199 // The view is now from the point of view of the parent of the current tip 3200 // block. Ensure the block template can be connected without violating any 3201 // rules. 3202 return b.checkConnectBlock(newNode, block, parent, view, nil) 3203 }