txscript: Optimize CalcMultiSigStats.

This converts the CalcMultiSigStats function to make use of the new
extractMultisigScriptDetails function instead of the far less efficient
parseScript thereby significantly optimizing the function.

The tests are also updated accordingly.

The following is a before and after comparison of analyzing a standard
multisig script:

benchmark                    old ns/op    new ns/op    delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   972          79.5         -91.82%

benchmark                    old allocs   new allocs   delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   1            0            -100.00%

benchmark                    old bytes    new bytes    delta
---------------------------------------------------------------
BenchmarkCalcMultiSigStats   2304         0            -100.00%
This commit is contained in:
Dave Collins 2019-03-13 01:12:13 -05:00 committed by Olaoluwa Osuntokun
parent 8c54905959
commit 7791f92f6f
No known key found for this signature in database
GPG key ID: 3BBD59E99B280306
2 changed files with 12 additions and 22 deletions

View file

@ -656,27 +656,21 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
// CalcMultiSigStats returns the number of public keys and signatures from // CalcMultiSigStats returns the number of public keys and signatures from
// a multi-signature transaction script. The passed script MUST already be // a multi-signature transaction script. The passed script MUST already be
// known to be a multi-signature script. // known to be a multi-signature script.
//
// 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 CalcMultiSigStats(script []byte) (int, int, error) { func CalcMultiSigStats(script []byte) (int, int, error) {
pops, err := parseScript(script) // The public keys are not needed here, so pass false to avoid the extra
if err != nil { // allocation.
return 0, 0, err const scriptVersion = 0
} details := extractMultisigScriptDetails(scriptVersion, script, false)
if !details.valid {
// A multi-signature script is of the pattern:
// NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG
// Therefore the number of signatures is the oldest item on the stack
// and the number of pubkeys is the 2nd to last. Also, the absolute
// minimum for a multi-signature script is 1 pubkey, so at least 4
// items must be on the stack per:
// OP_1 PUBKEY OP_1 OP_CHECKMULTISIG
if len(pops) < 4 {
str := fmt.Sprintf("script %x is not a multisig script", script) str := fmt.Sprintf("script %x is not a multisig script", script)
return 0, 0, scriptError(ErrNotMultisigScript, str) return 0, 0, scriptError(ErrNotMultisigScript, str)
} }
numSigs := asSmallInt(pops[0].opcode.value) return details.numPubKeys, details.requiredSigs, nil
numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value)
return numPubKeys, numSigs, nil
} }
// payToPubKeyHashScript creates a new script to pay a transaction // payToPubKeyHashScript creates a new script to pay a transaction

View file

@ -832,7 +832,7 @@ func TestCalcMultiSigStats(t *testing.T) {
name: "short script", name: "short script",
script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" + script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" +
"e03909a67962e0ea1f61d", "e03909a67962e0ea1f61d",
err: scriptError(ErrMalformedPush, ""), err: scriptError(ErrNotMultisigScript, ""),
}, },
{ {
name: "stack underflow", name: "stack underflow",
@ -843,11 +843,7 @@ func TestCalcMultiSigStats(t *testing.T) {
}, },
{ {
name: "multisig script", name: "multisig script",
script: "0 DATA_72 0x30450220106a3e4ef0b51b764a2887226" + script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" +
"2ffef55846514dacbdcbbdd652c849d395b4384022100" +
"e03ae554c3cbb40600d31dd46fc33f25e47bf8525b1fe" +
"07282e3b6ecb5f3bb2801 CODESEPARATOR 1 DATA_33 " +
"0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" +
"0357b3a7886211ab414d55a 1 CHECKMULTISIG", "0357b3a7886211ab414d55a 1 CHECKMULTISIG",
err: nil, err: nil,
}, },