Skip to content

Commit

Permalink
core/interop: add base58 encoding/decoding syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
roman-khimov committed Aug 23, 2020
1 parent 562e7e3 commit 9c72ea1
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 30 deletions.
2 changes: 2 additions & 0 deletions pkg/compiler/syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type Syscall struct {
// All lists are sorted, keep 'em this way, please.
var syscalls = map[string]map[string]Syscall{
"binary": {
"Base58Decode": {interopnames.SystemBinaryBase58Decode, false},
"Base58Encode": {interopnames.SystemBinaryBase58Encode, false},
"Base64Decode": {interopnames.SystemBinaryBase64Decode, false},
"Base64Encode": {interopnames.SystemBinaryBase64Encode, false},
"Deserialize": {interopnames.SystemBinaryDeserialize, false},
Expand Down
4 changes: 4 additions & 0 deletions pkg/core/interop/interopnames/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package interopnames

// Names of all used interops.
const (
SystemBinaryBase58Decode = "System.Binary.Base58Decode"
SystemBinaryBase58Encode = "System.Binary.Base58Encode"
SystemBinaryBase64Decode = "System.Binary.Base64Decode"
SystemBinaryBase64Encode = "System.Binary.Base64Encode"
SystemBinaryDeserialize = "System.Binary.Deserialize"
Expand Down Expand Up @@ -67,6 +69,8 @@ const (
)

var names = []string{
SystemBinaryBase58Decode,
SystemBinaryBase58Encode,
SystemBinaryBase64Decode,
SystemBinaryBase64Encode,
SystemBinaryDeserialize,
Expand Down
28 changes: 24 additions & 4 deletions pkg/core/interop_neo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"sort"

"github.com/mr-tron/base58"
"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/crypto/hash"
Expand Down Expand Up @@ -195,16 +196,16 @@ func runtimeDeserialize(ic *interop.Context) error {
return vm.RuntimeDeserialize(ic.VM)
}

// runtimeEncode encodes top stack item into a base64 string.
func runtimeEncode(ic *interop.Context) error {
// runtimeEncodeBase64 encodes top stack item into a base64 string.
func runtimeEncodeBase64(ic *interop.Context) error {
src := ic.VM.Estack().Pop().Bytes()
result := base64.StdEncoding.EncodeToString(src)
ic.VM.Estack().PushVal([]byte(result))
return nil
}

// runtimeDecode decodes top stack item from base64 string to byte array.
func runtimeDecode(ic *interop.Context) error {
// runtimeDecodeBase64 decodes top stack item from base64 string to byte array.
func runtimeDecodeBase64(ic *interop.Context) error {
src := ic.VM.Estack().Pop().String()
result, err := base64.StdEncoding.DecodeString(src)
if err != nil {
Expand All @@ -213,3 +214,22 @@ func runtimeDecode(ic *interop.Context) error {
ic.VM.Estack().PushVal(result)
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
}
58 changes: 34 additions & 24 deletions pkg/core/interop_neo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"testing"

"github.com/mr-tron/base58"
"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/dao"
Expand Down Expand Up @@ -220,36 +221,45 @@ func TestECDSAVerify(t *testing.T) {
})
}

func TestRuntimeEncode(t *testing.T) {
str := []byte("my pretty string")
func TestRuntimeEncodeDecode(t *testing.T) {
original := []byte("my pretty string")
encoded64 := base64.StdEncoding.EncodeToString(original)
encoded58 := base58.Encode(original)
v, ic, bc := createVM(t)
defer bc.Close()

v.Estack().PushVal(str)
require.NoError(t, runtimeEncode(ic))

expected := []byte(base64.StdEncoding.EncodeToString(str))
actual := v.Estack().Pop().Bytes()
require.Equal(t, expected, 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))

t.Run("Encode64", func(t *testing.T) {
v.Estack().PushVal(original)
require.NoError(t, runtimeEncodeBase64(ic))
actual := v.Estack().Pop().Bytes()
require.Equal(t, expected, actual)
require.Equal(t, []byte(encoded64), actual)
})

t.Run("error", func(t *testing.T) {
v.Estack().PushVal(str + "%")
require.Error(t, runtimeDecode(ic))
t.Run("Encode58", func(t *testing.T) {
v.Estack().PushVal(original)
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))
})
}

Expand Down
6 changes: 4 additions & 2 deletions pkg/core/interops.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ func SpawnVM(ic *interop.Context) *vm.VM {

// All lists are sorted, keep 'em this way, please.
var systemInterops = []interop.Function{
{Name: interopnames.SystemBinaryBase64Decode, Func: runtimeDecode, Price: 100000, ParamCount: 1},
{Name: interopnames.SystemBinaryBase64Encode, Func: runtimeEncode, Price: 100000, ParamCount: 1},
{Name: interopnames.SystemBinaryBase58Decode, Func: runtimeDecodeBase58, 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.SystemBinarySerialize, Func: runtimeSerialize, Price: 100000, ParamCount: 1},
{Name: interopnames.SystemBlockchainGetBlock, Func: bcGetBlock, Price: 2500000,
Expand Down
12 changes: 12 additions & 0 deletions pkg/interop/binary/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,15 @@ func Base64Encode(b []byte) []byte {
func Base64Decode(b []byte) []byte {
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
}

0 comments on commit 9c72ea1

Please sign in to comment.