package vm import ( "encoding/binary" ) func getNumOfThingsFromInstr(instr Instruction, param []byte) (int, bool) { var nthings int switch instr { case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16: nthings = int(instr-PUSH1) + 1 case PUSHBYTES1: nthings = int(param[0]) case PUSHBYTES2: nthings = int(binary.LittleEndian.Uint16(param)) default: return 0, false } if nthings < 1 || nthings > MaxArraySize { return 0, false } return nthings, true } // IsMultiSigContract checks whether the passed script is a multi-signature // contract. func IsMultiSigContract(script []byte) bool { var nsigs, nkeys int ctx := NewContext(script) instr, param, err := ctx.Next() if err != nil { return false } nsigs, ok := getNumOfThingsFromInstr(instr, param) if !ok { return false } for { instr, param, err = ctx.Next() if err != nil { return false } if instr != PUSHBYTES33 { break } nkeys++ if nkeys > MaxArraySize { return false } } if nkeys < nsigs { return false } nkeys2, ok := getNumOfThingsFromInstr(instr, param) if !ok { return false } if nkeys2 != nkeys { return false } instr, _, err = ctx.Next() if err != nil || instr != CHECKMULTISIG { return false } instr, _, err = ctx.Next() if err != nil || instr != RET || ctx.ip != len(script) { return false } return true } // IsSignatureContract checks whether the passed script is a signature check // contract. func IsSignatureContract(script []byte) bool { ctx := NewContext(script) instr, _, err := ctx.Next() if err != nil || instr != PUSHBYTES33 { return false } instr, _, err = ctx.Next() if err != nil || instr != CHECKSIG { return false } instr, _, err = ctx.Next() if err != nil || instr != RET || ctx.ip != len(script) { return false } return true } // IsStandardContract checks whether the passed script is a signature or // multi-signature contract. func IsStandardContract(script []byte) bool { return IsSignatureContract(script) || IsMultiSigContract(script) }