vm: remove crypto-related opcodes
All cryptography has moved to interops in NEO3. There is no SHA256 interop RN, but it is to appear later. Closes #777.
This commit is contained in:
parent
c1aa96d614
commit
519b31a704
13 changed files with 90 additions and 110 deletions
|
@ -13,7 +13,6 @@ var (
|
|||
// Go language builtin functions and custom builtin utility functions.
|
||||
builtinFuncs = []string{
|
||||
"len", "append", "SHA256",
|
||||
"SHA1", "Hash256", "Hash160",
|
||||
"AppCall",
|
||||
"FromAddress", "Equals",
|
||||
"panic",
|
||||
|
|
|
@ -1065,9 +1065,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
|||
}
|
||||
emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)})
|
||||
case "SHA256":
|
||||
emit.Opcode(c.prog.BinWriter, opcode.SHA256)
|
||||
case "SHA1":
|
||||
emit.Opcode(c.prog.BinWriter, opcode.SHA1)
|
||||
emit.Syscall(c.prog.BinWriter, "Neo.Crypto.SHA256")
|
||||
case "AppCall":
|
||||
numArgs := len(expr.Args) - 1
|
||||
c.emitReverse(numArgs)
|
||||
|
|
|
@ -2,6 +2,11 @@ package compiler_test
|
|||
|
||||
import (
|
||||
"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) {
|
||||
|
@ -16,20 +21,12 @@ func TestSHA256(t *testing.T) {
|
|||
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) {
|
||||
src := `
|
||||
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})
|
||||
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}
|
||||
require.Equal(t, h, v.PopResult())
|
||||
}
|
||||
|
|
|
@ -25,10 +25,6 @@ func getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) util.Fixed8 {
|
|||
case opcode.SYSCALL:
|
||||
interopID := vm.GetInteropID(parameter)
|
||||
return getSyscallPrice(v, interopID)
|
||||
case opcode.SHA1, opcode.SHA256:
|
||||
return toFixed8(10)
|
||||
case opcode.HASH160, opcode.HASH256:
|
||||
return toFixed8(20)
|
||||
default:
|
||||
return toFixed8(1)
|
||||
}
|
||||
|
|
15
pkg/core/interop/crypto/hash.go
Normal file
15
pkg/core/interop/crypto/hash.go
Normal 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
|
||||
}
|
30
pkg/core/interop/crypto/hash_test.go
Normal file
30
pkg/core/interop/crypto/hash_test.go
Normal 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()))
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
var (
|
||||
ecdsaVerifyID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaVerify"))
|
||||
ecdsaCheckMultisigID = emit.InteropNameToID([]byte("Neo.Crypto.ECDsaCheckMultiSig"))
|
||||
sha256ID = emit.InteropNameToID([]byte("Neo.Crypto.SHA256"))
|
||||
)
|
||||
|
||||
// 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)
|
||||
},
|
||||
}
|
||||
case sha256ID:
|
||||
return &vm.InteropFuncPrice{
|
||||
Func: func(v *vm.VM) error {
|
||||
return Sha256(ic, v)
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ var neoInterops = []interop.Function{
|
|||
{Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0},
|
||||
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, 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.Create", Func: enumerator.Create, Price: 1},
|
||||
{Name: "Neo.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
||||
|
|
|
@ -3,11 +3,6 @@ package crypto
|
|||
// Package crypto provides function signatures that can be used inside
|
||||
// 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.
|
||||
func SHA256(b []byte) []byte {
|
||||
return nil
|
||||
|
|
|
@ -131,15 +131,6 @@ const (
|
|||
MAX Opcode = 0xA4
|
||||
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)
|
||||
PACK Opcode = 0xC0
|
||||
UNPACK Opcode = 0xC1
|
||||
|
|
|
@ -114,13 +114,6 @@ func _() {
|
|||
_ = x[MIN-163]
|
||||
_ = x[MAX-164]
|
||||
_ = 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[UNPACK-193]
|
||||
_ = x[NEWARRAY0-194]
|
||||
|
@ -146,7 +139,7 @@ func _() {
|
|||
_ = x[THROWIFNOT-241]
|
||||
}
|
||||
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
|
||||
|
||||
var _Opcode_map = map[Opcode]string{
|
||||
0: _Opcode_name[0:8],
|
||||
|
@ -253,36 +246,29 @@ var _Opcode_map = map[Opcode]string{
|
|||
163: _Opcode_name[548:551],
|
||||
164: _Opcode_name[551:554],
|
||||
165: _Opcode_name[554:560],
|
||||
167: _Opcode_name[560:564],
|
||||
168: _Opcode_name[564:570],
|
||||
169: _Opcode_name[570:577],
|
||||
170: _Opcode_name[577:584],
|
||||
172: _Opcode_name[584:592],
|
||||
173: _Opcode_name[592:598],
|
||||
174: _Opcode_name[598:611],
|
||||
192: _Opcode_name[611:615],
|
||||
193: _Opcode_name[615:621],
|
||||
194: _Opcode_name[621:630],
|
||||
195: _Opcode_name[630:638],
|
||||
196: _Opcode_name[638:647],
|
||||
197: _Opcode_name[647:657],
|
||||
198: _Opcode_name[657:666],
|
||||
200: _Opcode_name[666:672],
|
||||
202: _Opcode_name[672:676],
|
||||
203: _Opcode_name[676:682],
|
||||
204: _Opcode_name[682:686],
|
||||
205: _Opcode_name[686:692],
|
||||
206: _Opcode_name[692:700],
|
||||
207: _Opcode_name[700:706],
|
||||
208: _Opcode_name[706:713],
|
||||
209: _Opcode_name[713:725],
|
||||
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],
|
||||
192: _Opcode_name[560:564],
|
||||
193: _Opcode_name[564:570],
|
||||
194: _Opcode_name[570:579],
|
||||
195: _Opcode_name[579:587],
|
||||
196: _Opcode_name[587:596],
|
||||
197: _Opcode_name[596:606],
|
||||
198: _Opcode_name[606:615],
|
||||
200: _Opcode_name[615:621],
|
||||
202: _Opcode_name[621:625],
|
||||
203: _Opcode_name[625:631],
|
||||
204: _Opcode_name[631:635],
|
||||
205: _Opcode_name[635:641],
|
||||
206: _Opcode_name[641:649],
|
||||
207: _Opcode_name[649:655],
|
||||
208: _Opcode_name[655:662],
|
||||
209: _Opcode_name[662:674],
|
||||
210: _Opcode_name[674:680],
|
||||
211: _Opcode_name[680:690],
|
||||
216: _Opcode_name[690:696],
|
||||
217: _Opcode_name[696:702],
|
||||
219: _Opcode_name[702:709],
|
||||
240: _Opcode_name[709:714],
|
||||
241: _Opcode_name[714:724],
|
||||
}
|
||||
|
||||
func (i Opcode) String() string {
|
||||
|
|
13
pkg/vm/vm.go
13
pkg/vm/vm.go
|
@ -1,7 +1,6 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -11,7 +10,6 @@ import (
|
|||
"text/tabwriter"
|
||||
"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/util"
|
||||
"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")
|
||||
}
|
||||
|
||||
// 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:
|
||||
// unlucky ^^
|
||||
|
||||
|
|
|
@ -3037,28 +3037,6 @@ func TestDupBool(t *testing.T) {
|
|||
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 {
|
||||
name string
|
||||
args []interface{}
|
||||
|
|
Loading…
Reference in a new issue