diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 45deb1d85..cd21fd72c 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -12,6 +12,7 @@ import ( "sort" "strings" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/vm" @@ -1313,7 +1314,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { emit.Opcode(c.prog.BinWriter, opcode.THROW) } else if isString(c.typeInfo.Types[arg].Type) { ast.Walk(c, arg) - emit.Syscall(c.prog.BinWriter, "System.Runtime.Log") + emit.Syscall(c.prog.BinWriter, interopnames.SystemRuntimeLog) emit.Opcode(c.prog.BinWriter, opcode.THROW) } else { c.prog.Err = errors.New("panic should have string or nil argument") diff --git a/pkg/compiler/panic_test.go b/pkg/compiler/panic_test.go index 646bca04e..54c51b9d8 100644 --- a/pkg/compiler/panic_test.go +++ b/pkg/compiler/panic_test.go @@ -6,8 +6,8 @@ import ( "math/big" "testing" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/vm" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/stretchr/testify/require" ) @@ -56,7 +56,7 @@ func getPanicSource(need bool, message string) string { } func getLogHandler(logs *[]string) vm.SyscallHandler { - logID := emit.InteropNameToID([]byte("System.Runtime.Log")) + logID := interopnames.ToID([]byte(interopnames.SystemRuntimeLog)) return func(v *vm.VM, id uint32) error { if id != logID { return errors.New("syscall not found") diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index 9f643bdd8..7f8a34275 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -1,5 +1,7 @@ package compiler +import "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" + // Syscall represents NEO or System syscall API with flag for proper AVM generation type Syscall struct { API string @@ -9,80 +11,80 @@ type Syscall struct { // All lists are sorted, keep 'em this way, please. var syscalls = map[string]map[string]Syscall{ "binary": { - "Base64Decode": {"System.Binary.Base64Decode", false}, - "Base64Encode": {"System.Binary.Base64Encode", false}, - "Deserialize": {"System.Binary.Deserialize", false}, - "Serialize": {"System.Binary.Serialize", false}, + "Base64Decode": {interopnames.SystemBinaryBase64Decode, false}, + "Base64Encode": {interopnames.SystemBinaryBase64Encode, false}, + "Deserialize": {interopnames.SystemBinaryDeserialize, false}, + "Serialize": {interopnames.SystemBinarySerialize, false}, }, "blockchain": { - "GetBlock": {"System.Blockchain.GetBlock", true}, - "GetContract": {"System.Blockchain.GetContract", true}, - "GetHeight": {"System.Blockchain.GetHeight", false}, - "GetTransaction": {"System.Blockchain.GetTransaction", true}, - "GetTransactionFromBlock": {"System.Blockchain.GetTransactionFromBlock", false}, - "GetTransactionHeight": {"System.Blockchain.GetTransactionHeight", false}, + "GetBlock": {interopnames.SystemBlockchainGetBlock, true}, + "GetContract": {interopnames.SystemBlockchainGetContract, true}, + "GetHeight": {interopnames.SystemBlockchainGetHeight, false}, + "GetTransaction": {interopnames.SystemBlockchainGetTransaction, true}, + "GetTransactionFromBlock": {interopnames.SystemBlockchainGetTransactionFromBlock, false}, + "GetTransactionHeight": {interopnames.SystemBlockchainGetTransactionHeight, false}, }, "contract": { - "Create": {"System.Contract.Create", true}, - "CreateStandardAccount": {"System.Contract.CreateStandardAccount", false}, - "Destroy": {"System.Contract.Destroy", false}, - "IsStandard": {"System.Contract.IsStandard", false}, - "GetCallFlags": {"System.Contract.GetCallFlags", false}, - "Update": {"System.Contract.Update", false}, + "Create": {interopnames.SystemContractCreate, true}, + "CreateStandardAccount": {interopnames.SystemContractCreateStandardAccount, false}, + "Destroy": {interopnames.SystemContractDestroy, false}, + "IsStandard": {interopnames.SystemContractIsStandard, false}, + "GetCallFlags": {interopnames.SystemContractGetCallFlags, false}, + "Update": {interopnames.SystemContractUpdate, false}, }, "crypto": { - "ECDsaSecp256k1Verify": {"Neo.Crypto.VerifyWithECDsaSecp256k1", false}, - "ECDSASecp256k1CheckMultisig": {"Neo.Crypto.CheckMultisigWithECDsaSecp256k1", false}, - "ECDsaSecp256r1Verify": {"Neo.Crypto.VerifyWithECDsaSecp256r1", false}, - "ECDSASecp256r1CheckMultisig": {"Neo.Crypto.CheckMultisigWithECDsaSecp256r1", false}, - "RIPEMD160": {"Neo.Crypto.RIPEMD160", false}, - "SHA256": {"Neo.Crypto.SHA256", false}, + "ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, false}, + "ECDSASecp256k1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, false}, + "ECDsaSecp256r1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256r1, false}, + "ECDSASecp256r1CheckMultisig": {interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, false}, + "RIPEMD160": {interopnames.NeoCryptoRIPEMD160, false}, + "SHA256": {interopnames.NeoCryptoSHA256, false}, }, "enumerator": { - "Concat": {"System.Enumerator.Concat", false}, - "Create": {"System.Enumerator.Create", false}, - "Next": {"System.Enumerator.Next", false}, - "Value": {"System.Enumerator.Value", false}, + "Concat": {interopnames.SystemEnumeratorConcat, false}, + "Create": {interopnames.SystemEnumeratorCreate, false}, + "Next": {interopnames.SystemEnumeratorNext, false}, + "Value": {interopnames.SystemEnumeratorValue, false}, }, "engine": { - "AppCall": {"System.Contract.Call", false}, + "AppCall": {interopnames.SystemContractCall, false}, }, "iterator": { - "Concat": {"System.Iterator.Concat", false}, - "Create": {"System.Iterator.Create", false}, - "Key": {"System.Iterator.Key", false}, - "Keys": {"System.Iterator.Keys", false}, - "Next": {"System.Enumerator.Next", false}, - "Value": {"System.Enumerator.Value", false}, - "Values": {"System.Iterator.Values", false}, + "Concat": {interopnames.SystemIteratorConcat, false}, + "Create": {interopnames.SystemIteratorCreate, false}, + "Key": {interopnames.SystemIteratorKey, false}, + "Keys": {interopnames.SystemIteratorKeys, false}, + "Next": {interopnames.SystemEnumeratorNext, false}, + "Value": {interopnames.SystemEnumeratorValue, false}, + "Values": {interopnames.SystemIteratorValues, false}, }, "json": { - "Deserialize": {"System.Json.Deserialize", false}, - "Serialize": {"System.Json.Serialize", false}, + "Deserialize": {interopnames.SystemJSONDeserialize, false}, + "Serialize": {interopnames.SystemJSONSerialize, false}, }, "runtime": { - "GasLeft": {"System.Runtime.GasLeft", false}, - "GetInvocationCounter": {"System.Runtime.GetInvocationCounter", false}, - "GetCallingScriptHash": {"System.Runtime.GetCallingScriptHash", false}, - "GetEntryScriptHash": {"System.Runtime.GetEntryScriptHash", false}, - "GetExecutingScriptHash": {"System.Runtime.GetExecutingScriptHash", false}, - "GetNotifications": {"System.Runtime.GetNotifications", false}, - "GetScriptContainer": {"System.Runtime.GetScriptContainer", true}, - "GetTime": {"System.Runtime.GetTime", false}, - "GetTrigger": {"System.Runtime.GetTrigger", false}, - "CheckWitness": {"System.Runtime.CheckWitness", false}, - "Log": {"System.Runtime.Log", false}, - "Notify": {"System.Runtime.Notify", false}, - "Platform": {"System.Runtime.Platform", false}, + "GasLeft": {interopnames.SystemRuntimeGasLeft, false}, + "GetInvocationCounter": {interopnames.SystemRuntimeGetInvocationCounter, false}, + "GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, false}, + "GetEntryScriptHash": {interopnames.SystemRuntimeGetEntryScriptHash, false}, + "GetExecutingScriptHash": {interopnames.SystemRuntimeGetExecutingScriptHash, false}, + "GetNotifications": {interopnames.SystemRuntimeGetNotifications, false}, + "GetScriptContainer": {interopnames.SystemRuntimeGetScriptContainer, true}, + "GetTime": {interopnames.SystemRuntimeGetTime, false}, + "GetTrigger": {interopnames.SystemRuntimeGetTrigger, false}, + "CheckWitness": {interopnames.SystemRuntimeCheckWitness, false}, + "Log": {interopnames.SystemRuntimeLog, false}, + "Notify": {interopnames.SystemRuntimeNotify, false}, + "Platform": {interopnames.SystemRuntimePlatform, false}, }, "storage": { - "ConvertContextToReadOnly": {"System.Storage.AsReadOnly", false}, - "Delete": {"System.Storage.Delete", false}, - "Find": {"System.Storage.Find", false}, - "Get": {"System.Storage.Get", false}, - "GetContext": {"System.Storage.GetContext", false}, - "GetReadOnlyContext": {"System.Storage.GetReadOnlyContext", false}, - "Put": {"System.Storage.Put", false}, - "PutEx": {"System.Storage.PutEx", false}, + "ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, false}, + "Delete": {interopnames.SystemStorageDelete, false}, + "Find": {interopnames.SystemStorageFind, false}, + "Get": {interopnames.SystemStorageGet, false}, + "GetContext": {interopnames.SystemStorageGetContext, false}, + "GetReadOnlyContext": {interopnames.SystemStorageGetReadOnlyContext, false}, + "Put": {interopnames.SystemStoragePut, false}, + "PutEx": {interopnames.SystemStoragePutEx, false}, }, } diff --git a/pkg/compiler/verify_test.go b/pkg/compiler/verify_test.go index 329f3e016..a1793fce8 100644 --- a/pkg/compiler/verify_test.go +++ b/pkg/compiler/verify_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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" ) @@ -19,7 +19,7 @@ func TestVerifyGood(t *testing.T) { src := getVerifyProg(pub, sig, msg) v, p := vmAndCompileInterop(t, src) - p.interops[emit.InteropNameToID([]byte("Neo.Crypto.VerifyWithECDsaSecp256r1"))] = func(v *vm.VM) error { + p.interops[interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256r1))] = func(v *vm.VM) error { assert.Equal(t, msg, v.Estack().Pop().Bytes()) assert.Equal(t, pub, v.Estack().Pop().Bytes()) assert.Equal(t, sig, v.Estack().Pop().Bytes()) diff --git a/pkg/compiler/vm_test.go b/pkg/compiler/vm_test.go index d4a317d36..19be8744b 100644 --- a/pkg/compiler/vm_test.go +++ b/pkg/compiler/vm_test.go @@ -7,11 +7,11 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/compiler" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/vm" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -109,10 +109,10 @@ func newStoragePlugin() *storagePlugin { mem: make(map[string][]byte), interops: make(map[uint32]func(v *vm.VM) error), } - s.interops[emit.InteropNameToID([]byte("System.Storage.Get"))] = s.Get - s.interops[emit.InteropNameToID([]byte("System.Storage.Put"))] = s.Put - s.interops[emit.InteropNameToID([]byte("System.Storage.GetContext"))] = s.GetContext - s.interops[emit.InteropNameToID([]byte("System.Runtime.Notify"))] = s.Notify + s.interops[interopnames.ToID([]byte(interopnames.SystemStorageGet))] = s.Get + s.interops[interopnames.ToID([]byte(interopnames.SystemStoragePut))] = s.Put + s.interops[interopnames.ToID([]byte(interopnames.SystemStorageGetContext))] = s.GetContext + s.interops[interopnames.ToID([]byte(interopnames.SystemRuntimeNotify))] = s.Notify return s } diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 7883ced7f..66d10bdc4 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -273,7 +274,7 @@ func TestSubscriptions(t *testing.T) { script := io.NewBufBinWriter() emit.Bytes(script.BinWriter, []byte("yay!")) - emit.Syscall(script.BinWriter, "System.Runtime.Notify") + emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) require.NoError(t, script.Err) txGood1 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) txGood1.Signers = []transaction.Signer{{Account: neoOwner}} @@ -284,7 +285,7 @@ func TestSubscriptions(t *testing.T) { // Reset() reuses the script buffer and we need to keep scripts. script = io.NewBufBinWriter() emit.Bytes(script.BinWriter, []byte("nay!")) - emit.Syscall(script.BinWriter, "System.Runtime.Notify") + emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) emit.Opcode(script.BinWriter, opcode.THROW) require.NoError(t, script.Err) txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) @@ -295,7 +296,7 @@ func TestSubscriptions(t *testing.T) { script = io.NewBufBinWriter() emit.Bytes(script.BinWriter, []byte("yay! yay! yay!")) - emit.Syscall(script.BinWriter, "System.Runtime.Notify") + emit.Syscall(script.BinWriter, interopnames.SystemRuntimeNotify) require.NoError(t, script.Err) txGood2 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0) txGood2.Signers = []transaction.Signer{{Account: neoOwner}} diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index a4f9b86ef..36a2f36c5 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -14,6 +14,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/block" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -239,7 +240,7 @@ func TestCreateBasicChain(t *testing.T) { require.NoError(t, err) emit.Bytes(script.BinWriter, bs) emit.Bytes(script.BinWriter, avm) - emit.Syscall(script.BinWriter, "System.Contract.Create") + emit.Syscall(script.BinWriter, interopnames.SystemContractCreate) txScript := script.Bytes() txDeploy := transaction.New(testchain.Network(), txScript, 100*native.GASFactor) diff --git a/pkg/core/interop/callback/callback.go b/pkg/core/interop/callback/callback.go index 6ea266341..754616bb4 100644 --- a/pkg/core/interop/callback/callback.go +++ b/pkg/core/interop/callback/callback.go @@ -4,8 +4,8 @@ import ( "errors" "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/vm" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -27,7 +27,7 @@ func Invoke(ic *interop.Context) error { cb.LoadContext(ic.VM, args) switch t := cb.(type) { case *MethodCallback: - id := emit.InteropNameToID([]byte("System.Contract.Call")) + id := interopnames.ToID([]byte(interopnames.SystemContractCall)) return ic.SyscallHandler(ic.VM, id) case *SyscallCallback: return ic.SyscallHandler(ic.VM, t.desc.ID) diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index ad1dbb958..e1db69a20 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/blockchainer" "github.com/nspcc-dev/neo-go/pkg/core/dao" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto" @@ -110,7 +111,7 @@ func NewContractMD(name string) *ContractMD { w := io.NewBufBinWriter() emit.String(w.BinWriter, c.Name) - emit.Syscall(w.BinWriter, "Neo.Native.Call") + emit.Syscall(w.BinWriter, interopnames.NeoNativeCall) c.Script = w.Bytes() c.Hash = hash.Hash160(c.Script) diff --git a/pkg/core/interop/crypto/hash_test.go b/pkg/core/interop/crypto/hash_test.go index 9f4bdc22c..4d87d27d5 100644 --- a/pkg/core/interop/crypto/hash_test.go +++ b/pkg/core/interop/crypto/hash_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "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/emit" @@ -17,7 +18,7 @@ func TestSHA256(t *testing.T) { res := "47dc540c94ceb704a23875c11273e16bb0b8a87aed84de911f2133568115f254" buf := io.NewBufBinWriter() emit.Bytes(buf.BinWriter, []byte{1, 0}) - emit.Syscall(buf.BinWriter, "Neo.Crypto.SHA256") + emit.Syscall(buf.BinWriter, interopnames.NeoCryptoSHA256) prog := buf.Bytes() ic := &interop.Context{Trigger: trigger.Verification} Register(ic) @@ -33,7 +34,7 @@ func TestRIPEMD160(t *testing.T) { res := "213492c0c6fc5d61497cf17249dd31cd9964b8a3" buf := io.NewBufBinWriter() emit.Bytes(buf.BinWriter, []byte{1, 0}) - emit.Syscall(buf.BinWriter, "Neo.Crypto.RIPEMD160") + emit.Syscall(buf.BinWriter, interopnames.NeoCryptoRIPEMD160) prog := buf.Bytes() ic := &interop.Context{Trigger: trigger.Verification} Register(ic) diff --git a/pkg/core/interop/crypto/interop.go b/pkg/core/interop/crypto/interop.go index a27850577..74e7815df 100644 --- a/pkg/core/interop/crypto/interop.go +++ b/pkg/core/interop/crypto/interop.go @@ -2,16 +2,16 @@ package crypto import ( "github.com/nspcc-dev/neo-go/pkg/core/interop" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" ) var ( - ecdsaSecp256r1VerifyID = emit.InteropNameToID([]byte("Neo.Crypto.VerifyWithECDsaSecp256r1")) - ecdsaSecp256k1VerifyID = emit.InteropNameToID([]byte("Neo.Crypto.VerifyWithECDsaSecp256k1")) - ecdsaSecp256r1CheckMultisigID = emit.InteropNameToID([]byte("Neo.Crypto.CheckMultisigWithECDsaSecp256r1")) - ecdsaSecp256k1CheckMultisigID = emit.InteropNameToID([]byte("Neo.Crypto.CheckMultisigWithECDsaSecp256k1")) - sha256ID = emit.InteropNameToID([]byte("Neo.Crypto.SHA256")) - ripemd160ID = emit.InteropNameToID([]byte("Neo.Crypto.RIPEMD160")) + ecdsaSecp256r1VerifyID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256r1)) + ecdsaSecp256k1VerifyID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256k1)) + ecdsaSecp256r1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)) + ecdsaSecp256k1CheckMultisigID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1)) + sha256ID = interopnames.ToID([]byte(interopnames.NeoCryptoSHA256)) + ripemd160ID = interopnames.ToID([]byte(interopnames.NeoCryptoRIPEMD160)) ) var cryptoInterops = []interop.Function{ diff --git a/pkg/core/interop/interopnames/convert.go b/pkg/core/interop/interopnames/convert.go new file mode 100644 index 000000000..54aa0f09c --- /dev/null +++ b/pkg/core/interop/interopnames/convert.go @@ -0,0 +1,25 @@ +package interopnames + +import ( + "crypto/sha256" + "encoding/binary" + "errors" +) + +var errNotFound = errors.New("interop not found") + +// ToID returns an identificator of the method based on its name. +func ToID(name []byte) uint32 { + h := sha256.Sum256(name) + return binary.LittleEndian.Uint32(h[:4]) +} + +// FromID returns interop name from its id. +func FromID(id uint32) (string, error) { + for i := range names { + if id == ToID([]byte(names[i])) { + return names[i], nil + } + } + return "", errNotFound +} diff --git a/pkg/core/interop/interopnames/convert_test.go b/pkg/core/interop/interopnames/convert_test.go new file mode 100644 index 000000000..1ec2c1f21 --- /dev/null +++ b/pkg/core/interop/interopnames/convert_test.go @@ -0,0 +1,21 @@ +package interopnames + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFromID(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + id := ToID([]byte(names[0])) + name, err := FromID(id) + require.NoError(t, err) + require.Equal(t, names[0], name) + }) + t.Run("Invalid", func(t *testing.T) { + _, err := FromID(0x42424242) + require.True(t, errors.Is(err, errNotFound)) + }) +} diff --git a/pkg/core/interop/interopnames/names.go b/pkg/core/interop/interopnames/names.go new file mode 100644 index 000000000..01f36cdf1 --- /dev/null +++ b/pkg/core/interop/interopnames/names.go @@ -0,0 +1,132 @@ +package interopnames + +// Names of all used interops. +const ( + SystemBinaryBase64Decode = "System.Binary.Base64Decode" + SystemBinaryBase64Encode = "System.Binary.Base64Encode" + SystemBinaryDeserialize = "System.Binary.Deserialize" + SystemBinarySerialize = "System.Binary.Serialize" + SystemBlockchainGetBlock = "System.Blockchain.GetBlock" + SystemBlockchainGetContract = "System.Blockchain.GetContract" + SystemBlockchainGetHeight = "System.Blockchain.GetHeight" + SystemBlockchainGetTransaction = "System.Blockchain.GetTransaction" + SystemBlockchainGetTransactionFromBlock = "System.Blockchain.GetTransactionFromBlock" + SystemBlockchainGetTransactionHeight = "System.Blockchain.GetTransactionHeight" + SystemCallbackCreate = "System.Callback.Create" + SystemCallbackCreateFromMethod = "System.Callback.CreateFromMethod" + SystemCallbackCreateFromSyscall = "System.Callback.CreateFromSyscall" + SystemCallbackInvoke = "System.Callback.Invoke" + SystemContractCall = "System.Contract.Call" + SystemContractCallEx = "System.Contract.CallEx" + SystemContractCreate = "System.Contract.Create" + SystemContractCreateStandardAccount = "System.Contract.CreateStandardAccount" + SystemContractDestroy = "System.Contract.Destroy" + SystemContractIsStandard = "System.Contract.IsStandard" + SystemContractGetCallFlags = "System.Contract.GetCallFlags" + SystemContractUpdate = "System.Contract.Update" + SystemEnumeratorConcat = "System.Enumerator.Concat" + SystemEnumeratorCreate = "System.Enumerator.Create" + SystemEnumeratorNext = "System.Enumerator.Next" + SystemEnumeratorValue = "System.Enumerator.Value" + SystemIteratorConcat = "System.Iterator.Concat" + SystemIteratorCreate = "System.Iterator.Create" + SystemIteratorKey = "System.Iterator.Key" + SystemIteratorKeys = "System.Iterator.Keys" + SystemIteratorValues = "System.Iterator.Values" + SystemJSONDeserialize = "System.Json.Deserialize" + SystemJSONSerialize = "System.Json.Serialize" + SystemRuntimeCheckWitness = "System.Runtime.CheckWitness" + SystemRuntimeGasLeft = "System.Runtime.GasLeft" + SystemRuntimeGetCallingScriptHash = "System.Runtime.GetCallingScriptHash" + SystemRuntimeGetEntryScriptHash = "System.Runtime.GetEntryScriptHash" + SystemRuntimeGetExecutingScriptHash = "System.Runtime.GetExecutingScriptHash" + SystemRuntimeGetInvocationCounter = "System.Runtime.GetInvocationCounter" + SystemRuntimeGetNotifications = "System.Runtime.GetNotifications" + SystemRuntimeGetScriptContainer = "System.Runtime.GetScriptContainer" + SystemRuntimeGetTime = "System.Runtime.GetTime" + SystemRuntimeGetTrigger = "System.Runtime.GetTrigger" + SystemRuntimeLog = "System.Runtime.Log" + SystemRuntimeNotify = "System.Runtime.Notify" + SystemRuntimePlatform = "System.Runtime.Platform" + SystemStorageDelete = "System.Storage.Delete" + SystemStorageFind = "System.Storage.Find" + SystemStorageGet = "System.Storage.Get" + SystemStorageGetContext = "System.Storage.GetContext" + SystemStorageGetReadOnlyContext = "System.Storage.GetReadOnlyContext" + SystemStoragePut = "System.Storage.Put" + SystemStoragePutEx = "System.Storage.PutEx" + SystemStorageAsReadOnly = "System.Storage.AsReadOnly" + NeoCryptoVerifyWithECDsaSecp256r1 = "Neo.Crypto.VerifyWithECDsaSecp256r1" + NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1" + NeoCryptoCheckMultisigWithECDsaSecp256r1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256r1" + NeoCryptoCheckMultisigWithECDsaSecp256k1 = "Neo.Crypto.CheckMultisigWithECDsaSecp256k1" + NeoCryptoSHA256 = "Neo.Crypto.SHA256" + NeoCryptoRIPEMD160 = "Neo.Crypto.RIPEMD160" + NeoNativeCall = "Neo.Native.Call" + NeoNativeDeploy = "Neo.Native.Deploy" +) + +var names = []string{ + SystemBinaryBase64Decode, + SystemBinaryBase64Encode, + SystemBinaryDeserialize, + SystemBinarySerialize, + SystemBlockchainGetBlock, + SystemBlockchainGetContract, + SystemBlockchainGetHeight, + SystemBlockchainGetTransaction, + SystemBlockchainGetTransactionFromBlock, + SystemBlockchainGetTransactionHeight, + SystemCallbackCreate, + SystemCallbackCreateFromMethod, + SystemCallbackCreateFromSyscall, + SystemCallbackInvoke, + SystemContractCall, + SystemContractCallEx, + SystemContractCreate, + SystemContractCreateStandardAccount, + SystemContractDestroy, + SystemContractIsStandard, + SystemContractGetCallFlags, + SystemContractUpdate, + SystemEnumeratorConcat, + SystemEnumeratorCreate, + SystemEnumeratorNext, + SystemEnumeratorValue, + SystemIteratorConcat, + SystemIteratorCreate, + SystemIteratorKey, + SystemIteratorKeys, + SystemIteratorValues, + SystemJSONDeserialize, + SystemJSONSerialize, + SystemRuntimeCheckWitness, + SystemRuntimeGasLeft, + SystemRuntimeGetCallingScriptHash, + SystemRuntimeGetEntryScriptHash, + SystemRuntimeGetExecutingScriptHash, + SystemRuntimeGetInvocationCounter, + SystemRuntimeGetNotifications, + SystemRuntimeGetScriptContainer, + SystemRuntimeGetTime, + SystemRuntimeGetTrigger, + SystemRuntimeLog, + SystemRuntimeNotify, + SystemRuntimePlatform, + SystemStorageDelete, + SystemStorageFind, + SystemStorageGet, + SystemStorageGetContext, + SystemStorageGetReadOnlyContext, + SystemStoragePut, + SystemStoragePutEx, + SystemStorageAsReadOnly, + NeoCryptoVerifyWithECDsaSecp256r1, + NeoCryptoVerifyWithECDsaSecp256k1, + NeoCryptoCheckMultisigWithECDsaSecp256r1, + NeoCryptoCheckMultisigWithECDsaSecp256k1, + NeoCryptoSHA256, + NeoCryptoRIPEMD160, + NeoNativeCall, + NeoNativeDeploy, +} diff --git a/pkg/core/interop/json/json_test.go b/pkg/core/interop/json/json_test.go index 12a86edcc..056a29c76 100644 --- a/pkg/core/interop/json/json_test.go +++ b/pkg/core/interop/json/json_test.go @@ -5,15 +5,15 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/core/interop" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) var ( - serializeID = emit.InteropNameToID([]byte("System.Json.Serialize")) - deserializeID = emit.InteropNameToID([]byte("System.Json.Deserialize")) + serializeID = interopnames.ToID([]byte(interopnames.SystemJSONSerialize)) + deserializeID = interopnames.ToID([]byte(interopnames.SystemJSONDeserialize)) ) var jsonInterops = []interop.Function{ diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 6b92e703d..e1fe89dbf 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -12,13 +12,13 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/interop/callback" "github.com/nspcc-dev/neo-go/pkg/core/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/core/interop/enumerator" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/interop/iterator" "github.com/nspcc-dev/neo-go/pkg/core/interop/json" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/vm" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) // SpawnVM returns a VM with script getter and interop functions set @@ -31,101 +31,101 @@ func SpawnVM(ic *interop.Context) *vm.VM { // All lists are sorted, keep 'em this way, please. var systemInterops = []interop.Function{ - {Name: "System.Binary.Base64Decode", Func: runtimeDecode, Price: 100000, ParamCount: 1}, - {Name: "System.Binary.Base64Encode", Func: runtimeEncode, Price: 100000, ParamCount: 1}, - {Name: "System.Binary.Deserialize", Func: runtimeDeserialize, Price: 500000, ParamCount: 1}, - {Name: "System.Binary.Serialize", Func: runtimeSerialize, Price: 100000, ParamCount: 1}, - {Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 2500000, + {Name: interopnames.SystemBinaryBase64Decode, Func: runtimeDecode, Price: 100000, ParamCount: 1}, + {Name: interopnames.SystemBinaryBase64Encode, Func: runtimeEncode, Price: 100000, ParamCount: 1}, + {Name: interopnames.SystemBinaryDeserialize, Func: runtimeDeserialize, Price: 500000, ParamCount: 1}, + {Name: interopnames.SystemBinarySerialize, Func: runtimeSerialize, Price: 100000, ParamCount: 1}, + {Name: interopnames.SystemBlockchainGetBlock, Func: bcGetBlock, Price: 2500000, RequiredFlags: smartcontract.AllowStates, ParamCount: 1}, - {Name: "System.Blockchain.GetContract", Func: bcGetContract, Price: 1000000, + {Name: interopnames.SystemBlockchainGetContract, Func: bcGetContract, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 1}, - {Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 400, + {Name: interopnames.SystemBlockchainGetHeight, Func: bcGetHeight, Price: 400, RequiredFlags: smartcontract.AllowStates}, - {Name: "System.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 1000000, + {Name: interopnames.SystemBlockchainGetTransaction, Func: bcGetTransaction, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 1}, - {Name: "System.Blockchain.GetTransactionFromBlock", Func: bcGetTransactionFromBlock, Price: 1000000, + {Name: interopnames.SystemBlockchainGetTransactionFromBlock, Func: bcGetTransactionFromBlock, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 2}, - {Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 1000000, + {Name: interopnames.SystemBlockchainGetTransactionHeight, Func: bcGetTransactionHeight, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 1}, - {Name: "System.Callback.Create", Func: callback.Create, Price: 400, ParamCount: 3, DisallowCallback: true}, - {Name: "System.Callback.CreateFromMethod", Func: callback.CreateFromMethod, Price: 1000000, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Callback.CreateFromSyscall", Func: callback.CreateFromSyscall, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Callback.Invoke", Func: callback.Invoke, Price: 1000000, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Contract.Call", Func: contractCall, Price: 1000000, + {Name: interopnames.SystemCallbackCreate, Func: callback.Create, Price: 400, ParamCount: 3, DisallowCallback: true}, + {Name: interopnames.SystemCallbackCreateFromMethod, Func: callback.CreateFromMethod, Price: 1000000, ParamCount: 2, DisallowCallback: true}, + {Name: interopnames.SystemCallbackCreateFromSyscall, Func: callback.CreateFromSyscall, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemCallbackInvoke, Func: callback.Invoke, Price: 1000000, ParamCount: 2, DisallowCallback: true}, + {Name: interopnames.SystemContractCall, Func: contractCall, Price: 1000000, RequiredFlags: smartcontract.AllowCall, ParamCount: 3, DisallowCallback: true}, - {Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1000000, + {Name: interopnames.SystemContractCallEx, Func: contractCallEx, Price: 1000000, RequiredFlags: smartcontract.AllowCall, ParamCount: 4, DisallowCallback: true}, - {Name: "System.Contract.Create", Func: contractCreate, Price: 0, + {Name: interopnames.SystemContractCreate, Func: contractCreate, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Contract.CreateStandardAccount", Func: contractCreateStandardAccount, Price: 10000, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1000000, RequiredFlags: smartcontract.AllowModifyStates, DisallowCallback: true}, - {Name: "System.Contract.IsStandard", Func: contractIsStandard, Price: 30000, ParamCount: 1}, - {Name: "System.Contract.GetCallFlags", Func: contractGetCallFlags, Price: 30000, DisallowCallback: true}, - {Name: "System.Contract.Update", Func: contractUpdate, Price: 0, + {Name: interopnames.SystemContractCreateStandardAccount, Func: contractCreateStandardAccount, Price: 10000, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemContractDestroy, Func: contractDestroy, Price: 1000000, RequiredFlags: smartcontract.AllowModifyStates, DisallowCallback: true}, + {Name: interopnames.SystemContractIsStandard, Func: contractIsStandard, Price: 30000, ParamCount: 1}, + {Name: interopnames.SystemContractGetCallFlags, Func: contractGetCallFlags, Price: 30000, DisallowCallback: true}, + {Name: interopnames.SystemContractUpdate, Func: contractUpdate, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 400, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Enumerator.Create", Func: enumerator.Create, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1000000, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Enumerator.Value", Func: enumerator.Value, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Iterator.Concat", Func: iterator.Concat, Price: 400, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Iterator.Create", Func: iterator.Create, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Iterator.Key", Func: iterator.Key, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Iterator.Keys", Func: iterator.Keys, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Iterator.Values", Func: iterator.Values, Price: 400, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Json.Deserialize", Func: json.Deserialize, Price: 500000, ParamCount: 1}, - {Name: "System.Json.Serialize", Func: json.Serialize, Price: 100000, ParamCount: 1}, - {Name: "System.Runtime.CheckWitness", Func: runtime.CheckWitness, Price: 30000, + {Name: interopnames.SystemEnumeratorConcat, Func: enumerator.Concat, Price: 400, ParamCount: 2, DisallowCallback: true}, + {Name: interopnames.SystemEnumeratorCreate, Func: enumerator.Create, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemEnumeratorNext, Func: enumerator.Next, Price: 1000000, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemEnumeratorValue, Func: enumerator.Value, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemIteratorConcat, Func: iterator.Concat, Price: 400, ParamCount: 2, DisallowCallback: true}, + {Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemIteratorKey, Func: iterator.Key, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemIteratorKeys, Func: iterator.Keys, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemIteratorValues, Func: iterator.Values, Price: 400, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.SystemJSONDeserialize, Func: json.Deserialize, Price: 500000, ParamCount: 1}, + {Name: interopnames.SystemJSONSerialize, Func: json.Serialize, Price: 100000, ParamCount: 1}, + {Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 30000, RequiredFlags: smartcontract.AllowStates, ParamCount: 1}, - {Name: "System.Runtime.GasLeft", Func: runtime.GasLeft, Price: 400}, - {Name: "System.Runtime.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 400}, - {Name: "System.Runtime.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 400}, - {Name: "System.Runtime.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 400}, - {Name: "System.Runtime.GetInvocationCounter", Func: runtime.GetInvocationCounter, Price: 400}, - {Name: "System.Runtime.GetNotifications", Func: runtime.GetNotifications, Price: 10000, ParamCount: 1}, - {Name: "System.Runtime.GetScriptContainer", Func: engineGetScriptContainer, Price: 250}, - {Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 250, RequiredFlags: smartcontract.AllowStates}, - {Name: "System.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 250}, - {Name: "System.Runtime.Log", Func: runtimeLog, Price: 1000000, RequiredFlags: smartcontract.AllowNotify, + {Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 400}, + {Name: interopnames.SystemRuntimeGetCallingScriptHash, Func: engineGetCallingScriptHash, Price: 400}, + {Name: interopnames.SystemRuntimeGetEntryScriptHash, Func: engineGetEntryScriptHash, Price: 400}, + {Name: interopnames.SystemRuntimeGetExecutingScriptHash, Func: engineGetExecutingScriptHash, Price: 400}, + {Name: interopnames.SystemRuntimeGetInvocationCounter, Func: runtime.GetInvocationCounter, Price: 400}, + {Name: interopnames.SystemRuntimeGetNotifications, Func: runtime.GetNotifications, Price: 10000, ParamCount: 1}, + {Name: interopnames.SystemRuntimeGetScriptContainer, Func: engineGetScriptContainer, Price: 250}, + {Name: interopnames.SystemRuntimeGetTime, Func: runtimeGetTime, Price: 250, RequiredFlags: smartcontract.AllowStates}, + {Name: interopnames.SystemRuntimeGetTrigger, Func: runtimeGetTrigger, Price: 250}, + {Name: interopnames.SystemRuntimeLog, Func: runtimeLog, Price: 1000000, RequiredFlags: smartcontract.AllowNotify, ParamCount: 1, DisallowCallback: true}, - {Name: "System.Runtime.Notify", Func: runtimeNotify, Price: 1000000, RequiredFlags: smartcontract.AllowNotify, + {Name: interopnames.SystemRuntimeNotify, Func: runtimeNotify, Price: 1000000, RequiredFlags: smartcontract.AllowNotify, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 250}, - {Name: "System.Storage.Delete", Func: storageDelete, Price: StoragePrice, + {Name: interopnames.SystemRuntimePlatform, Func: runtimePlatform, Price: 250}, + {Name: interopnames.SystemStorageDelete, Func: storageDelete, Price: StoragePrice, RequiredFlags: smartcontract.AllowModifyStates, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Storage.Find", Func: storageFind, Price: 1000000, RequiredFlags: smartcontract.AllowStates, + {Name: interopnames.SystemStorageFind, Func: storageFind, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Storage.Get", Func: storageGet, Price: 1000000, RequiredFlags: smartcontract.AllowStates, + {Name: interopnames.SystemStorageGet, Func: storageGet, Price: 1000000, RequiredFlags: smartcontract.AllowStates, ParamCount: 2, DisallowCallback: true}, - {Name: "System.Storage.GetContext", Func: storageGetContext, Price: 400, + {Name: interopnames.SystemStorageGetContext, Func: storageGetContext, Price: 400, RequiredFlags: smartcontract.AllowStates, DisallowCallback: true}, - {Name: "System.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 400, + {Name: interopnames.SystemStorageGetReadOnlyContext, Func: storageGetReadOnlyContext, Price: 400, RequiredFlags: smartcontract.AllowStates, DisallowCallback: true}, - {Name: "System.Storage.Put", Func: storagePut, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, + {Name: interopnames.SystemStoragePut, Func: storagePut, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, ParamCount: 3, DisallowCallback: true}, // These don't have static price in C# code. - {Name: "System.Storage.PutEx", Func: storagePutEx, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, + {Name: interopnames.SystemStoragePutEx, Func: storagePutEx, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, ParamCount: 4, DisallowCallback: true}, - {Name: "System.Storage.AsReadOnly", Func: storageContextAsReadOnly, Price: 400, + {Name: interopnames.SystemStorageAsReadOnly, Func: storageContextAsReadOnly, Price: 400, RequiredFlags: smartcontract.AllowStates, ParamCount: 1, DisallowCallback: true}, } var neoInterops = []interop.Function{ - {Name: "Neo.Crypto.VerifyWithECDsaSecp256r1", Func: crypto.ECDSASecp256r1Verify, + {Name: interopnames.NeoCryptoVerifyWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1Verify, Price: crypto.ECDSAVerifyPrice, ParamCount: 3}, - {Name: "Neo.Crypto.VerifyWithECDsaSecp256k1", Func: crypto.ECDSASecp256k1Verify, + {Name: interopnames.NeoCryptoVerifyWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1Verify, Price: crypto.ECDSAVerifyPrice, ParamCount: 3}, - {Name: "Neo.Crypto.CheckMultisigWithECDsaSecp256r1", Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3}, - {Name: "Neo.Crypto.CheckMultisigWithECDsaSecp256k1", Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3}, - {Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1000000, ParamCount: 1}, - {Name: "Neo.Crypto.RIPEMD160", Func: crypto.RipeMD160, Price: 1000000, ParamCount: 1}, - {Name: "Neo.Native.Call", Func: native.Call, Price: 0, ParamCount: 1, DisallowCallback: true}, - {Name: "Neo.Native.Deploy", Func: native.Deploy, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, DisallowCallback: true}, + {Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3}, + {Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3}, + {Name: interopnames.NeoCryptoSHA256, Func: crypto.Sha256, Price: 1000000, ParamCount: 1}, + {Name: interopnames.NeoCryptoRIPEMD160, Func: crypto.RipeMD160, Price: 1000000, ParamCount: 1}, + {Name: interopnames.NeoNativeCall, Func: native.Call, Price: 0, ParamCount: 1, DisallowCallback: true}, + {Name: interopnames.NeoNativeDeploy, Func: native.Deploy, Price: 0, RequiredFlags: smartcontract.AllowModifyStates, DisallowCallback: true}, } // initIDinInteropsSlice initializes IDs from names in one given // Function slice and then sorts it. func initIDinInteropsSlice(iops []interop.Function) { for i := range iops { - iops[i].ID = emit.InteropNameToID([]byte(iops[i].Name)) + iops[i].ID = interopnames.ToID([]byte(iops[i].Name)) } interop.Sort(iops) } diff --git a/pkg/core/util.go b/pkg/core/util.go index 999a5eef5..dae367fff 100644 --- a/pkg/core/util.go +++ b/pkg/core/util.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/interop/crypto" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -75,7 +76,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) func deployNativeContracts(magic netmode.Magic) *transaction.Transaction { buf := io.NewBufBinWriter() - emit.Syscall(buf.BinWriter, "Neo.Native.Deploy") + emit.Syscall(buf.BinWriter, interopnames.NeoNativeDeploy) script := buf.Bytes() tx := transaction.New(magic, script, 0) tx.Nonce = 0 diff --git a/pkg/crypto/keys/publickey.go b/pkg/crypto/keys/publickey.go index 358193b61..1d50d51d0 100644 --- a/pkg/crypto/keys/publickey.go +++ b/pkg/crypto/keys/publickey.go @@ -11,6 +11,7 @@ import ( "math/big" "github.com/btcsuite/btcd/btcec" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" @@ -295,7 +296,7 @@ func (p *PublicKey) GetVerificationScript() []byte { } emit.Bytes(buf.BinWriter, b) emit.Opcode(buf.BinWriter, opcode.PUSHNULL) - emit.Syscall(buf.BinWriter, "Neo.Crypto.VerifyWithECDsaSecp256r1") + emit.Syscall(buf.BinWriter, interopnames.NeoCryptoVerifyWithECDsaSecp256r1) return buf.Bytes() } diff --git a/pkg/rpc/request/txBuilder.go b/pkg/rpc/request/txBuilder.go index c3b76d91e..64b1ad1ed 100644 --- a/pkg/rpc/request/txBuilder.go +++ b/pkg/rpc/request/txBuilder.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -24,7 +25,7 @@ func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, error } emit.Bytes(script.BinWriter, rawManifest) emit.Bytes(script.BinWriter, avm) - emit.Syscall(script.BinWriter, "System.Contract.Create") + emit.Syscall(script.BinWriter, interopnames.SystemContractCreate) return script.Bytes(), nil } diff --git a/pkg/smartcontract/contract.go b/pkg/smartcontract/contract.go index 811ac6ae2..6a81896ae 100644 --- a/pkg/smartcontract/contract.go +++ b/pkg/smartcontract/contract.go @@ -4,6 +4,7 @@ import ( "fmt" "sort" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -31,7 +32,7 @@ func CreateMultiSigRedeemScript(m int, publicKeys keys.PublicKeys) ([]byte, erro } emit.Int(buf.BinWriter, int64(len(publicKeys))) emit.Opcode(buf.BinWriter, opcode.PUSHNULL) - emit.Syscall(buf.BinWriter, "Neo.Crypto.CheckMultisigWithECDsaSecp256r1") + emit.Syscall(buf.BinWriter, interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1) return buf.Bytes(), nil } diff --git a/pkg/smartcontract/contract_test.go b/pkg/smartcontract/contract_test.go index 1c8e74f9c..abcd20c8a 100644 --- a/pkg/smartcontract/contract_test.go +++ b/pkg/smartcontract/contract_test.go @@ -3,9 +3,9 @@ package smartcontract import ( "testing" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -34,7 +34,7 @@ func TestCreateMultiSigRedeemScript(t *testing.T) { assert.Equal(t, opcode.PUSH3, opcode.Opcode(br.ReadB())) assert.Equal(t, opcode.PUSHNULL, opcode.Opcode(br.ReadB())) assert.Equal(t, opcode.SYSCALL, opcode.Opcode(br.ReadB())) - assert.Equal(t, emit.InteropNameToID([]byte("Neo.Crypto.CheckMultisigWithECDsaSecp256r1")), br.ReadU32LE()) + assert.Equal(t, interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)), br.ReadU32LE()) } func TestCreateDefaultMultiSigRedeemScript(t *testing.T) { diff --git a/pkg/vm/contract_checks.go b/pkg/vm/contract_checks.go index cd2f83b52..1e8905663 100644 --- a/pkg/vm/contract_checks.go +++ b/pkg/vm/contract_checks.go @@ -3,15 +3,15 @@ package vm import ( "encoding/binary" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) var ( - verifyInteropID = emit.InteropNameToID([]byte("Neo.Crypto.VerifyWithECDsaSecp256r1")) - multisigInteropID = emit.InteropNameToID([]byte("Neo.Crypto.CheckMultisigWithECDsaSecp256r1")) + verifyInteropID = interopnames.ToID([]byte(interopnames.NeoCryptoVerifyWithECDsaSecp256r1)) + multisigInteropID = interopnames.ToID([]byte(interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1)) ) func getNumOfThingsFromInstr(instr opcode.Opcode, param []byte) (int, bool) { diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index 84fbad3c5..3e693a915 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -1,13 +1,13 @@ package emit import ( - "crypto/sha256" "encoding/binary" "errors" "fmt" "math/big" "math/bits" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" @@ -124,7 +124,7 @@ func Syscall(w *io.BinWriter, api string) { return } buf := make([]byte, 4) - binary.LittleEndian.PutUint32(buf, InteropNameToID([]byte(api))) + binary.LittleEndian.PutUint32(buf, interopnames.ToID([]byte(api))) Instruction(w, opcode.SYSCALL, buf) } @@ -149,7 +149,7 @@ func Jmp(w *io.BinWriter, op opcode.Opcode, label uint16) { // AppCall emits call to provided contract. func AppCall(w *io.BinWriter, scriptHash util.Uint160) { Bytes(w, scriptHash.BytesBE()) - Syscall(w, "System.Contract.Call") + Syscall(w, interopnames.SystemContractCall) } // AppCallWithOperationAndArgs emits an APPCALL with the given operation and arguments. @@ -162,9 +162,3 @@ func AppCallWithOperationAndArgs(w *io.BinWriter, scriptHash util.Uint160, opera func isInstructionJmp(op opcode.Opcode) bool { return opcode.JMP <= op && op <= opcode.CALLL } - -// InteropNameToID returns an identificator of the method based on its name. -func InteropNameToID(name []byte) uint32 { - h := sha256.Sum256(name) - return binary.LittleEndian.Uint32(h[:4]) -} diff --git a/pkg/vm/emit/emit_test.go b/pkg/vm/emit/emit_test.go index ddda3e684..1432a5e42 100644 --- a/pkg/vm/emit/emit_test.go +++ b/pkg/vm/emit/emit_test.go @@ -5,6 +5,7 @@ import ( "errors" "testing" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -190,8 +191,8 @@ func TestEmitString(t *testing.T) { func TestEmitSyscall(t *testing.T) { syscalls := []string{ - "System.Runtime.Log", - "System.Runtime.Notify", + interopnames.SystemRuntimeLog, + interopnames.SystemRuntimeNotify, "System.Runtime.Whatever", } @@ -201,7 +202,7 @@ func TestEmitSyscall(t *testing.T) { result := buf.Bytes() assert.Equal(t, 5, len(result)) assert.Equal(t, opcode.Opcode(result[0]), opcode.SYSCALL) - assert.Equal(t, binary.LittleEndian.Uint32(result[1:]), InteropNameToID([]byte(syscall))) + assert.Equal(t, binary.LittleEndian.Uint32(result[1:]), interopnames.ToID([]byte(syscall))) buf.Reset() } diff --git a/pkg/vm/interop.go b/pkg/vm/interop.go index ec1cf0ef3..9f6e9af6a 100644 --- a/pkg/vm/interop.go +++ b/pkg/vm/interop.go @@ -5,8 +5,8 @@ import ( "fmt" "sort" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -19,31 +19,31 @@ type interopIDFuncPrice struct { } var defaultVMInterops = []interopIDFuncPrice{ - {ID: emit.InteropNameToID([]byte("System.Binary.Deserialize")), + {ID: interopnames.ToID([]byte(interopnames.SystemBinaryDeserialize)), Func: RuntimeDeserialize, Price: 500000}, - {ID: emit.InteropNameToID([]byte("System.Binary.Serialize")), + {ID: interopnames.ToID([]byte(interopnames.SystemBinarySerialize)), Func: RuntimeSerialize, Price: 100000}, - {ID: emit.InteropNameToID([]byte("System.Runtime.Log")), + {ID: interopnames.ToID([]byte(interopnames.SystemRuntimeLog)), Func: runtimeLog, Price: 1000000, RequiredFlags: smartcontract.AllowNotify}, - {ID: emit.InteropNameToID([]byte("System.Runtime.Notify")), + {ID: interopnames.ToID([]byte(interopnames.SystemRuntimeNotify)), Func: runtimeNotify, Price: 1000000, RequiredFlags: smartcontract.AllowNotify}, - {ID: emit.InteropNameToID([]byte("System.Enumerator.Create")), + {ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorCreate)), Func: EnumeratorCreate, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Enumerator.Next")), + {ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorNext)), Func: EnumeratorNext, Price: 1000000}, - {ID: emit.InteropNameToID([]byte("System.Enumerator.Concat")), + {ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorConcat)), Func: EnumeratorConcat, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Enumerator.Value")), + {ID: interopnames.ToID([]byte(interopnames.SystemEnumeratorValue)), Func: EnumeratorValue, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Iterator.Create")), + {ID: interopnames.ToID([]byte(interopnames.SystemIteratorCreate)), Func: IteratorCreate, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Iterator.Concat")), + {ID: interopnames.ToID([]byte(interopnames.SystemIteratorConcat)), Func: IteratorConcat, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Iterator.Key")), + {ID: interopnames.ToID([]byte(interopnames.SystemIteratorKey)), Func: IteratorKey, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Iterator.Keys")), + {ID: interopnames.ToID([]byte(interopnames.SystemIteratorKeys)), Func: IteratorKeys, Price: 400}, - {ID: emit.InteropNameToID([]byte("System.Iterator.Values")), + {ID: interopnames.ToID([]byte(interopnames.SystemIteratorValues)), Func: IteratorValues, Price: 400}, } diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 14a3a435e..ac19b20e4 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -13,6 +13,7 @@ import ( "text/tabwriter" "unicode/utf8" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -191,10 +192,23 @@ func (v *VM) PrintOps() { v.getOffsetDesc(ctx, catchP), v.getOffsetDesc(ctx, finallyP)) case opcode.INITSSLOT: desc = fmt.Sprint(parameter[0]) + case opcode.CONVERT, opcode.ISTYPE: + typ := stackitem.Type(parameter[0]) + desc = fmt.Sprintf("%s (%x)", typ, parameter[0]) case opcode.INITSLOT: desc = fmt.Sprintf("%d local, %d arg", parameter[0], parameter[1]) case opcode.SYSCALL: - desc = fmt.Sprintf("%q", parameter) + name, err := interopnames.FromID(GetInteropID(parameter)) + if err != nil { + name = "not found" + } + desc = fmt.Sprintf("%s (%x)", name, parameter) + case opcode.PUSHINT8, opcode.PUSHINT16, opcode.PUSHINT32, + opcode.PUSHINT64, opcode.PUSHINT128, opcode.PUSHINT256: + val := bigint.FromBytes(parameter) + desc = fmt.Sprintf("%d (%x)", val, parameter) + case opcode.LDLOC, opcode.STLOC, opcode.LDARG, opcode.STARG, opcode.LDSFLD, opcode.STSFLD: + desc = fmt.Sprintf("%d (%x)", parameter[0], parameter) default: if utf8.Valid(parameter) { desc = fmt.Sprintf("%x (%q)", parameter, parameter) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index cb55e949b..cd2fae269 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -11,6 +11,7 @@ import ( "math/rand" "testing" + "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/io" @@ -23,7 +24,7 @@ import ( ) func fooInteropHandler(v *VM, id uint32) error { - if id == emit.InteropNameToID([]byte("foo")) { + if id == interopnames.ToID([]byte("foo")) { if !v.AddGas(1) { return errors.New("invalid gas amount") } @@ -244,6 +245,8 @@ func TestISTYPE(t *testing.T) { func testCONVERT(to stackitem.Type, item, res stackitem.Item) func(t *testing.T) { return func(t *testing.T) { prog := []byte{byte(opcode.CONVERT), byte(to)} + v := load(prog) + v.PrintOps() runWithArgs(t, prog, res, item) } } @@ -491,16 +494,16 @@ func getEnumeratorProg(n int, isIter bool) (prog []byte) { prog = []byte{byte(opcode.INITSSLOT), 1, byte(opcode.STSFLD0)} for i := 0; i < n; i++ { prog = append(prog, byte(opcode.LDSFLD0)) - prog = append(prog, getSyscallProg("System.Enumerator.Next")...) + prog = append(prog, getSyscallProg(interopnames.SystemEnumeratorNext)...) prog = append(prog, byte(opcode.LDSFLD0)) - prog = append(prog, getSyscallProg("System.Enumerator.Value")...) + prog = append(prog, getSyscallProg(interopnames.SystemEnumeratorValue)...) if isIter { prog = append(prog, byte(opcode.LDSFLD0)) - prog = append(prog, getSyscallProg("System.Iterator.Key")...) + prog = append(prog, getSyscallProg(interopnames.SystemIteratorKey)...) } } prog = append(prog, byte(opcode.LDSFLD0)) - prog = append(prog, getSyscallProg("System.Enumerator.Next")...) + prog = append(prog, getSyscallProg(interopnames.SystemEnumeratorNext)...) return } @@ -592,8 +595,8 @@ func TestIteratorConcat(t *testing.T) { } func TestIteratorKeys(t *testing.T) { - prog := getSyscallProg("System.Iterator.Create") - prog = append(prog, getSyscallProg("System.Iterator.Keys")...) + prog := getSyscallProg(interopnames.SystemIteratorCreate) + prog = append(prog, getSyscallProg(interopnames.SystemIteratorKeys)...) prog = append(prog, getEnumeratorProg(2, false)...) v := load(prog) @@ -612,8 +615,8 @@ func TestIteratorKeys(t *testing.T) { } func TestIteratorValues(t *testing.T) { - prog := getSyscallProg("System.Iterator.Create") - prog = append(prog, getSyscallProg("System.Iterator.Values")...) + prog := getSyscallProg(interopnames.SystemIteratorCreate) + prog = append(prog, getSyscallProg(interopnames.SystemIteratorValues)...) prog = append(prog, getEnumeratorProg(2, false)...) v := load(prog) @@ -646,8 +649,8 @@ func getSyscallProg(name string) (prog []byte) { } func getSerializeProg() (prog []byte) { - prog = append(prog, getSyscallProg("System.Binary.Serialize")...) - prog = append(prog, getSyscallProg("System.Binary.Deserialize")...) + prog = append(prog, getSyscallProg(interopnames.SystemBinarySerialize)...) + prog = append(prog, getSyscallProg(interopnames.SystemBinaryDeserialize)...) prog = append(prog, byte(opcode.RET)) return @@ -752,7 +755,7 @@ func TestSerializeStruct(t *testing.T) { } func TestDeserializeUnknown(t *testing.T) { - prog := append(getSyscallProg("System.Binary.Deserialize"), byte(opcode.RET)) + prog := append(getSyscallProg(interopnames.SystemBinaryDeserialize), byte(opcode.RET)) data, err := stackitem.SerializeItem(stackitem.NewBigInteger(big.NewInt(123))) require.NoError(t, err) @@ -788,7 +791,7 @@ func TestSerializeMapCompat(t *testing.T) { emit.Bytes(buf.BinWriter, []byte("key")) emit.Bytes(buf.BinWriter, []byte("value")) emit.Opcode(buf.BinWriter, opcode.SETITEM) - emit.Syscall(buf.BinWriter, "System.Binary.Serialize") + emit.Syscall(buf.BinWriter, interopnames.SystemBinarySerialize) require.NoError(t, buf.Err) vm := load(buf.Bytes())