diff --git a/pkg/vm/contract_checks.go b/pkg/vm/contract_checks.go index 00b425032..7a721aa3a 100644 --- a/pkg/vm/contract_checks.go +++ b/pkg/vm/contract_checks.go @@ -105,24 +105,32 @@ func ParseMultiSigContract(script []byte) (int, [][]byte, bool) { // IsSignatureContract checks whether the passed script is a signature check // contract. func IsSignatureContract(script []byte) bool { + _, ok := ParseSignatureContract(script) + return ok +} + +// ParseSignatureContract parses simple signature contract and returns +// public key. +func ParseSignatureContract(script []byte) ([]byte, bool) { if len(script) != 41 { - return false + return nil, false } ctx := NewContext(script) instr, param, err := ctx.Next() if err != nil || instr != opcode.PUSHDATA1 || len(param) != 33 { - return false + return nil, false } + pub := param instr, _, err = ctx.Next() if err != nil || instr != opcode.PUSHNULL { - return false + return nil, false } instr, param, err = ctx.Next() if err != nil || instr != opcode.SYSCALL || binary.LittleEndian.Uint32(param) != verifyInteropID { - return false + return nil, false } - return true + return pub, true } // IsStandardContract checks whether the passed script is a signature or diff --git a/pkg/vm/contract_checks_test.go b/pkg/vm/contract_checks_test.go index 88eb1aeab..29146c4f4 100644 --- a/pkg/vm/contract_checks_test.go +++ b/pkg/vm/contract_checks_test.go @@ -25,6 +25,15 @@ func testSignatureContract() []byte { return prog } +func TestParseSignatureContract(t *testing.T) { + prog := testSignatureContract() + pub := randomBytes(33) + copy(prog[2:], pub) + actual, ok := ParseSignatureContract(prog) + require.True(t, ok) + require.Equal(t, pub, actual) +} + func TestIsSignatureContract(t *testing.T) { t.Run("valid contract", func(t *testing.T) { prog := testSignatureContract()