Merge pull request #917 from nspcc-dev/feature/crypto

vm: remove crypto-related opcodes
This commit is contained in:
Roman Khimov 2020-04-29 21:52:30 +03:00 committed by GitHub
commit fda943b5cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 90 additions and 110 deletions

View file

@ -13,7 +13,6 @@ var (
// Go language builtin functions and custom builtin utility functions. // Go language builtin functions and custom builtin utility functions.
builtinFuncs = []string{ builtinFuncs = []string{
"len", "append", "SHA256", "len", "append", "SHA256",
"SHA1", "Hash256", "Hash160",
"AppCall", "AppCall",
"FromAddress", "Equals", "FromAddress", "Equals",
"panic", "panic",

View file

@ -1065,9 +1065,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
} }
emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)}) emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)})
case "SHA256": case "SHA256":
emit.Opcode(c.prog.BinWriter, opcode.SHA256) emit.Syscall(c.prog.BinWriter, "Neo.Crypto.SHA256")
case "SHA1":
emit.Opcode(c.prog.BinWriter, opcode.SHA1)
case "AppCall": case "AppCall":
numArgs := len(expr.Args) - 1 numArgs := len(expr.Args) - 1
c.emitReverse(numArgs) c.emitReverse(numArgs)

View file

@ -2,6 +2,11 @@ package compiler_test
import ( import (
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/stretchr/testify/require"
) )
func TestSHA256(t *testing.T) { func TestSHA256(t *testing.T) {
@ -16,20 +21,12 @@ func TestSHA256(t *testing.T) {
return hash return hash
} }
` `
eval(t, src, []byte{0x2a, 0xa, 0xb7, 0x32, 0xb4, 0xe9, 0xd8, 0x5e, 0xf7, 0xdc, 0x25, 0x30, 0x3b, 0x64, 0xab, 0x52, 0x7c, 0x25, 0xa4, 0xd7, 0x78, 0x15, 0xeb, 0xb5, 0x79, 0xf3, 0x96, 0xec, 0x6c, 0xac, 0xca, 0xd3}) v := vmAndCompile(t, src)
} ic := &interop.Context{Trigger: trigger.Verification}
v.RegisterInteropGetter(crypto.GetInterop(ic))
require.NoError(t, v.Run())
require.True(t, v.Estack().Len() >= 1)
func TestSHA1(t *testing.T) { h := []byte{0x2a, 0xa, 0xb7, 0x32, 0xb4, 0xe9, 0xd8, 0x5e, 0xf7, 0xdc, 0x25, 0x30, 0x3b, 0x64, 0xab, 0x52, 0x7c, 0x25, 0xa4, 0xd7, 0x78, 0x15, 0xeb, 0xb5, 0x79, 0xf3, 0x96, 0xec, 0x6c, 0xac, 0xca, 0xd3}
src := ` require.Equal(t, h, v.PopResult())
package foo
import (
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
)
func Main() []byte {
src := []byte{0x97}
hash := crypto.SHA1(src)
return hash
}
`
eval(t, src, []byte{0xfa, 0x13, 0x8a, 0xe3, 0x56, 0xd3, 0x5c, 0x8d, 0x77, 0x8, 0x3c, 0x40, 0x6a, 0x5b, 0xe7, 0x37, 0x45, 0x64, 0x3a, 0xae})
} }

View file

@ -25,10 +25,6 @@ func getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) util.Fixed8 {
case opcode.SYSCALL: case opcode.SYSCALL:
interopID := vm.GetInteropID(parameter) interopID := vm.GetInteropID(parameter)
return getSyscallPrice(v, interopID) return getSyscallPrice(v, interopID)
case opcode.SHA1, opcode.SHA256:
return toFixed8(10)
case opcode.HASH160, opcode.HASH256:
return toFixed8(20)
default: default:
return toFixed8(1) return toFixed8(1)
} }

View file

@ -0,0 +1,15 @@
package crypto
import (
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/vm"
)
// Sha256 returns sha256 hash of the data.
func Sha256(ic *interop.Context, v *vm.VM) error {
msg := getMessage(ic, v.Estack().Pop().Item())
h := hash.Sha256(msg).BytesBE()
v.Estack().PushVal(h)
return nil
}

View file

