core: add System.Binary.Base64Encode(Decode) interops

Part of #1055
This commit is contained in:
Anna Shaleva 2020-07-15 11:49:24 +03:00
parent f31ce9289d
commit 74d2f437f4
5 changed files with 72 additions and 2 deletions

View file

@ -9,8 +9,10 @@ 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": {
"Deserialize": {"System.Binary.Deserialize", false}, "Base64Decode": {"System.Binary.Base64Decode", false},
"Serialize": {"System.Binary.Serialize", false}, "Base64Encode": {"System.Binary.Base64Encode", false},
"Deserialize": {"System.Binary.Deserialize", false},
"Serialize": {"System.Binary.Serialize", false},
}, },
"blockchain": { "blockchain": {
"GetBlock": {"System.Blockchain.GetBlock", true}, "GetBlock": {"System.Blockchain.GetBlock", true},

View file

@ -2,6 +2,7 @@ package core
import ( import (
"bytes" "bytes"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"sort" "sort"
@ -192,3 +193,22 @@ func runtimeSerialize(_ *interop.Context, v *vm.VM) error {
func runtimeDeserialize(_ *interop.Context, v *vm.VM) error { func runtimeDeserialize(_ *interop.Context, v *vm.VM) error {
return vm.RuntimeDeserialize(v) return vm.RuntimeDeserialize(v)
} }
// runtimeEncode encodes top stack item into a base64 string.
func runtimeEncode(_ *interop.Context, v *vm.VM) error {
src := v.Estack().Pop().Bytes()
result := base64.StdEncoding.EncodeToString(src)
v.Estack().PushVal([]byte(result))
return nil
}
// runtimeDecode decodes top stack item from base64 string to byte array.
func runtimeDecode(_ *interop.Context, v *vm.VM) error {
src := string(v.Estack().Pop().Bytes())
result, err := base64.StdEncoding.DecodeString(src)
if err != nil {
return err
}
v.Estack().PushVal(result)
return nil
}

View file

@ -1,6 +1,7 @@
package core package core
import ( import (
"encoding/base64"
"fmt" "fmt"
"testing" "testing"
@ -214,6 +215,39 @@ func TestECDSAVerify(t *testing.T) {
}) })
} }
func TestRuntimeEncode(t *testing.T) {
str := []byte("my pretty string")
v, ic, bc := createVM(t)
defer bc.Close()
v.Estack().PushVal(str)
require.NoError(t, runtimeEncode(ic, v))
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, v))
actual := v.Estack().Pop().Bytes()
require.Equal(t, expected, actual)
})
t.Run("error", func(t *testing.T) {
v.Estack().PushVal(str + "%")
require.Error(t, runtimeDecode(ic, v))
})
}
// Helper functions to create VM, InteropContext, TX, Account, Contract. // Helper functions to create VM, InteropContext, TX, Account, Contract.
func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) { func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) {

View file

@ -69,6 +69,8 @@ func getInteropFromSlice(ic *interop.Context, slice []interop.Function) func(uin
// 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: "System.Binary.Base64Decode", Func: runtimeDecode, Price: 100000},
{Name: "System.Binary.Base64Encode", Func: runtimeEncode, Price: 100000},
{Name: "System.Binary.Deserialize", Func: runtimeDeserialize, Price: 500000}, {Name: "System.Binary.Deserialize", Func: runtimeDeserialize, Price: 500000},
{Name: "System.Binary.Serialize", Func: runtimeSerialize, Price: 100000}, {Name: "System.Binary.Serialize", Func: runtimeSerialize, Price: 100000},
{Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 2500000, {Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 2500000,

View file

@ -16,3 +16,15 @@ func Serialize(item interface{}) []byte {
func Deserialize(b []byte) interface{} { func Deserialize(b []byte) interface{} {
return nil return nil
} }
// Base64Encode encodes given byte slice into a base64 string and returns byte
// representation of this string. It uses `System.Binary.Base64Encode` interop.
func Base64Encode(b []byte) []byte {
return nil
}
// Base64Decode decodes given base64 string represented as a byte slice into
// byte slice. It uses `System.Binary.Base64Decode` interop.
func Base64Decode(b []byte) []byte {
return nil
}