// removeTransaction is the internal function which implements the public // RemoveTransaction. See the comment for RemoveTransaction for more details. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) removeTransaction(tx *btcutil.Tx, removeRedeemers bool) { txHash := tx.Hash() if removeRedeemers { // Remove any transactions which rely on this one. for i := uint32(0); i < uint32(len(tx.MsgTx().TxOut)); i++ { prevOut := wire.OutPoint{Hash: *txHash, Index: i} if txRedeemer, exists := mp.outpoints[prevOut]; exists { mp.removeTransaction(txRedeemer, true) } } } // Remove the transaction if needed. if txDesc, exists := mp.pool[*txHash]; exists { // Remove unconfirmed address index entries associated with the // transaction if enabled. if mp.cfg.AddrIndex != nil { mp.cfg.AddrIndex.RemoveUnconfirmedTx(txHash) } // Mark the referenced outpoints as unspent by the pool. for _, txIn := range txDesc.Tx.MsgTx().TxIn { delete(mp.outpoints, txIn.PreviousOutPoint) } delete(mp.pool, *txHash) atomic.StoreInt64(&mp.lastUpdated, time.Now().Unix()) } }
// ExtractWitnessCommitment attempts to locate, and return the witness // commitment for a block. The witness commitment is of the form: // SHA256(witness root || witness nonce). The function additionally returns a // boolean indicating if the witness root was located within any of the txOut's // in the passed transaction. The witness commitment is stored as the data push // for an OP_RETURN with special magic bytes to aide in location. func ExtractWitnessCommitment(tx *btcutil.Tx) ([]byte, bool) { var witnessCommitment []byte // The witness commitment *must* be located within one of the coinbase // transaction's outputs. if !IsCoinBase(tx) { return witnessCommitment, false } msgTx := tx.MsgTx() witFound := false for i := len(msgTx.TxOut) - 1; i >= 0; i-- { // The public key script that contains the witness commitment // must shared a prefix with the WitnessMagicBytes, and be at // least 38 bytes. pkScript := msgTx.TxOut[i].PkScript if len(pkScript) >= 38 && bytes.HasPrefix(pkScript, WitnessMagicBytes) { // The witness commitment itself is a 32-byte hash // directly after the WitnessMagicBytes. The remaining // bytes beyond the 38th byte currently have no consensus // meaning. witnessCommitment = msgTx.TxOut[i].PkScript[6:38] witFound = true break } } return witnessCommitment, witFound }
// IsFinalizedTransaction determines whether or not a transaction is finalized. func IsFinalizedTransaction(tx *btcutil.Tx, blockHeight int32, blockTime time.Time) bool { msgTx := tx.MsgTx() // Lock time of zero means the transaction is finalized. lockTime := msgTx.LockTime if lockTime == 0 { return true } // The lock time field of a transaction is either a block height at // which the transaction is finalized or a timestamp depending on if the // value is before the txscript.LockTimeThreshold. When it is under the // threshold it is a block height. blockTimeOrHeight := int64(0) if lockTime < txscript.LockTimeThreshold { blockTimeOrHeight = int64(blockHeight) } else { blockTimeOrHeight = blockTime.Unix() } if int64(lockTime) < blockTimeOrHeight { return true } // At this point, the transaction's lock time hasn't occurred yet, but // the transaction might still be finalized if the sequence number // for all transaction inputs is maxed out. for _, txIn := range msgTx.TxIn { if txIn.Sequence != math.MaxUint32 { return false } } return true }
func serializeTx(tx *btcutil.Tx) []byte { var buf bytes.Buffer err := tx.MsgTx().Serialize(&buf) if err != nil { panic(err) } return buf.Bytes() }
// removeOrphanDoubleSpends removes all orphans which spend outputs spent by the // passed transaction from the orphan pool. Removing those orphans then leads // to removing all orphans which rely on them, recursively. This is necessary // when a transaction is added to the main pool because it may spend outputs // that orphans also spend. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) removeOrphanDoubleSpends(tx *btcutil.Tx) { msgTx := tx.MsgTx() for _, txIn := range msgTx.TxIn { for _, orphan := range mp.orphansByPrev[txIn.PreviousOutPoint] { mp.removeOrphan(orphan, true) } } }
// GetTransactionWeight computes the value of the weight metric for a given // transaction. Currently the weight metric is simply the sum of the // transactions's serialized size without any witness data scaled // proportionally by the WitnessScaleFactor, and the transaction's serialized // size including any witness data. func GetTransactionWeight(tx *btcutil.Tx) int64 { msgTx := tx.MsgTx() baseSize := msgTx.SerializeSizeStripped() totalSize := msgTx.SerializeSize() // (baseSize * 3) + totalSize return int64((baseSize * (WitnessScaleFactor - 1)) + totalSize) }
// logSkippedDeps logs any dependencies which are also skipped as a result of // skipping a transaction while generating a block template at the trace level. func logSkippedDeps(tx *btcutil.Tx, deps map[chainhash.Hash]*txPrioItem) { if deps == nil { return } for _, item := range deps { log.Tracef("Skipping tx %s since it depends on %s\n", item.tx.Hash(), tx.Hash()) } }
// isNonstandardTransaction determines whether a transaction contains any // scripts which are not one of the standard types. func isNonstandardTransaction(tx *btcutil.Tx) bool { // Check all of the output public key scripts for non-standard scripts. for _, txOut := range tx.MsgTx().TxOut { scriptClass := txscript.GetScriptClass(txOut.PkScript) if scriptClass == txscript.NonStandardTy { return true } } return false }
// checkPoolDoubleSpend checks whether or not the passed transaction is // attempting to spend coins already spent by other transactions in the pool. // Note it does not check for double spends against transactions already in the // main chain. // // This function MUST be called with the mempool lock held (for reads). func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) error { for _, txIn := range tx.MsgTx().TxIn { if txR, exists := mp.outpoints[txIn.PreviousOutPoint]; exists { str := fmt.Sprintf("output %v already spent by "+ "transaction %v in the memory pool", txIn.PreviousOutPoint, txR.Hash()) return txRuleError(wire.RejectDuplicate, str) } } return nil }
// RemoveDoubleSpends removes all transactions which spend outputs spent by the // passed transaction from the memory pool. Removing those transactions then // leads to removing all transactions which rely on them, recursively. This is // necessary when a block is connected to the main chain because the block may // contain transactions which were previously unknown to the memory pool. // // This function is safe for concurrent access. func (mp *TxPool) RemoveDoubleSpends(tx *btcutil.Tx) { // Protect concurrent access. mp.mtx.Lock() for _, txIn := range tx.MsgTx().TxIn { if txRedeemer, ok := mp.outpoints[txIn.PreviousOutPoint]; ok { if !txRedeemer.Hash().IsEqual(tx.Hash()) { mp.removeTransaction(txRedeemer, true) } } } mp.mtx.Unlock() }
// ProcessTransaction is the main workhorse for handling insertion of new // free-standing transactions into the memory pool. It includes functionality // such as rejecting duplicate transactions, ensuring transactions follow all // rules, orphan transaction handling, and insertion into the memory pool. // // It returns a slice of transactions added to the mempool. When the // error is nil, the list will include the passed transaction itself along // with any additional orphan transaactions that were added as a result of // the passed one being accepted. // // This function is safe for concurrent access. func (mp *TxPool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, rateLimit bool, tag Tag) ([]*TxDesc, error) { log.Tracef("Processing transaction %v", tx.Hash()) // Protect concurrent access. mp.mtx.Lock() defer mp.mtx.Unlock() // Potentially accept the transaction to the memory pool. missingParents, txD, err := mp.maybeAcceptTransaction(tx, true, rateLimit, true) if err != nil { return nil, err } if len(missingParents) == 0 { // Accept any orphan transactions that depend on this // transaction (they may no longer be orphans if all inputs // are now available) and repeat for those accepted // transactions until there are no more. newTxs := mp.processOrphans(tx) acceptedTxs := make([]*TxDesc, len(newTxs)+1) // Add the parent transaction first so remote nodes // do not add orphans. acceptedTxs[0] = txD copy(acceptedTxs[1:], newTxs) return acceptedTxs, nil } // The transaction is an orphan (has inputs missing). Reject // it if the flag to allow orphans is not set. if !allowOrphan { // Only use the first missing parent transaction in // the error message. // // NOTE: RejectDuplicate is really not an accurate // reject code here, but it matches the reference // implementation and there isn't a better choice due // to the limited number of reject codes. Missing // inputs is assumed to mean they are already spent // which is not really always the case. str := fmt.Sprintf("orphan transaction %v references "+ "outputs of unknown or fully-spent "+ "transaction %v", tx.Hash(), missingParents[0]) return nil, txRuleError(wire.RejectDuplicate, str) } // Potentially add the orphan transaction to the orphan pool. err = mp.maybeAddOrphan(tx, tag) return nil, err }
// spendTransaction updates the passed view by marking the inputs to the passed // transaction as spent. It also adds all outputs in the passed transaction // which are not provably unspendable as available unspent transaction outputs. func spendTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32) error { for _, txIn := range tx.MsgTx().TxIn { originHash := &txIn.PreviousOutPoint.Hash originIndex := txIn.PreviousOutPoint.Index entry := utxoView.LookupEntry(originHash) if entry != nil { entry.SpendOutput(originIndex) } } utxoView.AddTxOuts(tx, height) return nil }
// connectTransaction updates the view by adding all new utxos created by the // passed transaction and marking all utxos that the transactions spend as // spent. In addition, when the 'stxos' argument is not nil, it will be updated // to append an entry for each spent txout. An error will be returned if the // view does not contain the required utxos. func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, stxos *[]spentTxOut) error { // Coinbase transactions don't have any inputs to spend. if IsCoinBase(tx) { // Add the transaction's outputs as available utxos. view.AddTxOuts(tx, blockHeight) return nil } // Spend the referenced utxos by marking them spent in the view and, // if a slice was provided for the spent txout details, append an entry // to it. for _, txIn := range tx.MsgTx().TxIn { originIndex := txIn.PreviousOutPoint.Index entry := view.entries[txIn.PreviousOutPoint.Hash] // Ensure the referenced utxo exists in the view. This should // never happen unless there is a bug is introduced in the code. if entry == nil { return AssertError(fmt.Sprintf("view missing input %v", txIn.PreviousOutPoint)) } entry.SpendOutput(originIndex) // Don't create the stxo details if not requested. if stxos == nil { continue } // Populate the stxo details using the utxo entry. When the // transaction is fully spent, set the additional stxo fields // accordingly since those details will no longer be available // in the utxo set. var stxo = spentTxOut{ compressed: false, version: entry.Version(), amount: entry.AmountByIndex(originIndex), pkScript: entry.PkScriptByIndex(originIndex), } if entry.IsFullySpent() { stxo.height = entry.BlockHeight() stxo.isCoinBase = entry.IsCoinBase() } // Append the entry to the provided spent txouts slice. *stxos = append(*stxos, stxo) } // Add the transaction's outputs as available utxos. view.AddTxOuts(tx, blockHeight) return nil }
// addOrphan adds an orphan transaction to the orphan pool. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) addOrphan(tx *btcutil.Tx, tag Tag) { // Nothing to do if no orphans are allowed. if mp.cfg.Policy.MaxOrphanTxs <= 0 { return } // Limit the number orphan transactions to prevent memory exhaustion. // This will periodically remove any expired orphans and evict a random // orphan if space is still needed. mp.limitNumOrphans() mp.orphans[*tx.Hash()] = &orphanTx{ tx: tx, tag: tag, expiration: time.Now().Add(orphanTTL), } for _, txIn := range tx.MsgTx().TxIn { if _, exists := mp.orphansByPrev[txIn.PreviousOutPoint]; !exists { mp.orphansByPrev[txIn.PreviousOutPoint] = make(map[chainhash.Hash]*btcutil.Tx) } mp.orphansByPrev[txIn.PreviousOutPoint][*tx.Hash()] = tx } log.Debugf("Stored orphan transaction %v (total: %d)", tx.Hash(), len(mp.orphans)) }
// addTransaction adds the passed transaction to the memory pool. It should // not be called directly as it doesn't perform any validation. This is a // helper for maybeAcceptTransaction. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32, fee int64) *TxDesc { // Add the transaction to the pool and mark the referenced outpoints // as spent by the pool. txD := &TxDesc{ TxDesc: mining.TxDesc{ Tx: tx, Added: time.Now(), Height: height, Fee: fee, FeePerKB: fee * 1000 / int64(tx.MsgTx().SerializeSize()), }, StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height), } mp.pool[*tx.Hash()] = txD for _, txIn := range tx.MsgTx().TxIn { mp.outpoints[txIn.PreviousOutPoint] = tx } atomic.StoreInt64(&mp.lastUpdated, time.Now().Unix()) // Add unconfirmed address index entries associated with the transaction // if enabled. if mp.cfg.AddrIndex != nil { mp.cfg.AddrIndex.AddUnconfirmedTx(tx, utxoView) } return txD }
// CountP2SHSigOps returns the number of signature operations for all input // transactions which are of the pay-to-script-hash type. This uses the // precise, signature operation counting mechanism from the script engine which // requires access to the input transaction scripts. func CountP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint) (int, error) { // Coinbase transactions have no interesting inputs. if isCoinBaseTx { return 0, nil } // Accumulate the number of signature operations in all transaction // inputs. msgTx := tx.MsgTx() totalSigOps := 0 for txInIndex, txIn := range msgTx.TxIn { // Ensure the referenced input transaction is available. originTxHash := &txIn.PreviousOutPoint.Hash originTxIndex := txIn.PreviousOutPoint.Index txEntry := utxoView.LookupEntry(originTxHash) if txEntry == nil || txEntry.IsOutputSpent(originTxIndex) { str := fmt.Sprintf("unable to find unspent output "+ "%v referenced from transaction %s:%d", txIn.PreviousOutPoint, tx.Hash(), txInIndex) return 0, ruleError(ErrMissingTx, str) } // We're only interested in pay-to-script-hash types, so skip // this input if it's not one. pkScript := txEntry.PkScriptByIndex(originTxIndex) if !txscript.IsPayToScriptHash(pkScript) { continue } // Count the precise number of signature operations in the // referenced public key script. sigScript := txIn.SignatureScript numSigOps := txscript.GetPreciseSigOpCount(sigScript, pkScript, true) // We could potentially overflow the accumulator so check for // overflow. lastSigOps := totalSigOps totalSigOps += numSigOps if totalSigOps < lastSigOps { str := fmt.Sprintf("the public key script from output "+ "%v contains too many signature operations - "+ "overflow", txIn.PreviousOutPoint) return 0, ruleError(ErrTooManySigOps, str) } } return totalSigOps, nil }
func (c *RPCClient) onRecvTx(tx *btcutil.Tx, block *btcjson.BlockDetails) { blk, err := parseBlock(block) if err != nil { // Log and drop improper notification. log.Errorf("recvtx notification bad block: %v", err) return } rec, err := wtxmgr.NewTxRecordFromMsgTx(tx.MsgTx(), time.Now()) if err != nil { log.Errorf("Cannot create transaction record for relevant "+ "tx: %v", err) return } select { case c.enqueueNotification <- RelevantTx{rec, blk}: case <-c.quit: } }
// CountSigOps returns the number of signature operations for all transaction // input and output scripts in the provided transaction. This uses the // quicker, but imprecise, signature operation counting mechanism from // txscript. func CountSigOps(tx *btcutil.Tx) int { msgTx := tx.MsgTx() // Accumulate the number of signature operations in all transaction // inputs. totalSigOps := 0 for _, txIn := range msgTx.TxIn { numSigOps := txscript.GetSigOpCount(txIn.SignatureScript) totalSigOps += numSigOps } // Accumulate the number of signature operations in all transaction // outputs. for _, txOut := range msgTx.TxOut { numSigOps := txscript.GetSigOpCount(txOut.PkScript) totalSigOps += numSigOps } return totalSigOps }
// indexUnconfirmedAddresses modifies the unconfirmed (memory-only) address // index to include mappings for the addresses encoded by the passed public key // script to the transaction. // // This function is safe for concurrent access. func (idx *AddrIndex) indexUnconfirmedAddresses(pkScript []byte, tx *btcutil.Tx) { // The error is ignored here since the only reason it can fail is if the // script fails to parse and it was already validated before being // admitted to the mempool. _, addresses, _, _ := txscript.ExtractPkScriptAddrs(pkScript, idx.chainParams) for _, addr := range addresses { // Ignore unsupported address types. addrKey, err := addrToKey(addr) if err != nil { continue } // Add a mapping from the address to the transaction. idx.unconfirmedLock.Lock() addrIndexEntry := idx.txnsByAddr[addrKey] if addrIndexEntry == nil { addrIndexEntry = make(map[chainhash.Hash]*btcutil.Tx) idx.txnsByAddr[addrKey] = addrIndexEntry } addrIndexEntry[*tx.Hash()] = tx // Add a mapping from the transaction to the address. addrsByTxEntry := idx.addrsByTx[*tx.Hash()] if addrsByTxEntry == nil { addrsByTxEntry = make(map[[addrKeySize]byte]struct{}) idx.addrsByTx[*tx.Hash()] = addrsByTxEntry } addrsByTxEntry[addrKey] = struct{}{} idx.unconfirmedLock.Unlock() } }
// FetchUtxoView loads utxo details about the input transactions referenced by // the passed transaction from the point of view of the end of the main chain. // It also attempts to fetch the utxo details for the transaction itself so the // returned view can be examined for duplicate unspent transaction outputs. // // This function is safe for concurrent access however the returned view is NOT. func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) { b.chainLock.RLock() defer b.chainLock.RUnlock() // Create a set of needed transactions based on those referenced by the // inputs of the passed transaction. Also, add the passed transaction // itself as a way for the caller to detect duplicates that are not // fully spent. txNeededSet := make(map[chainhash.Hash]struct{}) txNeededSet[*tx.Hash()] = struct{}{} if !IsCoinBase(tx) { for _, txIn := range tx.MsgTx().TxIn { txNeededSet[txIn.PreviousOutPoint.Hash] = struct{}{} } } // Request the utxos from the point of view of the end of the main // chain. view := NewUtxoViewpoint() err := view.fetchUtxosMain(b.db, txNeededSet) return view, err }
// checkInputsStandard performs a series of checks on a transaction's inputs // to ensure they are "standard". A standard transaction input within the // context of this function is one whose referenced public key script is of a // standard form and, for pay-to-script-hash, does not have more than // maxStandardP2SHSigOps signature operations. However, it should also be noted // that standard inputs also are those which have a clean stack after execution // and only contain pushed data in their signature scripts. This function does // not perform those checks because the script engine already does this more // accurately and concisely via the txscript.ScriptVerifyCleanStack and // txscript.ScriptVerifySigPushOnly flags. func checkInputsStandard(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) error { // NOTE: The reference implementation also does a coinbase check here, // but coinbases have already been rejected prior to calling this // function so no need to recheck. for i, txIn := range tx.MsgTx().TxIn { // It is safe to elide existence and index checks here since // they have already been checked prior to calling this // function. prevOut := txIn.PreviousOutPoint entry := utxoView.LookupEntry(&prevOut.Hash) originPkScript := entry.PkScriptByIndex(prevOut.Index) switch txscript.GetScriptClass(originPkScript) { case txscript.NonStandardTy: str := fmt.Sprintf("transaction input #%d has a "+ "non-standard script form", i) return txRuleError(wire.RejectNonstandard, str) } } return nil }
// AddUnconfirmedTx adds all addresses related to the transaction to the // unconfirmed (memory-only) address index. // // NOTE: This transaction MUST have already been validated by the memory pool // before calling this function with it and have all of the inputs available in // the provided utxo view. Failure to do so could result in some or all // addresses not being indexed. // // This function is safe for concurrent access. func (idx *AddrIndex) AddUnconfirmedTx(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) { // Index addresses of all referenced previous transaction outputs. // // The existence checks are elided since this is only called after the // transaction has already been validated and thus all inputs are // already known to exist. for _, txIn := range tx.MsgTx().TxIn { entry := utxoView.LookupEntry(&txIn.PreviousOutPoint.Hash) if entry == nil { // Ignore missing entries. This should never happen // in practice since the function comments specifically // call out all inputs must be available. continue } pkScript := entry.PkScriptByIndex(txIn.PreviousOutPoint.Index) idx.indexUnconfirmedAddresses(pkScript, tx) } // Index addresses of all created outputs. for _, txOut := range tx.MsgTx().TxOut { idx.indexUnconfirmedAddresses(txOut.PkScript, tx) } }
// ExtractCoinbaseHeight attempts to extract the height of the block from the // scriptSig of a coinbase transaction. Coinbase heights are only present in // blocks of version 2 or later. This was added as part of BIP0034. func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) { sigScript := coinbaseTx.MsgTx().TxIn[0].SignatureScript if len(sigScript) < 1 { str := "the coinbase signature script for blocks of " + "version %d or greater must start with the " + "length of the serialized block height" str = fmt.Sprintf(str, serializedHeightVersion) return 0, ruleError(ErrMissingCoinbaseHeight, str) } // Detect the case when the block height is a small integer encoded with // as single byte. opcode := int(sigScript[0]) if opcode == txscript.OP_0 { return 0, nil } if opcode >= txscript.OP_1 && opcode <= txscript.OP_16 { return int32(opcode - (txscript.OP_1 - 1)), nil } // Otherwise, the opcode is the length of the following bytes which // encode in the block height. serializedLen := int(sigScript[0]) if len(sigScript[1:]) < serializedLen { str := "the coinbase signature script for blocks of " + "version %d or greater must start with the " + "serialized block height" str = fmt.Sprintf(str, serializedLen) return 0, ruleError(ErrMissingCoinbaseHeight, str) } serializedHeightBytes := make([]byte, 8, 8) copy(serializedHeightBytes, sigScript[1:serializedLen+1]) serializedHeight := binary.LittleEndian.Uint64(serializedHeightBytes) return int32(serializedHeight), nil }
// GetSigOpCost returns the unified sig op cost for the passed transaction // respecting current active soft-forks which modified sig op cost counting. // The unified sig op cost for a transaction is computed as the sum of: the // legacy sig op count scaled according to the WitnessScaleFactor, the sig op // count for all p2sh inputs scaled by the WitnessScaleFactor, and finally the // unscaled sig op count for any inputs spending witness programs. func GetSigOpCost(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint, bip16, segWit bool) (int, error) { numSigOps := CountSigOps(tx) * WitnessScaleFactor if bip16 { numP2SHSigOps, err := CountP2SHSigOps(tx, isCoinBaseTx, utxoView) if err != nil { return 0, nil } numSigOps += (numP2SHSigOps * WitnessScaleFactor) } if segWit && !isCoinBaseTx { msgTx := tx.MsgTx() for txInIndex, txIn := range msgTx.TxIn { // Ensure the referenced input transaction is available. originTxHash := &txIn.PreviousOutPoint.Hash originTxIndex := txIn.PreviousOutPoint.Index txEntry := utxoView.LookupEntry(originTxHash) if txEntry == nil || txEntry.IsOutputSpent(originTxIndex) { str := fmt.Sprintf("unable to find unspent output "+ "%v referenced from transaction %s:%d", txIn.PreviousOutPoint, tx.Hash(), txInIndex) return 0, ruleError(ErrMissingTx, str) } witness := txIn.Witness sigScript := txIn.SignatureScript pkScript := txEntry.PkScriptByIndex(originTxIndex) numSigOps += txscript.GetWitnessSigOpCount(sigScript, pkScript, witness) } } return numSigOps, nil }
// maybeAddOrphan potentially adds an orphan to the orphan pool. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) maybeAddOrphan(tx *btcutil.Tx, tag Tag) error { // Ignore orphan transactions that are too large. This helps avoid // a memory exhaustion attack based on sending a lot of really large // orphans. In the case there is a valid transaction larger than this, // it will ultimtely be rebroadcast after the parent transactions // have been mined or otherwise received. // // Note that the number of orphan transactions in the orphan pool is // also limited, so this equates to a maximum memory used of // mp.cfg.Policy.MaxOrphanTxSize * mp.cfg.Policy.MaxOrphanTxs (which is ~5MB // using the default values at the time this comment was written). serializedLen := tx.MsgTx().SerializeSize() if serializedLen > mp.cfg.Policy.MaxOrphanTxSize { str := fmt.Sprintf("orphan transaction size of %d bytes is "+ "larger than max allowed size of %d bytes", serializedLen, mp.cfg.Policy.MaxOrphanTxSize) return txRuleError(wire.RejectNonstandard, str) } // Add the orphan if the none of the above disqualified it. mp.addOrphan(tx, tag) return nil }
// removeOrphan is the internal function which implements the public // RemoveOrphan. See the comment for RemoveOrphan for more details. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) removeOrphan(tx *btcutil.Tx, removeRedeemers bool) { // Nothing to do if passed tx is not an orphan. txHash := tx.Hash() otx, exists := mp.orphans[*txHash] if !exists { return } // Remove the reference from the previous orphan index. for _, txIn := range otx.tx.MsgTx().TxIn { orphans, exists := mp.orphansByPrev[txIn.PreviousOutPoint] if exists { delete(orphans, *txHash) // Remove the map entry altogether if there are no // longer any orphans which depend on it. if len(orphans) == 0 { delete(mp.orphansByPrev, txIn.PreviousOutPoint) } } } // Remove any orphans that redeem outputs from this one if requested. if removeRedeemers { prevOut := wire.OutPoint{Hash: *txHash} for txOutIdx := range tx.MsgTx().TxOut { prevOut.Index = uint32(txOutIdx) for _, orphan := range mp.orphansByPrev[prevOut] { mp.removeOrphan(orphan, true) } } } // Remove the transaction from the orphan pool. delete(mp.orphans, *txHash) }
// AddTxOuts adds all outputs in the passed transaction which are not provably // unspendable to the view. When the view already has entries for any of the // outputs, they are simply marked unspent. All fields will be updated for // existing entries since it's possible it has changed during a reorg. func (view *UtxoViewpoint) AddTxOuts(tx *btcutil.Tx, blockHeight int32) { // When there are not already any utxos associated with the transaction, // add a new entry for it to the view. entry := view.LookupEntry(tx.Hash()) if entry == nil { entry = newUtxoEntry(tx.MsgTx().Version, IsCoinBase(tx), blockHeight) view.entries[*tx.Hash()] = entry } else { entry.blockHeight = blockHeight } entry.modified = true // Loop all of the transaction outputs and add those which are not // provably unspendable. for txOutIdx, txOut := range tx.MsgTx().TxOut { if txscript.IsUnspendable(txOut.PkScript) { continue } // Update existing entries. All fields are updated because it's // possible (although extremely unlikely) that the existing // entry is being replaced by a different transaction with the // same hash. This is allowed so long as the previous // transaction is fully spent. if output, ok := entry.sparseOutputs[uint32(txOutIdx)]; ok { output.spent = false output.compressed = false output.amount = txOut.Value output.pkScript = txOut.PkScript continue } // Add the unspent transaction output. entry.sparseOutputs[uint32(txOutIdx)] = &utxoOutput{ spent: false, compressed: false, amount: txOut.Value, pkScript: txOut.PkScript, } } return }
// ValidateTransactionScripts validates the scripts for the passed transaction // using multiple goroutines. func ValidateTransactionScripts(tx *btcutil.Tx, utxoView *UtxoViewpoint, flags txscript.ScriptFlags, sigCache *txscript.SigCache, hashCache *txscript.HashCache) error { // If the hashcache doesn't yet has the sighash midstate for this // transaction, then we'll compute them now so we can re-use them // amongst all worker validation goroutines. if !hashCache.ContainsHashes(tx.Hash()) { hashCache.AddSigHashes(tx.MsgTx()) } // The same pointer to the transaction's sighash midstate will be // re-used amongst all validation goroutines. By pre-computing the // sighash here instead of during validation, we ensure the sighashes // are only computed once. cachedHashes, _ := hashCache.GetSigHashes(tx.Hash()) // Collect all of the transaction inputs and required information for // validation. txIns := tx.MsgTx().TxIn txValItems := make([]*txValidateItem, 0, len(txIns)) for txInIdx, txIn := range txIns { // Skip coinbases. if txIn.PreviousOutPoint.Index == math.MaxUint32 { continue } txVI := &txValidateItem{ txInIndex: txInIdx, txIn: txIn, tx: tx, sigHashes: cachedHashes, } txValItems = append(txValItems, txVI) } // Validate all of the inputs. validator := newTxValidator(utxoView, flags, sigCache, hashCache) return validator.Validate(txValItems) }
// CheckTransactionInputs performs a series of checks on the inputs to a // transaction to ensure they are valid. An example of some of the checks // include verifying all inputs exist, ensuring the coinbase seasoning // requirements are met, detecting double spends, validating all values and fees // are in the legal range and the total output amount doesn't exceed the input // amount, and verifying the signatures to prove the spender was the owner of // the bitcoins and therefore allowed to spend them. As it checks the inputs, // it also calculates the total fees for the transaction and returns that value. // // NOTE: The transaction MUST have already been sanity checked with the // CheckTransactionSanity function prior to calling this function. func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpoint, chainParams *chaincfg.Params) (int64, error) { // Coinbase transactions have no inputs. if IsCoinBase(tx) { return 0, nil } txHash := tx.Hash() var totalSatoshiIn int64 for txInIndex, txIn := range tx.MsgTx().TxIn { // Ensure the referenced input transaction is available. originTxHash := &txIn.PreviousOutPoint.Hash utxoEntry := utxoView.LookupEntry(originTxHash) if utxoEntry == nil { str := fmt.Sprintf("unable to find unspent output "+ "%v referenced from transaction %s:%d", txIn.PreviousOutPoint, tx.Hash(), txInIndex) return 0, ruleError(ErrMissingTx, str) } // Ensure the transaction is not spending coins which have not // yet reached the required coinbase maturity. if utxoEntry.IsCoinBase() { originHeight := utxoEntry.BlockHeight() blocksSincePrev := txHeight - originHeight coinbaseMaturity := int32(chainParams.CoinbaseMaturity) if blocksSincePrev < coinbaseMaturity { str := fmt.Sprintf("tried to spend coinbase "+ "transaction %v from height %v at "+ "height %v before required maturity "+ "of %v blocks", originTxHash, originHeight, txHeight, coinbaseMaturity) return 0, ruleError(ErrImmatureSpend, str) } } // Ensure the transaction is not double spending coins. originTxIndex := txIn.PreviousOutPoint.Index if utxoEntry.IsOutputSpent(originTxIndex) { str := fmt.Sprintf("transaction %s:%d tried to double "+ "spend output %v", txHash, txInIndex, txIn.PreviousOutPoint) return 0, ruleError(ErrDoubleSpend, str) } // Ensure the transaction amounts are in range. Each of the // output values of the input transactions must not be negative // or more than the max allowed per transaction. All amounts in // a transaction are in a unit value known as a satoshi. One // bitcoin is a quantity of satoshi as defined by the // SatoshiPerBitcoin constant. originTxSatoshi := utxoEntry.AmountByIndex(originTxIndex) if originTxSatoshi < 0 { str := fmt.Sprintf("transaction output has negative "+ "value of %v", btcutil.Amount(originTxSatoshi)) return 0, ruleError(ErrBadTxOutValue, str) } if originTxSatoshi > btcutil.MaxSatoshi { str := fmt.Sprintf("transaction output value of %v is "+ "higher than max allowed value of %v", btcutil.Amount(originTxSatoshi), btcutil.MaxSatoshi) return 0, ruleError(ErrBadTxOutValue, str) } // The total of all outputs must not be more than the max // allowed per transaction. Also, we could potentially overflow // the accumulator so check for overflow. lastSatoshiIn := totalSatoshiIn totalSatoshiIn += originTxSatoshi if totalSatoshiIn < lastSatoshiIn || totalSatoshiIn > btcutil.MaxSatoshi { str := fmt.Sprintf("total value of all transaction "+ "inputs is %v which is higher than max "+ "allowed value of %v", totalSatoshiIn, btcutil.MaxSatoshi) return 0, ruleError(ErrBadTxOutValue, str) } } // Calculate the total output amount for this transaction. It is safe // to ignore overflow and out of range errors here because those error // conditions would have already been caught by checkTransactionSanity. var totalSatoshiOut int64 for _, txOut := range tx.MsgTx().TxOut { totalSatoshiOut += txOut.Value } // Ensure the transaction does not spend more than its inputs. if totalSatoshiIn < totalSatoshiOut { str := fmt.Sprintf("total value of all transaction inputs for "+ "transaction %v is %v which is less than the amount "+ "spent of %v", txHash, totalSatoshiIn, totalSatoshiOut) return 0, ruleError(ErrSpendTooHigh, str) } // NOTE: bitcoind checks if the transaction fees are < 0 here, but that // is an impossible condition because of the check above that ensures // the inputs are >= the outputs. txFeeInSatoshi := totalSatoshiIn - totalSatoshiOut return txFeeInSatoshi, nil }
// maybeAcceptTransaction is the internal function which implements the public // MaybeAcceptTransaction. See the comment for MaybeAcceptTransaction for // more details. // // This function MUST be called with the mempool lock held (for writes). func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) { txHash := tx.Hash() // Don't accept the transaction if it already exists in the pool. This // applies to orphan transactions as well when the reject duplicate // orphans flag is set. This check is intended to be a quick check to // weed out duplicates. if mp.isTransactionInPool(txHash) || (rejectDupOrphans && mp.isOrphanInPool(txHash)) { str := fmt.Sprintf("already have transaction %v", txHash) return nil, nil, txRuleError(wire.RejectDuplicate, str) } // Perform preliminary sanity checks on the transaction. This makes // use of blockchain which contains the invariant rules for what // transactions are allowed into blocks. err := blockchain.CheckTransactionSanity(tx) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } // A standalone transaction must not be a coinbase transaction. if blockchain.IsCoinBase(tx) { str := fmt.Sprintf("transaction %v is an individual coinbase", txHash) return nil, nil, txRuleError(wire.RejectInvalid, str) } // Don't accept transactions with a lock time after the maximum int32 // value for now. This is an artifact of older bitcoind clients which // treated this field as an int32 and would treat anything larger // incorrectly (as negative). if tx.MsgTx().LockTime > math.MaxInt32 { str := fmt.Sprintf("transaction %v has a lock time after "+ "2038 which is not accepted yet", txHash) return nil, nil, txRuleError(wire.RejectNonstandard, str) } // Get the current height of the main chain. A standalone transaction // will be mined into the next block at best, so its height is at least // one more than the current height. bestHeight := mp.cfg.BestHeight() nextBlockHeight := bestHeight + 1 medianTimePast := mp.cfg.MedianTimePast() // Don't allow non-standard transactions if the network parameters // forbid their acceptance. if !mp.cfg.Policy.AcceptNonStd { err = checkTransactionStandard(tx, nextBlockHeight, medianTimePast, mp.cfg.Policy.MinRelayTxFee, mp.cfg.Policy.MaxTxVersion) if err != nil { // Attempt to extract a reject code from the error so // it can be retained. When not possible, fall back to // a non standard error. rejectCode, found := extractRejectCode(err) if !found { rejectCode = wire.RejectNonstandard } str := fmt.Sprintf("transaction %v is not standard: %v", txHash, err) return nil, nil, txRuleError(rejectCode, str) } } // The transaction may not use any of the same outputs as other // transactions already in the pool as that would ultimately result in a // double spend. This check is intended to be quick and therefore only // detects double spends within the transaction pool itself. The // transaction could still be double spending coins from the main chain // at this point. There is a more in-depth check that happens later // after fetching the referenced transaction inputs from the main chain // which examines the actual spend data and prevents double spends. err = mp.checkPoolDoubleSpend(tx) if err != nil { return nil, nil, err } // Fetch all of the unspent transaction outputs referenced by the inputs // to this transaction. This function also attempts to fetch the // transaction itself to be used for detecting a duplicate transaction // without needing to do a separate lookup. utxoView, err := mp.fetchInputUtxos(tx) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } // Don't allow the transaction if it exists in the main chain and is not // not already fully spent. txEntry := utxoView.LookupEntry(txHash) if txEntry != nil && !txEntry.IsFullySpent() { return nil, nil, txRuleError(wire.RejectDuplicate, "transaction already exists") } delete(utxoView.Entries(), *txHash) // Transaction is an orphan if any of the referenced input transactions // don't exist. Adding orphans to the orphan pool is not handled by // this function, and the caller should use maybeAddOrphan if this // behavior is desired. var missingParents []*chainhash.Hash for originHash, entry := range utxoView.Entries() { if entry == nil || entry.IsFullySpent() { // Must make a copy of the hash here since the iterator // is replaced and taking its address directly would // result in all of the entries pointing to the same // memory location and thus all be the final hash. hashCopy := originHash missingParents = append(missingParents, &hashCopy) } } if len(missingParents) > 0 { return missingParents, nil, nil } // Don't allow the transaction into the mempool unless its sequence // lock is active, meaning that it'll be allowed into the next block // with respect to its defined relative lock times. sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } if !blockchain.SequenceLockActive(sequenceLock, nextBlockHeight, medianTimePast) { return nil, nil, txRuleError(wire.RejectNonstandard, "transaction's sequence locks on inputs not met") } // Perform several checks on the transaction inputs using the invariant // rules in blockchain for what transactions are allowed into blocks. // Also returns the fees associated with the transaction which will be // used later. txFee, err := blockchain.CheckTransactionInputs(tx, nextBlockHeight, utxoView, mp.cfg.ChainParams) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } // Don't allow transactions with non-standard inputs if the network // parameters forbid their acceptance. if !mp.cfg.Policy.AcceptNonStd { err := checkInputsStandard(tx, utxoView) if err != nil { // Attempt to extract a reject code from the error so // it can be retained. When not possible, fall back to // a non standard error. rejectCode, found := extractRejectCode(err) if !found { rejectCode = wire.RejectNonstandard } str := fmt.Sprintf("transaction %v has a non-standard "+ "input: %v", txHash, err) return nil, nil, txRuleError(rejectCode, str) } } // NOTE: if you modify this code to accept non-standard transactions, // you should add code here to check that the transaction does a // reasonable number of ECDSA signature verifications. // Don't allow transactions with an excessive number of signature // operations which would result in making it impossible to mine. Since // the coinbase address itself can contain signature operations, the // maximum allowed signature operations per transaction is less than // the maximum allowed signature operations per block. // TODO(roasbeef): last bool should be conditional on segwit activation sigOpCost, err := blockchain.GetSigOpCost(tx, false, utxoView, true, true) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } if sigOpCost > mp.cfg.Policy.MaxSigOpCostPerTx { str := fmt.Sprintf("transaction %v sigop cost is too high: %d > %d", txHash, sigOpCost, maxStandardSigOpsCost) return nil, nil, txRuleError(wire.RejectNonstandard, str) } // Don't allow transactions with fees too low to get into a mined block. // // Most miners allow a free transaction area in blocks they mine to go // alongside the area used for high-priority transactions as well as // transactions with fees. A transaction size of up to 1000 bytes is // considered safe to go into this section. Further, the minimum fee // calculated below on its own would encourage several small // transactions to avoid fees rather than one single larger transaction // which is more desirable. Therefore, as long as the size of the // transaction does not exceeed 1000 less than the reserved space for // high-priority transactions, don't require a fee for it. serializedSize := blockchain.GetTxVirtualSize(tx) minFee := calcMinRequiredTxRelayFee(serializedSize, mp.cfg.Policy.MinRelayTxFee) if serializedSize >= (DefaultBlockPrioritySize-1000) && txFee < minFee { str := fmt.Sprintf("transaction %v has %d fees which is under "+ "the required amount of %d", txHash, txFee, minFee) return nil, nil, txRuleError(wire.RejectInsufficientFee, str) } // Require that free transactions have sufficient priority to be mined // in the next block. Transactions which are being added back to the // memory pool from blocks that have been disconnected during a reorg // are exempted. if isNew && !mp.cfg.Policy.DisableRelayPriority && txFee < minFee { currentPriority := mining.CalcPriority(tx.MsgTx(), utxoView, nextBlockHeight) if currentPriority <= mining.MinHighPriority { str := fmt.Sprintf("transaction %v has insufficient "+ "priority (%g <= %g)", txHash, currentPriority, mining.MinHighPriority) return nil, nil, txRuleError(wire.RejectInsufficientFee, str) } } // Free-to-relay transactions are rate limited here to prevent // penny-flooding with tiny transactions as a form of attack. if rateLimit && txFee < minFee { nowUnix := time.Now().Unix() // Decay passed data with an exponentially decaying ~10 minute // window - matches bitcoind handling. mp.pennyTotal *= math.Pow(1.0-1.0/600.0, float64(nowUnix-mp.lastPennyUnix)) mp.lastPennyUnix = nowUnix // Are we still over the limit? if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 { str := fmt.Sprintf("transaction %v has been rejected "+ "by the rate limiter due to low fees", txHash) return nil, nil, txRuleError(wire.RejectInsufficientFee, str) } oldTotal := mp.pennyTotal mp.pennyTotal += float64(serializedSize) log.Tracef("rate limit: curTotal %v, nextTotal: %v, "+ "limit %v", oldTotal, mp.pennyTotal, mp.cfg.Policy.FreeTxRelayLimit*10*1000) } // Verify crypto signatures for each input and reject the transaction if // any don't verify. err = blockchain.ValidateTransactionScripts(tx, utxoView, txscript.StandardVerifyFlags, mp.cfg.SigCache, mp.cfg.HashCache) if err != nil { if cerr, ok := err.(blockchain.RuleError); ok { return nil, nil, chainRuleError(cerr) } return nil, nil, err } // Add to transaction pool. txD := mp.addTransaction(utxoView, tx, bestHeight, txFee) log.Debugf("Accepted transaction %v (pool size: %v)", txHash, len(mp.pool)) return nil, txD, nil }