@ -0,0 +1,30 @@
package crypto
import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSHA256(t *testing.T) {
// 0x0100 hashes to 47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254
res := "47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254"
buf := io.NewBufBinWriter()
emit.Bytes(buf.BinWriter, []byte{1, 0})
emit.Syscall(buf.BinWriter, "Neo.Crypto.SHA256")
prog := buf.Bytes()
v := vm.New()
ic := &interop.Context{Trigger: trigger.Verification}
v.RegisterInteropGetter(GetInterop(ic))
v.Load(prog)
require.NoError(t, v.Run())
assert.Equal(t, 1, v.Estack().Len())
assert.Equal(t, res, hex.EncodeToString(v.Estack().Pop().Bytes()))
}

View file

@ -9,6 +9,7 @@ import (
var ( var (
ecdsaVerifyID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaVerify")) ecdsaVerifyID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaVerify"))
ecdsaCheckMultisigID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaCheckMultiSig")) ecdsaCheckMultisigID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaCheckMultiSig"))
sha256ID = emit.InteropNameToID([]byte("Neo.Crypto.SHA256"))
) )
// GetInterop returns interop getter for crypto-related stuff. // GetInterop returns interop getter for crypto-related stuff.
@ -27,6 +28,12 @@ func GetInterop(ic *interop.Context) func(uint32) *vm.InteropFuncPrice {
return ECDSACheckMultisig(ic, v) return ECDSACheckMultisig(ic, v)
}, },
} }
case sha256ID:
return &vm.InteropFuncPrice{
Func: func(v *vm.VM) error {
return Sha256(ic, v)
},
}
default: default:
return nil return nil
} }

View file

@ -147,6 +147,7 @@ var neoInterops = []interop.Function{
{Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0}, {Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0},
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1}, {Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
{Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1}, {Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},
{Name: "Neo.Enumerator.Concat", Func: enumerator.Concat, Price: 1}, {Name: "Neo.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
{Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1}, {Name: "Neo.Enumerator.Create", Func: enumerator.Create, Price: 1},
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1}, {Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},

View file

@ -3,11 +3,6 @@ package crypto
// Package crypto provides function signatures that can be used inside // Package crypto provides function signatures that can be used inside
// smart contracts that are written in the neo-go framework. // smart contracts that are written in the neo-go framework.
// SHA1 computes the sha1 hash of b.
func SHA1(b []byte) []byte {
return nil
}
// SHA256 computes the sha256 hash of b. // SHA256 computes the sha256 hash of b.
func SHA256(b []byte) []byte { func SHA256(b []byte) []byte {
return nil return nil

View file

@ -131,15 +131,6 @@ const (
MAX Opcode = 0xA4 MAX Opcode = 0xA4
WITHIN Opcode = 0xA5 WITHIN Opcode = 0xA5
// Crypto
SHA1 Opcode = 0xA7
SHA256 Opcode = 0xA8
HASH160 Opcode = 0xA9
HASH256 Opcode = 0xAA
CHECKSIG Opcode = 0xAC
VERIFY Opcode = 0xAD
CHECKMULTISIG Opcode = 0xAE
// Advanced data structures (arrays, structures, maps) // Advanced data structures (arrays, structures, maps)
PACK Opcode = 0xC0 PACK Opcode = 0xC0
UNPACK Opcode = 0xC1 UNPACK Opcode = 0xC1

View file

@ -114,13 +114,6 @@ func _() {
_ = x[MIN-163] _ = x[MIN-163]
_ = x[MAX-164] _ = x[MAX-164]
_ = x[WITHIN-165] _ = x[WITHIN-165]
_ = x[SHA1-167]
_ = x[SHA256-168]
_ = x[HASH160-169]
_ = x[HASH256-170]
_ = x[CHECKSIG-172]
_ = x[VERIFY-173]
_ = x[CHECKMULTISIG-174]
_ = x[PACK-192] _ = x[PACK-192]
_ = x[UNPACK-193] _ = x[UNPACK-193]
_ = x[NEWARRAY0-194] _ = x[NEWARRAY0-194]
@ -146,7 +139,7 @@ func _() {
_ = x[THROWIFNOT-241] _ = x[THROWIFNOT-241]
} }
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT" const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
var _Opcode_map = map[Opcode]string{ var _Opcode_map = map[Opcode]string{
0: _Opcode_name[0:8], 0: _Opcode_name[0:8],
@ -253,36 +246,29 @@ var _Opcode_map = map[Opcode]string{
163: _Opcode_name[548:551], 163: _Opcode_name[548:551],
164: _Opcode_name[551:554], 164: _Opcode_name[551:554],
165: _Opcode_name[554:560], 165: _Opcode_name[554:560],
167: _Opcode_name[560:564], 192: _Opcode_name[560:564],
168: _Opcode_name[564:570], 193: _Opcode_name[564:570],
169: _Opcode_name[570:577], 194: _Opcode_name[570:579],
170: _Opcode_name[577:584], 195: _Opcode_name[579:587],
172: _Opcode_name[584:592], 196: _Opcode_name[587:596],
173: _Opcode_name[592:598], 197: _Opcode_name[596:606],
174: _Opcode_name[598:611], 198: _Opcode_name[606:615],
192: _Opcode_name[611:615], 200: _Opcode_name[615:621],
193: _Opcode_name[615:621], 202: _Opcode_name[621:625],
194: _Opcode_name[621:630], 203: _Opcode_name[625:631],
195: _Opcode_name[630:638], 204: _Opcode_name[631:635],
196: _Opcode_name[638:647], 205: _Opcode_name[635:641],
197: _Opcode_name[647:657], 206: _Opcode_name[641:649],
198: _Opcode_name[657:666], 207: _Opcode_name[649:655],
200: _Opcode_name[666:672], 208: _Opcode_name[655:662],
202: _Opcode_name[672:676], 209: _Opcode_name[662:674],
203: _Opcode_name[676:682], 210: _Opcode_name[674:680],
204: _Opcode_name[682:686], 211: _Opcode_name[680:690],
205: _Opcode_name[686:692], 216: _Opcode_name[690:696],
206: _Opcode_name[692:700], 217: _Opcode_name[696:702],
207: _Opcode_name[700:706], 219: _Opcode_name[702:709],
208: _Opcode_name[706:713], 240: _Opcode_name[709:714],
209: _Opcode_name[713:725], 241: _Opcode_name[714:724],
210: _Opcode_name[725:731],
211: _Opcode_name[731:741],
216: _Opcode_name[741:747],
217: _Opcode_name[747:753],
219: _Opcode_name[753:760],
240: _Opcode_name[760:765],
241: _Opcode_name[765:775],
} }
func (i Opcode) String() string { func (i Opcode) String() string {

View file

@ -1,7 +1,6 @@
package vm package vm
import ( import (
"crypto/sha1"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -11,7 +10,6 @@ import (
"text/tabwriter" "text/tabwriter"
"unicode/utf8" "unicode/utf8"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
@ -1314,17 +1312,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
panic("wrong collection type") panic("wrong collection type")
} }
// Cryptographic operations.
case opcode.SHA1:
b := v.estack.Pop().Bytes()
sha := sha1.New()
sha.Write(b)
v.estack.PushVal(sha.Sum(nil))
case opcode.SHA256:
b := v.estack.Pop().Bytes()
v.estack.PushVal(hash.Sha256(b).BytesBE())
case opcode.NOP: case opcode.NOP:
// unlucky ^^ // unlucky ^^

View file

@ -3037,28 +3037,6 @@ func TestDupBool(t *testing.T) {
assert.Equal(t, true, vm.estack.Pop().Bool()) assert.Equal(t, true, vm.estack.Pop().Bool())
} }
func TestSHA1(t *testing.T) {
// 0x0100 hashes to 0e356ba505631fbf715758bed27d503f8b260e3a
res := "0e356ba505631fbf715758bed27d503f8b260e3a"
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
opcode.SHA1)
vm := load(prog)
runVM(t, vm)
assert.Equal(t, 1, vm.estack.Len())
assert.Equal(t, res, hex.EncodeToString(vm.estack.Pop().Bytes()))
}
func TestSHA256(t *testing.T) {
// 0x0100 hashes to 47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254
res := "47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254"
prog := makeProgram(opcode.PUSHDATA1, 2, 1, 0,
opcode.SHA256)
vm := load(prog)
runVM(t, vm)
assert.Equal(t, 1, vm.estack.Len())
assert.Equal(t, res, hex.EncodeToString(vm.estack.Pop().Bytes()))
}
var opcodesTestCases = map[opcode.Opcode][]struct { var opcodesTestCases = map[opcode.Opcode][]struct {
name string name string
args []interface{} args []interface{}