Don't possibly dereference bad signatures in OP_CHECKMULTISIG.
We do all the preprocessing in one loop. Fixes a bug introduced a while ago to handle invalid signatures. Found by more tests from bitcoind.
This commit is contained in:
parent
c8332cc9a7
commit
dab2a7cb0f
1 changed files with 15 additions and 8 deletions
23
opcode.go
23
opcode.go
|
@ -1819,6 +1819,11 @@ func opcodeCheckSigVerify(op *parsedOpcode, s *Script) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sig struct {
|
||||||
|
s *btcec.Signature
|
||||||
|
ht byte
|
||||||
|
}
|
||||||
|
|
||||||
// stack; sigs <numsigs> pubkeys <numpubkeys>
|
// stack; sigs <numsigs> pubkeys <numpubkeys>
|
||||||
func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
||||||
|
|
||||||
|
@ -1857,21 +1862,25 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
||||||
nsig := int(numSignatures.Int64())
|
nsig := int(numSignatures.Int64())
|
||||||
|
|
||||||
sigStrings := make([][]byte, nsig)
|
sigStrings := make([][]byte, nsig)
|
||||||
signatures := make([]*btcec.Signature, 0, nsig)
|
signatures := make([]sig, 0, nsig)
|
||||||
for i := range sigStrings {
|
for i := range sigStrings {
|
||||||
sigStrings[i], err = s.dstack.PopByteArray()
|
sigStrings[i], err = s.dstack.PopByteArray()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var sig *btcec.Signature
|
if len(sigStrings[i]) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sig := sig{}
|
||||||
|
sig.ht = sigStrings[i][len(sigStrings[i])-1]
|
||||||
// skip off the last byte for hashtype
|
// skip off the last byte for hashtype
|
||||||
if s.der {
|
if s.der {
|
||||||
sig, err =
|
sig.s, err =
|
||||||
btcec.ParseDERSignature(
|
btcec.ParseDERSignature(
|
||||||
sigStrings[i][:len(sigStrings[i])-1],
|
sigStrings[i][:len(sigStrings[i])-1],
|
||||||
btcec.S256())
|
btcec.S256())
|
||||||
} else {
|
} else {
|
||||||
sig, err =
|
sig.s, err =
|
||||||
btcec.ParseSignature(
|
btcec.ParseSignature(
|
||||||
sigStrings[i][:len(sigStrings[i])-1],
|
sigStrings[i][:len(sigStrings[i])-1],
|
||||||
btcec.S256())
|
btcec.S256())
|
||||||
|
@ -1906,10 +1915,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
||||||
for i := range signatures {
|
for i := range signatures {
|
||||||
// check signatures.
|
// check signatures.
|
||||||
success := false
|
success := false
|
||||||
// get hashtype from original byte string
|
|
||||||
hashType := sigStrings[i][len(sigStrings[i])-1]
|
|
||||||
|
|
||||||
hash := calcScriptHash(script, hashType, &s.tx, s.txidx)
|
hash := calcScriptHash(script, signatures[i].ht, &s.tx, s.txidx)
|
||||||
inner:
|
inner:
|
||||||
// Find first pubkey that successfully validates signature.
|
// Find first pubkey that successfully validates signature.
|
||||||
// we start off the search from the key that was successful
|
// we start off the search from the key that was successful
|
||||||
|
@ -1924,7 +1931,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
success = ecdsa.Verify(pubKeys[curPk], hash,
|
success = ecdsa.Verify(pubKeys[curPk], hash,
|
||||||
signatures[i].R, signatures[i].S)
|
signatures[i].s.R, signatures[i].s.S)
|
||||||
if success {
|
if success {
|
||||||
break inner
|
break inner
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue