mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-09-03 20:35:10 +00:00
mempool: Improve tx input standard checks.
This changes the transaction input standardness checks as follows: - Allow any script in a pay-to-script-hash transaction to be relayed and mined so long as it has no more than 15 signature operations - Remove the obsolete checks which naively calculated the number of expected inputs in favor of the more accurate ScriptVerifyCleanStack and ScriptVerifySigPushOnly functionality of the script engine that was added after these checks.
This commit is contained in:
parent
c6d50b7abf
commit
2ef82e7db3
1 changed files with 27 additions and 30 deletions
|
@ -14,6 +14,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// maxStandardP2SHSigOps is the maximum number of signature operations
|
||||||
|
// that are considered standard in a pay-to-script-hash script.
|
||||||
|
maxStandardP2SHSigOps = 15
|
||||||
|
|
||||||
// maxStandardTxSize is the maximum size allowed for transactions that
|
// maxStandardTxSize is the maximum size allowed for transactions that
|
||||||
// are considered standard and will therefore be relayed and considered
|
// are considered standard and will therefore be relayed and considered
|
||||||
// for mining.
|
// for mining.
|
||||||
|
@ -152,12 +156,15 @@ func calcInputValueAge(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextB
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkInputsStandard performs a series of checks on a transaction's inputs
|
// checkInputsStandard performs a series of checks on a transaction's inputs
|
||||||
// to ensure they are "standard". A standard transaction input is one that
|
// to ensure they are "standard". A standard transaction input within the
|
||||||
// that consumes the expected number of elements from the stack and that number
|
// context of this function is one whose referenced public key script is of a
|
||||||
// is the same as the output script pushes. This help prevent resource
|
// standard form and, for pay-to-script-hash, does not have more than
|
||||||
// exhaustion attacks by "creative" use of scripts that are super expensive to
|
// maxStandardP2SHSigOps signature operations. However, it should also be noted
|
||||||
// process like OP_DUP OP_CHECKSIG OP_DROP repeated a large number of times
|
// that standard inputs also are those which have a clean stack after execution
|
||||||
// followed by a final OP_TRUE.
|
// 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 {
|
func checkInputsStandard(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) error {
|
||||||
// NOTE: The reference implementation also does a coinbase check here,
|
// NOTE: The reference implementation also does a coinbase check here,
|
||||||
// but coinbases have already been rejected prior to calling this
|
// but coinbases have already been rejected prior to calling this
|
||||||
|
@ -170,31 +177,21 @@ func checkInputsStandard(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) err
|
||||||
prevOut := txIn.PreviousOutPoint
|
prevOut := txIn.PreviousOutPoint
|
||||||
entry := utxoView.LookupEntry(&prevOut.Hash)
|
entry := utxoView.LookupEntry(&prevOut.Hash)
|
||||||
originPkScript := entry.PkScriptByIndex(prevOut.Index)
|
originPkScript := entry.PkScriptByIndex(prevOut.Index)
|
||||||
|
switch txscript.GetScriptClass(originPkScript) {
|
||||||
|
case txscript.ScriptHashTy:
|
||||||
|
numSigOps := txscript.GetPreciseSigOpCount(
|
||||||
|
txIn.SignatureScript, originPkScript, true)
|
||||||
|
if numSigOps > maxStandardP2SHSigOps {
|
||||||
|
str := fmt.Sprintf("transaction input #%d has "+
|
||||||
|
"%d signature operations which is more "+
|
||||||
|
"than the allowed max amount of %d",
|
||||||
|
i, numSigOps, maxStandardP2SHSigOps)
|
||||||
|
return txRuleError(wire.RejectNonstandard, str)
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate stats for the script pair.
|
case txscript.NonStandardTy:
|
||||||
scriptInfo, err := txscript.CalcScriptInfo(txIn.SignatureScript,
|
str := fmt.Sprintf("transaction input #%d has a "+
|
||||||
originPkScript, true)
|
"non-standard script form", i)
|
||||||
if err != nil {
|
|
||||||
str := fmt.Sprintf("transaction input #%d script parse "+
|
|
||||||
"failure: %v", i, err)
|
|
||||||
return txRuleError(wire.RejectNonstandard, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A negative value for expected inputs indicates the script is
|
|
||||||
// non-standard in some way.
|
|
||||||
if scriptInfo.ExpectedInputs < 0 {
|
|
||||||
str := fmt.Sprintf("transaction input #%d expects %d "+
|
|
||||||
"inputs", i, scriptInfo.ExpectedInputs)
|
|
||||||
return txRuleError(wire.RejectNonstandard, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The script pair is non-standard if the number of available
|
|
||||||
// inputs does not match the number of expected inputs.
|
|
||||||
if scriptInfo.NumInputs != scriptInfo.ExpectedInputs {
|
|
||||||
str := fmt.Sprintf("transaction input #%d expects %d "+
|
|
||||||
"inputs, but referenced output script provides "+
|
|
||||||
"%d", i, scriptInfo.ExpectedInputs,
|
|
||||||
scriptInfo.NumInputs)
|
|
||||||
return txRuleError(wire.RejectNonstandard, str)
|
return txRuleError(wire.RejectNonstandard, str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue