core/interop: add base58 encoding/decoding syscalls
Follow neo-project/neo#1833.
This commit is contained in:
parent
562e7e371f
commit
9c72ea1d64
6 changed files with 80 additions and 30 deletions
|
@ -11,6 +11,8 @@ type Syscall struct {
|
||||||
// All lists are sorted, keep 'em this way, please.
|
// All lists are sorted, keep 'em this way, please.
|
||||||
var syscalls = map[string]map[string]Syscall{
|
var syscalls = map[string]map[string]Syscall{
|
||||||
"binary": {
|
"binary": {
|
||||||
|
"Base58Decode": {interopnames.SystemBinaryBase58Decode, false},
|
||||||
|
"Base58Encode": {interopnames.SystemBinaryBase58Encode, false},
|
||||||
"Base64Decode": {interopnames.SystemBinaryBase64Decode, false},
|
"Base64Decode": {interopnames.SystemBinaryBase64Decode, false},
|
||||||
"Base64Encode": {interopnames.SystemBinaryBase64Encode, false},
|
"Base64Encode": {interopnames.SystemBinaryBase64Encode, false},
|
||||||
"Deserialize": {interopnames.SystemBinaryDeserialize, false},
|
"Deserialize": {interopnames.SystemBinaryDeserialize, false},
|
||||||
|
|
|
@ -2,6 +2,8 @@ package interopnames
|
||||||
|
|
||||||
// Names of all used interops.
|
// Names of all used interops.
|
||||||
const (
|
const (
|
||||||
|
SystemBinaryBase58Decode = "System.Binary.Base58Decode"
|
||||||
|
SystemBinaryBase58Encode = "System.Binary.Base58Encode"
|
||||||
SystemBinaryBase64Decode = "System.Binary.Base64Decode"
|
SystemBinaryBase64Decode = "System.Binary.Base64Decode"
|
||||||
SystemBinaryBase64Encode = "System.Binary.Base64Encode"
|
SystemBinaryBase64Encode = "System.Binary.Base64Encode"
|
||||||
SystemBinaryDeserialize = "System.Binary.Deserialize"
|
SystemBinaryDeserialize = "System.Binary.Deserialize"
|
||||||
|
@ -67,6 +69,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var names = []string{
|
var names = []string{
|
||||||
|
SystemBinaryBase58Decode,
|
||||||
|
SystemBinaryBase58Encode,
|
||||||
SystemBinaryBase64Decode,
|
SystemBinaryBase64Decode,
|
||||||
SystemBinaryBase64Encode,
|
SystemBinaryBase64Encode,
|
||||||
SystemBinaryDeserialize,
|
SystemBinaryDeserialize,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
@ -195,16 +196,16 @@ func runtimeDeserialize(ic *interop.Context) error {
|
||||||
return vm.RuntimeDeserialize(ic.VM)
|
return vm.RuntimeDeserialize(ic.VM)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runtimeEncode encodes top stack item into a base64 string.
|
// runtimeEncodeBase64 encodes top stack item into a base64 string.
|
||||||
func runtimeEncode(ic *interop.Context) error {
|
func runtimeEncodeBase64(ic *interop.Context) error {
|
||||||
src := ic.VM.Estack().Pop().Bytes()
|
src := ic.VM.Estack().Pop().Bytes()
|
||||||
result := base64.StdEncoding.EncodeToString(src)
|
result := base64.StdEncoding.EncodeToString(src)
|
||||||
ic.VM.Estack().PushVal([]byte(result))
|
ic.VM.Estack().PushVal([]byte(result))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runtimeDecode decodes top stack item from base64 string to byte array.
|
// runtimeDecodeBase64 decodes top stack item from base64 string to byte array.
|
||||||
func runtimeDecode(ic *interop.Context) error {
|
func runtimeDecodeBase64(ic *interop.Context) error {
|
||||||
src := ic.VM.Estack().Pop().String()
|
src := ic.VM.Estack().Pop().String()
|
||||||
result, err := base64.StdEncoding.DecodeString(src)
|
result, err := base64.StdEncoding.DecodeString(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -213,3 +214,22 @@ func runtimeDecode(ic *interop.Context) error {
|
||||||
ic.VM.Estack().PushVal(result)
|
ic.VM.Estack().PushVal(result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runtimeEncodeBase58 encodes top stack item into a base58 string.
|
||||||
|
func runtimeEncodeBase58(ic *interop.Context) error {
|
||||||
|
src := ic.VM.Estack().Pop().Bytes()
|
||||||
|
result := base58.Encode(src)
|
||||||
|
ic.VM.Estack().PushVal([]byte(result))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// runtimeDecodeBase58 decodes top stack item from base58 string to byte array.
|
||||||
|
func runtimeDecodeBase58(ic *interop.Context) error {
|
||||||
|
src := ic.VM.Estack().Pop().String()
|
||||||
|
result, err := base58.Decode(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ic.VM.Estack().PushVal(result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mr-tron/base58"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"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/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
|
@ -220,36 +221,45 @@ func TestECDSAVerify(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRuntimeEncode(t *testing.T) {
|
func TestRuntimeEncodeDecode(t *testing.T) {
|
||||||
str := []byte("my pretty string")
|
original := []byte("my pretty string")
|
||||||
|
encoded64 := base64.StdEncoding.EncodeToString(original)
|
||||||
|
encoded58 := base58.Encode(original)
|
||||||
v, ic, bc := createVM(t)
|
v, ic, bc := createVM(t)
|
||||||
defer bc.Close()
|
defer bc.Close()
|
||||||
|
|
||||||
v.Estack().PushVal(str)
|
t.Run("Encode64", func(t *testing.T) {
|
||||||
require.NoError(t, runtimeEncode(ic))
|
v.Estack().PushVal(original)
|
||||||
|
require.NoError(t, runtimeEncodeBase64(ic))
|
||||||
expected := []byte(base64.StdEncoding.EncodeToString(str))
|
|
||||||
actual := v.Estack().Pop().Bytes()
|
actual := v.Estack().Pop().Bytes()
|
||||||
require.Equal(t, expected, actual)
|
require.Equal(t, []byte(encoded64), actual)
|
||||||
}
|
|
||||||
|
|
||||||
func TestRuntimeDecode(t *testing.T) {
|
|
||||||
expected := []byte("my pretty string")
|
|
||||||
str := base64.StdEncoding.EncodeToString(expected)
|
|
||||||
v, ic, bc := createVM(t)
|
|
||||||
defer bc.Close()
|
|
||||||
|
|
||||||
t.Run("positive", func(t *testing.T) {
|
|
||||||
v.Estack().PushVal(str)
|
|
||||||
require.NoError(t, runtimeDecode(ic))
|
|
||||||
|
|
||||||
actual := v.Estack().Pop().Bytes()
|
|
||||||
require.Equal(t, expected, actual)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("error", func(t *testing.T) {
|
t.Run("Encode58", func(t *testing.T) {
|
||||||
v.Estack().PushVal(str + "%")
|
v.Estack().PushVal(original)
|
||||||
require.Error(t, runtimeDecode(ic))
|
require.NoError(t, runtimeEncodeBase58(ic))
|
||||||
|
actual := v.Estack().Pop().Bytes()
|
||||||
|
require.Equal(t, []byte(encoded58), actual)
|
||||||
|
})
|
||||||
|
t.Run("Decode64/positive", func(t *testing.T) {
|
||||||
|
v.Estack().PushVal(encoded64)
|
||||||
|
require.NoError(t, runtimeDecodeBase64(ic))
|
||||||
|
actual := v.Estack().Pop().Bytes()
|
||||||
|
require.Equal(t, original, actual)
|
||||||
|
})
|
||||||
|
t.Run("Decode64/error", func(t *testing.T) {
|
||||||
|
v.Estack().PushVal(encoded64 + "%")
|
||||||
|
require.Error(t, runtimeDecodeBase64(ic))
|
||||||
|
})
|
||||||
|
t.Run("Decode58/positive", func(t *testing.T) {
|
||||||
|
v.Estack().PushVal(encoded58)
|
||||||
|
require.NoError(t, runtimeDecodeBase58(ic))
|
||||||
|
actual := v.Estack().Pop().Bytes()
|
||||||
|
require.Equal(t, original, actual)
|
||||||
|
})
|
||||||
|
t.Run("Decode58/error", func(t *testing.T) {
|
||||||
|
v.Estack().PushVal(encoded58 + "%")
|
||||||
|
require.Error(t, runtimeDecodeBase58(ic))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,10 @@ func SpawnVM(ic *interop.Context) *vm.VM {
|
||||||
|
|
||||||
// All lists are sorted, keep 'em this way, please.
|
// All lists are sorted, keep 'em this way, please.
|
||||||
var systemInterops = []interop.Function{
|
var systemInterops = []interop.Function{
|
||||||
{Name: interopnames.SystemBinaryBase64Decode, Func: runtimeDecode, Price: 100000, ParamCount: 1},
|
{Name: interopnames.SystemBinaryBase58Decode, Func: runtimeDecodeBase58, Price: 100000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemBinaryBase64Encode, Func: runtimeEncode, Price: 100000, ParamCount: 1},
|
{Name: interopnames.SystemBinaryBase58Encode, Func: runtimeEncodeBase58, Price: 100000, ParamCount: 1},
|
||||||
|
{Name: interopnames.SystemBinaryBase64Decode, Func: runtimeDecodeBase64, Price: 100000, ParamCount: 1},
|
||||||
|
{Name: interopnames.SystemBinaryBase64Encode, Func: runtimeEncodeBase64, Price: 100000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemBinaryDeserialize, Func: runtimeDeserialize, Price: 500000, ParamCount: 1},
|
{Name: interopnames.SystemBinaryDeserialize, Func: runtimeDeserialize, Price: 500000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemBinarySerialize, Func: runtimeSerialize, Price: 100000, ParamCount: 1},
|
{Name: interopnames.SystemBinarySerialize, Func: runtimeSerialize, Price: 100000, ParamCount: 1},
|
||||||
{Name: interopnames.SystemBlockchainGetBlock, Func: bcGetBlock, Price: 2500000,
|
{Name: interopnames.SystemBlockchainGetBlock, Func: bcGetBlock, Price: 2500000,
|
||||||
|
|
|
@ -28,3 +28,15 @@ func Base64Encode(b []byte) []byte {
|
||||||
func Base64Decode(b []byte) []byte {
|
func Base64Decode(b []byte) []byte {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base58Encode encodes given byte slice into a base58 string and returns byte
|
||||||
|
// representation of this string. It uses `System.Binary.Base58Encode` syscall.
|
||||||
|
func Base58Encode(b []byte) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base58Decode decodes given base58 string represented as a byte slice into
|
||||||
|
// a new byte slice. It uses `System.Binary.Base58Decode` syscall.
|
||||||
|
func Base58Decode(b []byte) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue