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:
parent
ea7b0e3816
commit
e0cafeb4ca
2 changed files with 12 additions and 22 deletions
|
@ -656,27 +656,21 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness,
|
|||
// CalcMultiSigStats returns the number of public keys and signatures from
|
||||
// a multi-signature transaction script. The passed script MUST already be
|
||||
// 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) {
|
||||
pops, err := parseScript(script)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// The public keys are not needed here, so pass false to avoid the extra
|
||||
// allocation.
|
||||
const scriptVersion = 0
|
||||
details := extractMultisigScriptDetails(scriptVersion, script, false)
|
||||
if !details.valid {
|
||||
str := fmt.Sprintf("script %x is not a multisig script", script)
|
||||
return 0, 0, scriptError(ErrNotMultisigScript, str)
|
||||
}
|
||||
|
||||
numSigs := asSmallInt(pops[0].opcode.value)
|
||||
numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value)
|
||||
return numPubKeys, numSigs, nil
|
||||
return details.numPubKeys, details.requiredSigs, nil
|
||||
}
|
||||
|
||||
// payToPubKeyHashScript creates a new script to pay a transaction
|
||||
|
|
|
@ -832,7 +832,7 @@ func TestCalcMultiSigStats(t *testing.T) {
|
|||
name: "short script",
|
||||
script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" +
|
||||
"e03909a67962e0ea1f61d",
|
||||
err: scriptError(ErrMalformedPush, ""),
|
||||
err: scriptError(ErrNotMultisigScript, ""),
|
||||
},
|
||||
{
|
||||
name: "stack underflow",
|
||||
|
@ -843,11 +843,7 @@ func TestCalcMultiSigStats(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "multisig script",
|
||||
script: "0 DATA_72 0x30450220106a3e4ef0b51b764a2887226" +
|
||||
"2ffef55846514dacbdcbbdd652c849d395b4384022100" +
|
||||
"e03ae554c3cbb40600d31dd46fc33f25e47bf8525b1fe" +
|
||||
"07282e3b6ecb5f3bb2801 CODESEPARATOR 1 DATA_33 " +
|
||||
"0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" +
|
||||
script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" +
|
||||
"0357b3a7886211ab414d55a 1 CHECKMULTISIG",
|
||||
err: nil,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue