txscript: Optimize CalcSignatureHash.
This modifies the CalcSignatureHash function to make use of the new signature hash calculation function that accepts raw scripts without needing to first parse them. Consequently, it also doubles as a slight optimization to the execution time and a significant reduction in the number of allocations. In order to convert the CalcScriptHash function and keep the same semantics, a new function named checkScriptParses is introduced which will quickly determine if a script can be fully parsed without failure and return the parse failure in the case it can't. The following is a before and after comparison of analyzing a large multiple input transaction: benchmark old ns/op new ns/op delta BenchmarkCalcSigHash-8 3627895 3619477 -0.23% benchmark old allocs new allocs delta BenchmarkCalcSigHash-8 1335 801 -40.00% benchmark old bytes new bytes delta BenchmarkCalcSigHash-8 1373812 1293354 -5.86%
This commit is contained in:
parent
af757d3d0d
commit
c19535b145
1 changed files with 18 additions and 4 deletions
|
@ -567,12 +567,17 @@ func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx {
|
||||||
// CalcSignatureHash will, given a script and hash type for the current script
|
// CalcSignatureHash will, given a script and hash type for the current script
|
||||||
// engine instance, calculate the signature hash to be used for signing and
|
// engine instance, calculate the signature hash to be used for signing and
|
||||||
// verification.
|
// verification.
|
||||||
|
//
|
||||||
|
// NOTE: This function is only valid for version 0 scripts. Since the function
|
||||||
|
// does not accept a script version, the results are undefined for other script
|
||||||
|
// versions.
|
||||||
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) {
|
func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) {
|
||||||
parsedScript, err := parseScript(script)
|
const scriptVersion = 0
|
||||||
if err != nil {
|
if err := checkScriptParses(scriptVersion, script); err != nil {
|
||||||
return nil, fmt.Errorf("cannot parse output script: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return calcSignatureHash(parsedScript, hashType, tx, idx)
|
|
||||||
|
return calcSignatureHashRaw(script, hashType, tx, idx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// calcSignatureHashRaw computes the signature hash for the specified input of
|
// calcSignatureHashRaw computes the signature hash for the specified input of
|
||||||
|
@ -850,6 +855,15 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkScriptParses returns an error if the provided script fails to parse.
|
||||||
|
func checkScriptParses(scriptVersion uint16, script []byte) error {
|
||||||
|
tokenizer := MakeScriptTokenizer(scriptVersion, script)
|
||||||
|
for tokenizer.Next() {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
return tokenizer.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// IsUnspendable returns whether the passed public key script is unspendable, or
|
// IsUnspendable returns whether the passed public key script is unspendable, or
|
||||||
// guaranteed to fail at execution. This allows inputs to be pruned instantly
|
// guaranteed to fail at execution. This allows inputs to be pruned instantly
|
||||||
// when entering the UTXO set.
|
// when entering the UTXO set.
|
||||||
|
|
Loading…
Reference in a new issue