From 454689b8f6bec7f4d26d96e4806c8fbe480499e0 Mon Sep 17 00:00:00 2001 From: Edward Mack Date: Mon, 25 Oct 2021 09:31:42 -0400 Subject: [PATCH] feat(lib/runtime/wasmer): implement ext_default_child_storage_storage_kill_version_3 (#1878) --- lib/runtime/wasmer/imports.go | 64 ++++++++++++++++++++++++++---- lib/runtime/wasmer/imports_test.go | 48 ++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/lib/runtime/wasmer/imports.go b/lib/runtime/wasmer/imports.go index 4be947a08d..584d5d26ba 100644 --- a/lib/runtime/wasmer/imports.go +++ b/lib/runtime/wasmer/imports.go @@ -1142,19 +1142,67 @@ func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, ch return 0 } -//export ext_default_child_storage_storage_kill_version_3 -func ext_default_child_storage_storage_kill_version_3(context unsafe.Pointer, childStorageKeySpan, _ C.int64_t) C.int64_t { - logger.Debug("[ext_default_child_storage_storage_kill_version_3] executing...") - logger.Warn("[ext_default_child_storage_storage_kill_version_3] somewhat unimplemented") - // TODO: need to use `limit` parameter (#1793) +type noneRemain uint32 +type someRemain uint32 + +func (noneRemain) Index() uint { + return 0 +} +func (someRemain) Index() uint { + return 1 +} +//export ext_default_child_storage_storage_kill_version_3 +func ext_default_child_storage_storage_kill_version_3(context unsafe.Pointer, childStorageKeySpan, lim C.int64_t) C.int64_t { + logger.Debug("executing...") instanceContext := wasm.IntoInstanceContext(context) ctx := instanceContext.Data().(*runtime.Context) storage := ctx.Storage - childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan) - storage.DeleteChild(childStorageKey) - return 0 + + limitBytes := asMemorySlice(instanceContext, lim) + buf := &bytes.Buffer{} + buf.Write(limitBytes) + + limit, err := optional.NewBytes(true, nil).Decode(buf) + if err != nil { + logger.Warn("cannot generate limit", "error", err) + } + + deleted, all, err := storage.DeleteChildLimit(childStorageKey, limit) + if err != nil { + logger.Warn("cannot get child storage", "error", err) + return C.int64_t(0) + } + + vdt, err := scale.NewVaryingDataType(noneRemain(0), someRemain(0)) + if err != nil { + logger.Warn("cannot create new varying data type", "error", err) + } + + if all { + err = vdt.Set(noneRemain(deleted)) + } else { + err = vdt.Set(someRemain(deleted)) + } + if err != nil { + logger.Warn("cannot set varying data type", "error", err) + return C.int64_t(0) + } + + encoded, err := scale.Marshal(vdt) + if err != nil { + logger.Warn("problem marshaling varying data type", "error", err) + return C.int64_t(0) + } + + out, err := toWasmMemoryOptional(instanceContext, encoded) + if err != nil { + logger.Warn("failed to allocate", "error", err) + return 0 + } + + return C.int64_t(out) } //export ext_allocator_free_version_1 diff --git a/lib/runtime/wasmer/imports_test.go b/lib/runtime/wasmer/imports_test.go index 27b286fb8b..831f309dee 100644 --- a/lib/runtime/wasmer/imports_test.go +++ b/lib/runtime/wasmer/imports_test.go @@ -1226,6 +1226,54 @@ func Test_ext_default_child_storage_storage_kill_version_2_limit_none(t *testing require.Nil(t, child) } +func Test_ext_default_child_storage_storage_kill_version_3(t *testing.T) { + inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME) + + tr := trie.NewEmptyTrie() + tr.Put([]byte(`key2`), []byte(`value2`)) + tr.Put([]byte(`key1`), []byte(`value1`)) + tr.Put([]byte(`key3`), []byte(`value3`)) + err := inst.ctx.Storage.SetChild(testChildKey, tr) + require.NoError(t, err) + + testLimitBytes := make([]byte, 4) + binary.LittleEndian.PutUint32(testLimitBytes, uint32(2)) + optLimit2 := optional.NewBytes(true, testLimitBytes) + + testCases := []struct { + key []byte + limit *optional.Bytes + expected []byte + errMsg string + }{ + {key: []byte(`fakekey`), limit: optLimit2, expected: []byte{0, 0, 0, 0, 0}, errMsg: "Failed to call the `rtm_ext_default_child_storage_storage_kill_version_3` exported function."}, + {key: testChildKey, limit: optLimit2, expected: []byte{1, 2, 0, 0, 0}}, + {key: testChildKey, limit: nil, expected: []byte{0, 1, 0, 0, 0}}, + } + + for _, test := range testCases { + encChildKey, err := scale.Marshal(test.key) + require.NoError(t, err) + encOptLimit, err := test.limit.Encode() + require.NoError(t, err) + res, err := inst.Exec("rtm_ext_default_child_storage_storage_kill_version_3", append(encChildKey, encOptLimit...)) + if test.errMsg != "" { + require.Error(t, err) + require.EqualError(t, err, test.errMsg) + continue + } + + require.NoError(t, err) + + buf := &bytes.Buffer{} + buf.Write(res) + + read, err := new(optional.Bytes).Decode(buf) + require.NoError(t, err) + require.Equal(t, test.expected, read.Value()) + } +} + func Test_ext_storage_append_version_1(t *testing.T) { inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME)