Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement ext_default_child_storage_storage_kill_version_2 #1799

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
14ad9eb
add code to parse limit param
edwardmack Sep 7, 2021
30c33e1
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 20, 2021
d98c6b9
add optional encoding for limit
edwardmack Sep 20, 2021
630cf49
implement functionity for ext function
edwardmack Sep 21, 2021
1feedd1
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 21, 2021
ec158ed
lint
edwardmack Sep 21, 2021
b90978e
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 24, 2021
25eea72
implement trie.DeleteChildLimit function
edwardmack Sep 27, 2021
7729642
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 28, 2021
76397b3
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 29, 2021
f8d43d2
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Sep 30, 2021
d08925e
address PR comments
edwardmack Sep 30, 2021
6922869
update HOST_API_TEST_RUNTIME_URL to use master branch
edwardmack Oct 1, 2021
3a80c2a
lint
edwardmack Oct 1, 2021
309d672
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
noot Oct 5, 2021
29edd5e
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
noot Oct 5, 2021
7f9d279
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Oct 5, 2021
676ab7c
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Oct 6, 2021
4b318ff
combine parameters
edwardmack Oct 6, 2021
d66bcae
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
noot Oct 7, 2021
d9a233f
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
edwardmack Oct 7, 2021
e7924d7
Merge branch 'development' into ed/impl_ext_default_child_storage_sto…
noot Oct 7, 2021
eca7c15
add unit test for DeleteChildLimit
edwardmack Oct 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions lib/runtime/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ const (
POLKADOT_RUNTIME_URL = "https://github.com/noot/polkadot/blob/noot/v0.8.25/polkadot_runtime.wasm?raw=true"

// v0.8 test API wasm
HOST_API_TEST_RUNTIME = "hostapi_runtime"
HOST_API_TEST_RUNTIME_FP = "hostapi_runtime.compact.wasm"
HOST_API_TEST_RUNTIME_URL = "https://github.com/noot/polkadot-spec/blob/master/test/hostapi_runtime.compact.wasm?raw=true"
HOST_API_TEST_RUNTIME = "hostapi_runtime"
HOST_API_TEST_RUNTIME_FP = "hostapi_runtime.compact.wasm"
//HOST_API_TEST_RUNTIME_URL = "https://github.com/noot/polkadot-spec/blob/master/test/hostapi_runtime.compact.wasm?raw=true"
// todo (ed) use above URL once ed/add_rtm_ext_default_child_storage_storage_kill_version_2 has been merged to master
HOST_API_TEST_RUNTIME_URL = "https://github.com/noot/polkadot-spec/blob/ed/add_rtm_ext_default_child_storage_storage_kill_version_2/test/hostapi_runtime.compact.wasm?raw=true"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this ready to be merged?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, PR #2 on noot/polkadot-spec is ready to merge (if it looks good to you).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merged!


// v0.8 substrate runtime with modified name and babe C=(1, 1)
DEV_RUNTIME = "dev_runtime"
Expand Down
2 changes: 2 additions & 0 deletions lib/runtime/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package runtime
import (
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/common/optional"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/lib/transaction"
"github.com/ChainSafe/gossamer/lib/trie"
Expand Down Expand Up @@ -66,6 +67,7 @@ type Storage interface {
GetChildStorage(keyToChild, key []byte) ([]byte, error)
Delete(key []byte)
DeleteChild(keyToChild []byte)
DeleteChildLimit(keyToChild []byte, limit *optional.Bytes) (uint32, bool, error)
ClearChildStorage(keyToChild, key []byte) error
NextKey([]byte) []byte
ClearPrefixInChild(keyToChild, prefix []byte) error
Expand Down
39 changes: 39 additions & 0 deletions lib/runtime/storage/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ package storage

import (
"encoding/binary"
"sort"
"sync"

"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/common/optional"
"github.com/ChainSafe/gossamer/lib/trie"
)

Expand Down Expand Up @@ -178,6 +180,43 @@ func (s *TrieState) DeleteChild(key []byte) {
s.t.DeleteChild(key)
}

// DeleteChildLimit deletes up to limit of database entries by lexicographic order, return number
// deleted, true if all delete otherwise false
func (s *TrieState) DeleteChildLimit(key []byte, limit *optional.Bytes) (uint32, bool, error) {
noot marked this conversation as resolved.
Show resolved Hide resolved
s.lock.Lock()
defer s.lock.Unlock()
tr, err := s.t.GetChild(key)
if err != nil {
return 0, false, err
}
qtyEntries := uint32(len(tr.Entries()))
if limit == nil || !limit.Exists() {
s.t.DeleteChild(key)
return qtyEntries, true, nil
}
limitUint := binary.LittleEndian.Uint32(limit.Value())

keys := make([]string, 0, len(tr.Entries()))
for k := range tr.Entries() {
keys = append(keys, k)
}
sort.Strings(keys)
deleted := uint32(0)
for _, k := range keys {
tr.Delete([]byte(k))
deleted++
if deleted == limitUint {
break
}
}

if deleted == qtyEntries {
return deleted, true, nil
}

return deleted, false, nil
}

// ClearChildStorage removes the child storage entry from the trie
func (s *TrieState) ClearChildStorage(keyToChild, key []byte) error {
s.lock.Lock()
Expand Down
26 changes: 20 additions & 6 deletions lib/runtime/wasmer/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -1120,19 +1120,33 @@ func ext_default_child_storage_storage_kill_version_1(context unsafe.Pointer, ch
}

//export ext_default_child_storage_storage_kill_version_2
func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, childStorageKeySpan, _ C.int64_t) C.int32_t {
func ext_default_child_storage_storage_kill_version_2(context unsafe.Pointer, childStorageKeySpan C.int64_t, lim C.int64_t) C.int32_t {
logger.Debug("[ext_default_child_storage_storage_kill_version_2] executing...")
logger.Warn("[ext_default_child_storage_storage_kill_version_2] somewhat unimplemented")
// TODO: need to use `limit` parameter

instanceContext := wasm.IntoInstanceContext(context)
ctx := instanceContext.Data().(*runtime.Context)
storage := ctx.Storage

childStorageKey := asMemorySlice(instanceContext, childStorageKeySpan)
storage.DeleteChild(childStorageKey)

// note: this function always returns `KillStorageResult::AllRemoved`, which is 0
limitBytes := asMemorySlice(instanceContext, lim)
buf := &bytes.Buffer{}
buf.Write(limitBytes)

limit, err := optional.NewBytes(true, nil).Decode(buf)
if err != nil {
logger.Warn("[ext_default_child_storage_storage_kill_version_2] cannot generate limit", "error", err)
return 0
}

_, all, err := storage.DeleteChildLimit(childStorageKey, limit)
if err != nil {
logger.Warn("[ext_default_child_storage_storage_kill_version_2] cannot get child storage", "error", err)
}

if all {
return 1
}

return 0
}

Expand Down
95 changes: 95 additions & 0 deletions lib/runtime/wasmer/imports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package wasmer

import (
"bytes"
"encoding/binary"
"os"
"sort"
"testing"
Expand Down Expand Up @@ -1071,6 +1072,100 @@ func Test_ext_default_child_storage_storage_kill_version_1(t *testing.T) {
require.Nil(t, child)
}

func Test_ext_default_child_storage_storage_kill_version_2_limit_all(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`))
err := inst.ctx.Storage.SetChild(testChildKey, tr)
require.NoError(t, err)

// Confirm if value is set
child, err := inst.ctx.Storage.GetChild(testChildKey)
require.NoError(t, err)
require.NotNil(t, child)

encChildKey, err := scale.Encode(testChildKey)
require.NoError(t, err)

testLimit := uint32(2)
testLimitBytes := make([]byte, 4)
binary.LittleEndian.PutUint32(testLimitBytes, testLimit)

optLimit, err := optional.NewBytes(true, testLimitBytes).Encode()
require.NoError(t, err)

res, err := inst.Exec("rtm_ext_default_child_storage_storage_kill_version_2", append(encChildKey, optLimit...))
require.NoError(t, err)
require.Equal(t, []byte{0, 0, 0, 0}, res)

child, _ = inst.ctx.Storage.GetChild(testChildKey)
require.Nil(t, child)
}

func Test_ext_default_child_storage_storage_kill_version_2_limit_1(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`))
err := inst.ctx.Storage.SetChild(testChildKey, tr)
require.NoError(t, err)

// Confirm if value is set
child, err := inst.ctx.Storage.GetChild(testChildKey)
require.NoError(t, err)
require.NotNil(t, child)

encChildKey, err := scale.Encode(testChildKey)
require.NoError(t, err)

testLimit := uint32(1)
testLimitBytes := make([]byte, 4)
binary.LittleEndian.PutUint32(testLimitBytes, testLimit)

optLimit, err := optional.NewBytes(true, testLimitBytes).Encode()
require.NoError(t, err)

res, err := inst.Exec("rtm_ext_default_child_storage_storage_kill_version_2", append(encChildKey, optLimit...))
require.NoError(t, err)
require.Equal(t, []byte{0, 0, 0, 0}, res)

child, err = inst.ctx.Storage.GetChild(testChildKey)
require.NoError(t, err)
require.Equal(t, 1, len(child.Entries()))
}

func Test_ext_default_child_storage_storage_kill_version_2_limit_none(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`))
err := inst.ctx.Storage.SetChild(testChildKey, tr)
require.NoError(t, err)

// Confirm if value is set
child, err := inst.ctx.Storage.GetChild(testChildKey)
require.NoError(t, err)
require.NotNil(t, child)

encChildKey, err := scale.Encode(testChildKey)
require.NoError(t, err)

optLimit, err := optional.NewBytes(false, nil).Encode()
require.NoError(t, err)

res, err := inst.Exec("rtm_ext_default_child_storage_storage_kill_version_2", append(encChildKey, optLimit...))
require.NoError(t, err)
require.Equal(t, []byte{1, 0, 0, 0}, res)

child, err = inst.ctx.Storage.GetChild(testChildKey)
require.Error(t, err)
require.Nil(t, child)
}

func Test_ext_storage_append_version_1(t *testing.T) {
inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME)

Expand Down