vm: implement ParseMultisigContract()
When creating witness for a multisig contract, it is needed to extract the order of public keys from it.
This commit is contained in:
parent
acea3867b2
commit
8819d4f970
1 changed files with 19 additions and 10 deletions
|
@ -31,49 +31,58 @@ func getNumOfThingsFromInstr(instr opcode.Opcode, param []byte) (int, bool) {
|
||||||
// IsMultiSigContract checks whether the passed script is a multi-signature
|
// IsMultiSigContract checks whether the passed script is a multi-signature
|
||||||
// contract.
|
// contract.
|
||||||
func IsMultiSigContract(script []byte) bool {
|
func IsMultiSigContract(script []byte) bool {
|
||||||
|
_, ok := ParseMultiSigContract(script)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMultiSigContract returns list of public keys from the verification
|
||||||
|
// script of the contract.
|
||||||
|
func ParseMultiSigContract(script []byte) ([][]byte, bool) {
|
||||||
var nsigs, nkeys int
|
var nsigs, nkeys int
|
||||||
|
|
||||||
ctx := NewContext(script)
|
ctx := NewContext(script)
|
||||||
instr, param, err := ctx.Next()
|
instr, param, err := ctx.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
nsigs, ok := getNumOfThingsFromInstr(instr, param)
|
nsigs, ok := getNumOfThingsFromInstr(instr, param)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
var pubs [][]byte
|
||||||
for {
|
for {
|
||||||
instr, param, err = ctx.Next()
|
instr, param, err = ctx.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
if instr != opcode.PUSHBYTES33 {
|
if instr != opcode.PUSHBYTES33 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
pubs = append(pubs, param)
|
||||||
nkeys++
|
nkeys++
|
||||||
if nkeys > MaxArraySize {
|
if nkeys > MaxArraySize {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if nkeys < nsigs {
|
if nkeys < nsigs {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
nkeys2, ok := getNumOfThingsFromInstr(instr, param)
|
nkeys2, ok := getNumOfThingsFromInstr(instr, param)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
if nkeys2 != nkeys {
|
if nkeys2 != nkeys {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
instr, _, err = ctx.Next()
|
instr, _, err = ctx.Next()
|
||||||
if err != nil || instr != opcode.CHECKMULTISIG {
|
if err != nil || instr != opcode.CHECKMULTISIG {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
instr, _, err = ctx.Next()
|
instr, _, err = ctx.Next()
|
||||||
if err != nil || instr != opcode.RET || ctx.ip != len(script) {
|
if err != nil || instr != opcode.RET || ctx.ip != len(script) {
|
||||||
return false
|
return nil, false
|
||||||
}
|
}
|
||||||
return true
|
return pubs, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSignatureContract checks whether the passed script is a signature check
|
// IsSignatureContract checks whether the passed script is a signature check
|
||||||
|
|
Loading…
Reference in a new issue