package vm import ( "encoding/binary" "testing" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func testSignatureContract() []byte { prog := make([]byte, 41) prog[0] = byte(opcode.PUSHDATA1) prog[1] = 33 prog[35] = byte(opcode.PUSHNULL) prog[36] = byte(opcode.SYSCALL) binary.LittleEndian.PutUint32(prog[37:], verifyInteropID) return prog } func TestIsSignatureContract(t *testing.T) { t.Run("valid contract", func(t *testing.T) { prog := testSignatureContract() assert.True(t, IsSignatureContract(prog)) assert.True(t, IsStandardContract(prog)) }) t.Run("invalid interop ID", func(t *testing.T) { prog := testSignatureContract() binary.LittleEndian.PutUint32(prog[37:], ^verifyInteropID) assert.False(t, IsSignatureContract(prog)) assert.False(t, IsStandardContract(prog)) }) t.Run("invalid pubkey size", func(t *testing.T) { prog := testSignatureContract() prog[1] = 32 assert.False(t, IsSignatureContract(prog)) assert.False(t, IsStandardContract(prog)) }) t.Run("no PUSHNULL", func(t *testing.T) { prog := testSignatureContract() prog[35] = byte(opcode.PUSH1) assert.False(t, IsSignatureContract(prog)) assert.False(t, IsStandardContract(prog)) }) t.Run("invalid length", func(t *testing.T) { prog := testSignatureContract() prog = append(prog, 0) assert.False(t, IsSignatureContract(prog)) assert.False(t, IsStandardContract(prog)) }) } func testMultisigContract(t *testing.T, n, m int) []byte { pubs := make(keys.PublicKeys, n) for i := 0; i < n; i++ { priv, err := keys.NewPrivateKey() require.NoError(t, err) pubs[i] = priv.PublicKey() } prog, err := smartcontract.CreateMultiSigRedeemScript(m, pubs) require.NoError(t, err) return prog } func TestIsMultiSigContract(t *testing.T) { t.Run("valid contract", func(t *testing.T) { prog := testMultisigContract(t, 2, 2) assert.True(t, IsMultiSigContract(prog)) assert.True(t, IsStandardContract(prog)) }) t.Run("0-length", func(t *testing.T) { assert.False(t, IsMultiSigContract([]byte{})) }) t.Run("invalid param", func(t *testing.T) { prog := []byte{byte(opcode.PUSHDATA1), 10} assert.False(t, IsMultiSigContract(prog)) }) t.Run("too many keys", func(t *testing.T) { prog := testMultisigContract(t, 1025, 1) assert.False(t, IsMultiSigContract(prog)) }) t.Run("invalid interop ID", func(t *testing.T) { prog := testMultisigContract(t, 2, 2) prog[len(prog)-4] ^= 0xFF assert.False(t, IsMultiSigContract(prog)) }) t.Run("no PUSHNULL", func(t *testing.T) { prog := testMultisigContract(t, 2, 2) prog[len(prog)-6] ^= 0xFF assert.False(t, IsMultiSigContract(prog)) }) t.Run("invalid keys number", func(t *testing.T) { prog := testMultisigContract(t, 2, 2) prog[len(prog)-7] = byte(opcode.PUSH3) assert.False(t, IsMultiSigContract(prog)) }) t.Run("invalid length", func(t *testing.T) { prog := testMultisigContract(t, 2, 2) prog = append(prog, 0) assert.False(t, IsMultiSigContract(prog)) }) }