Skip to content

Commit 96c30a6

Browse files
authored
feat: implement ext_offchain_index_set_version_1 for wasmer runtime (#1739)
* implement ext_offchain_index_set_version_1 * add storage to local * add baseDB to runtime context * add init base db for tests * add base db to node storage in tests * add base db to node storage for sync/test_helpers * use baseDB instead of creating new db * lint issues * address deep source issues * fix lint issues * add db check, rename var * add init BaseDB to createRuntimeStorage
1 parent ad2d85e commit 96c30a6

File tree

10 files changed

+106
-22
lines changed

10 files changed

+106
-22
lines changed

dot/core/test_helpers.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@ package core
1818

1919
import (
2020
"io/ioutil"
21+
"path/filepath"
2122
"testing"
2223

24+
coremocks "github.com/ChainSafe/gossamer/dot/core/mocks"
2325
"github.com/ChainSafe/gossamer/dot/network"
2426
"github.com/ChainSafe/gossamer/dot/state"
2527
"github.com/ChainSafe/gossamer/lib/common"
2628
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
2729
"github.com/ChainSafe/gossamer/lib/genesis"
2830
"github.com/ChainSafe/gossamer/lib/keystore"
31+
"github.com/ChainSafe/gossamer/lib/runtime"
2932
rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage"
3033
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
34+
"github.com/ChainSafe/gossamer/lib/utils"
3135
log "github.com/ChainSafe/log15"
32-
33-
coremocks "github.com/ChainSafe/gossamer/dot/core/mocks"
3436
"github.com/stretchr/testify/mock"
3537
"github.com/stretchr/testify/require"
3638
)
@@ -105,6 +107,17 @@ func NewTestService(t *testing.T, cfg *Config) *Service {
105107
rtCfg.CodeHash, err = cfg.StorageState.LoadCodeHash(nil)
106108
require.NoError(t, err)
107109

110+
nodeStorage := runtime.NodeStorage{}
111+
112+
if stateSrvc != nil {
113+
nodeStorage.BaseDB = stateSrvc.Base
114+
} else {
115+
nodeStorage.BaseDB, err = utils.SetupDatabase(filepath.Join(testDatadirPath, "offline_storage"), false)
116+
require.NoError(t, err)
117+
}
118+
119+
rtCfg.NodeStorage = nodeStorage
120+
108121
cfg.Runtime, err = wasmer.NewRuntimeFromGenesis(gen, rtCfg)
109122
require.NoError(t, err)
110123
}

dot/services.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ func createRuntimeStorage(st *state.Service) (*runtime.NodeStorage, error) {
9999
return &runtime.NodeStorage{
100100
LocalStorage: localStorage,
101101
PersistentStorage: chaindb.NewTable(st.DB(), "offlinestorage"),
102+
BaseDB: st.Base,
102103
}, nil
103104
}
104105

dot/state/base.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ func (s *BaseState) LoadCodeSubstitutedBlockHash() common.Hash {
125125
return common.NewHash(hash)
126126
}
127127

128+
// Put stores key/value pair in database
129+
func (s *BaseState) Put(key, value []byte) error {
130+
return s.db.Put(key, value)
131+
}
132+
133+
// Get retrieves value by key from database
134+
func (s *BaseState) Get(key []byte) ([]byte, error) {
135+
return s.db.Get(key)
136+
}
137+
128138
func (s *BaseState) storeSkipToEpoch(epoch uint64) error {
129139
buf := make([]byte, 8)
130140
binary.LittleEndian.PutUint64(buf, epoch)

dot/sync/test_helpers.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ package sync
1919
import (
2020
"io/ioutil"
2121
"math/big"
22+
"path/filepath"
2223
"testing"
2324
"time"
2425

25-
"github.com/stretchr/testify/mock"
26-
2726
"github.com/ChainSafe/gossamer/dot/state"
27+
syncmocks "github.com/ChainSafe/gossamer/dot/sync/mocks"
2828
"github.com/ChainSafe/gossamer/dot/types"
2929
"github.com/ChainSafe/gossamer/lib/babe"
3030
"github.com/ChainSafe/gossamer/lib/common"
@@ -34,11 +34,11 @@ import (
3434
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
3535
"github.com/ChainSafe/gossamer/lib/transaction"
3636
"github.com/ChainSafe/gossamer/lib/trie"
37+
"github.com/ChainSafe/gossamer/lib/utils"
3738
"github.com/ChainSafe/gossamer/pkg/scale"
3839
log "github.com/ChainSafe/log15"
40+
"github.com/stretchr/testify/mock"
3941
"github.com/stretchr/testify/require"
40-
41-
syncmocks "github.com/ChainSafe/gossamer/dot/sync/mocks"
4242
)
4343

4444
// NewMockFinalityGadget create and return sync FinalityGadget interface mock
@@ -100,6 +100,16 @@ func NewTestSyncer(t *testing.T, usePolkadotGenesis bool) *Service {
100100
rtCfg.CodeHash, err = cfg.StorageState.LoadCodeHash(nil)
101101
require.NoError(t, err)
102102

103+
nodeStorage := runtime.NodeStorage{}
104+
if stateSrvc != nil {
105+
nodeStorage.BaseDB = stateSrvc.Base
106+
} else {
107+
nodeStorage.BaseDB, err = utils.SetupDatabase(filepath.Join(testDatadirPath, "offline_storage"), false)
108+
require.NoError(t, err)
109+
}
110+
111+
rtCfg.NodeStorage = nodeStorage
112+
103113
instance, err := wasmer.NewRuntimeFromGenesis(gen, rtCfg) //nolint
104114
require.NoError(t, err)
105115
cfg.Runtime = instance

lib/babe/babe_test.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,25 @@ import (
2121
"io/ioutil"
2222
"math/big"
2323
"os"
24+
"path/filepath"
2425
"testing"
2526
"time"
2627

2728
"github.com/ChainSafe/gossamer/dot/core"
2829
"github.com/ChainSafe/gossamer/dot/state"
2930
"github.com/ChainSafe/gossamer/dot/types"
31+
"github.com/ChainSafe/gossamer/lib/babe/mocks"
3032
"github.com/ChainSafe/gossamer/lib/common"
3133
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
3234
"github.com/ChainSafe/gossamer/lib/genesis"
3335
"github.com/ChainSafe/gossamer/lib/runtime"
3436
rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage"
3537
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
3638
"github.com/ChainSafe/gossamer/lib/trie"
39+
"github.com/ChainSafe/gossamer/lib/utils"
3740
log "github.com/ChainSafe/log15"
38-
"github.com/stretchr/testify/require"
39-
40-
"github.com/ChainSafe/gossamer/lib/babe/mocks"
4141
mock "github.com/stretchr/testify/mock"
42+
"github.com/stretchr/testify/require"
4243
)
4344

4445
var (
@@ -100,15 +101,17 @@ func createTestService(t *testing.T, cfg *ServiceConfig) *Service {
100101
cfg.TransactionState = state.NewTransactionState()
101102
}
102103

104+
testDatadirPath, err := ioutil.TempDir("/tmp", "test-datadir-*") //nolint
105+
106+
var dbSrv *state.Service
103107
if cfg.BlockState == nil || cfg.StorageState == nil || cfg.EpochState == nil {
104-
testDatadirPath, err := ioutil.TempDir("/tmp", "test-datadir-*") //nolint
105108
require.NoError(t, err)
106109

107110
config := state.Config{
108111
Path: testDatadirPath,
109112
LogLevel: log.LvlInfo,
110113
}
111-
dbSrv := state.NewService(config)
114+
dbSrv = state.NewService(config)
112115
dbSrv.UseMemDB()
113116

114117
if cfg.EpochLength > 0 {
@@ -140,6 +143,16 @@ func createTestService(t *testing.T, cfg *ServiceConfig) *Service {
140143
rtCfg.CodeHash, err = storageState.LoadCodeHash(nil)
141144
require.NoError(t, err)
142145

146+
nodeStorage := runtime.NodeStorage{}
147+
if dbSrv != nil {
148+
nodeStorage.BaseDB = dbSrv.Base
149+
} else {
150+
nodeStorage.BaseDB, err = utils.SetupDatabase(filepath.Join(testDatadirPath, "offline_storage"), false)
151+
require.NoError(t, err)
152+
}
153+
154+
rtCfg.NodeStorage = nodeStorage
155+
143156
cfg.Runtime, err = wasmer.NewRuntimeFromGenesis(gen, rtCfg)
144157
require.NoError(t, err)
145158
}

lib/runtime/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const NodeStorageTypeLocal NodeStorageType = 2
3535
type NodeStorage struct {
3636
LocalStorage BasicStorage
3737
PersistentStorage BasicStorage
38+
BaseDB BasicStorage
3839
}
3940

4041
// SetLocal persists a key and value into LOCAL node storage

lib/runtime/wasmer/exports_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ func TestNodeRuntime_ValidateTransaction(t *testing.T) {
265265
cfg := &Config{}
266266
cfg.Storage = genState
267267
cfg.LogLvl = 4
268+
nodeStorage := runtime.NodeStorage{}
269+
nodeStorage.BaseDB = runtime.NewInMemoryDB(t)
270+
cfg.NodeStorage = nodeStorage
268271

269272
rt, err := NewRuntimeFromGenesis(gen, cfg)
270273
require.NoError(t, err)

lib/runtime/wasmer/imports.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ import (
133133
)
134134

135135
//export ext_logging_log_version_1
136-
func ext_logging_log_version_1(context unsafe.Pointer, level C.int32_t, targetData C.int64_t, msgData C.int64_t) {
136+
func ext_logging_log_version_1(context unsafe.Pointer, level C.int32_t, targetData, msgData C.int64_t) {
137137
logger.Trace("[ext_logging_log_version_1] executing...")
138138
instanceContext := wasm.IntoInstanceContext(context)
139139

@@ -319,7 +319,7 @@ func ext_crypto_ed25519_public_keys_version_1(context unsafe.Pointer, keyTypeID
319319
}
320320

321321
//export ext_crypto_ed25519_sign_version_1
322-
func ext_crypto_ed25519_sign_version_1(context unsafe.Pointer, keyTypeID C.int32_t, key C.int32_t, msg C.int64_t) C.int64_t {
322+
func ext_crypto_ed25519_sign_version_1(context unsafe.Pointer, keyTypeID, key C.int32_t, msg C.int64_t) C.int64_t {
323323
logger.Debug("[ext_crypto_ed25519_sign_version_1] executing...")
324324

325325
instanceContext := wasm.IntoInstanceContext(context)
@@ -872,7 +872,7 @@ func ext_misc_print_hex_version_1(context unsafe.Pointer, dataSpan C.int64_t) {
872872
}
873873

874874
//export ext_misc_print_num_version_1
875-
func ext_misc_print_num_version_1(context unsafe.Pointer, data C.int64_t) {
875+
func ext_misc_print_num_version_1(_ unsafe.Pointer, data C.int64_t) {
876876
logger.Trace("[ext_misc_print_num_version_1] executing...")
877877

878878
logger.Debug("[ext_misc_print_num_version_1]", "num", fmt.Sprintf("%d", int64(data)))
@@ -932,7 +932,7 @@ func ext_misc_runtime_version_version_1(context unsafe.Pointer, dataSpan C.int64
932932
}
933933

934934
//export ext_default_child_storage_read_version_1
935-
func ext_default_child_storage_read_version_1(context unsafe.Pointer, childStorageKey C.int64_t, key C.int64_t, valueOut C.int64_t, offset C.int32_t) C.int64_t {
935+
func ext_default_child_storage_read_version_1(context unsafe.Pointer, childStorageKey, key, valueOut C.int64_t, offset C.int32_t) C.int64_t {
936936
logger.Debug("[ext_default_child_storage_read_version_1] executing...")
937937

938938
instanceContext := wasm.IntoInstanceContext(context)
@@ -979,7 +979,7 @@ func ext_default_child_storage_clear_version_1(context unsafe.Pointer, childStor
979979
}
980980

981981
//export ext_default_child_storage_clear_prefix_version_1
982-
func ext_default_child_storage_clear_prefix_version_1(context unsafe.Pointer, childStorageKey C.int64_t, prefixSpan C.int64_t) {
982+
func ext_default_child_storage_clear_prefix_version_1(context unsafe.Pointer, childStorageKey, prefixSpan C.int64_t) {
983983
logger.Debug("[ext_default_child_storage_clear_prefix_version_1] executing...")
984984

985985
instanceContext := wasm.IntoInstanceContext(context)
@@ -996,7 +996,7 @@ func ext_default_child_storage_clear_prefix_version_1(context unsafe.Pointer, ch
996996
}
997997

998998
//export ext_default_child_storage_exists_version_1
999-
func ext_default_child_storage_exists_version_1(context unsafe.Pointer, childStorageKey C.int64_t, key C.int64_t) C.int32_t {
999+
func ext_default_child_storage_exists_version_1(context unsafe.Pointer, childStorageKey, key C.int64_t) C.int32_t {
10001000
logger.Debug("[ext_default_child_storage_exists_version_1] executing...")
10011001

10021002
instanceContext := wasm.IntoInstanceContext(context)
@@ -1036,7 +1036,7 @@ func ext_default_child_storage_get_version_1(context unsafe.Pointer, childStorag
10361036
}
10371037

10381038
//export ext_default_child_storage_next_key_version_1
1039-
func ext_default_child_storage_next_key_version_1(context unsafe.Pointer, childStorageKey C.int64_t, key C.int64_t) C.int64_t {
1039+
func ext_default_child_storage_next_key_version_1(context unsafe.Pointer, childStorageKey, key C.int64_t) C.int64_t {
10401040
logger.Debug("[ext_default_child_storage_next_key_version_1] executing...")
10411041

10421042
instanceContext := wasm.IntoInstanceContext(context)
@@ -1348,7 +1348,18 @@ func ext_hashing_twox_64_version_1(context unsafe.Pointer, dataSpan C.int64_t) C
13481348
//export ext_offchain_index_set_version_1
13491349
func ext_offchain_index_set_version_1(context unsafe.Pointer, keySpan, valueSpan C.int64_t) {
13501350
logger.Trace("[ext_offchain_index_set_version_1] executing...")
1351-
logger.Warn("[ext_offchain_index_set_version_1] unimplemented")
1351+
instanceContext := wasm.IntoInstanceContext(context)
1352+
runtimeCtx := instanceContext.Data().(*runtime.Context)
1353+
1354+
storageKey := asMemorySlice(instanceContext, keySpan)
1355+
newValue := asMemorySlice(instanceContext, valueSpan)
1356+
cp := make([]byte, len(newValue))
1357+
copy(cp, newValue)
1358+
1359+
err := runtimeCtx.NodeStorage.BaseDB.Put(storageKey, cp)
1360+
if err != nil {
1361+
logger.Error("[ext_offchain_index_set_version_1] failed to set value in raw storage", "error", err)
1362+
}
13521363
}
13531364

13541365
//export ext_offchain_local_storage_clear_version_1
@@ -1573,14 +1584,14 @@ func storageAppend(storage runtime.Storage, key, valueToAppend []byte) error {
15731584
nextLength = big.NewInt(0).Add(currLength, big.NewInt(1))
15741585
}
15751586

1576-
lengthEnc, err := scale.Encode(nextLength)
1587+
finalVal, err := scale.Encode(nextLength)
15771588
if err != nil {
15781589
logger.Trace("[ext_storage_append_version_1] failed to encode new length", "error", err)
15791590
return err
15801591
}
15811592

15821593
// append new length prefix to start of items array
1583-
finalVal := append(lengthEnc, valueRes...)
1594+
finalVal = append(finalVal, valueRes...)
15841595
logger.Debug("[ext_storage_append_version_1]", "resulting value", fmt.Sprintf("0x%x", finalVal))
15851596
storage.Set(key, finalVal)
15861597
return nil
@@ -1794,7 +1805,7 @@ func ext_storage_root_version_1(context unsafe.Pointer) C.int64_t {
17941805
}
17951806

17961807
//export ext_storage_set_version_1
1797-
func ext_storage_set_version_1(context unsafe.Pointer, keySpan C.int64_t, valueSpan C.int64_t) {
1808+
func ext_storage_set_version_1(context unsafe.Pointer, keySpan, valueSpan C.int64_t) {
17981809
logger.Trace("[ext_storage_set_version_1] executing...")
17991810

18001811
instanceContext := wasm.IntoInstanceContext(context)

lib/runtime/wasmer/imports_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,27 @@ func Test_ext_storage_set_version_1(t *testing.T) {
409409
require.Equal(t, testvalue, val)
410410
}
411411

412+
func Test_ext_offline_index_set_version_1(t *testing.T) {
413+
// TODO this currently fails with error could nat find exported function, determine how else to test this
414+
t.Skip()
415+
inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME)
416+
417+
testkey := []byte("noot")
418+
testvalue := []byte("washere")
419+
420+
encKey, err := scale.Encode(testkey)
421+
require.NoError(t, err)
422+
encValue, err := scale.Encode(testvalue)
423+
require.NoError(t, err)
424+
425+
_, err = inst.Exec("rtm_ext_offline_index_set_version_1", append(encKey, encValue...))
426+
require.NoError(t, err)
427+
428+
val, err := inst.ctx.NodeStorage.PersistentStorage.Get(testkey)
429+
require.NoError(t, err)
430+
require.Equal(t, testvalue, val)
431+
}
432+
412433
func Test_ext_crypto_ed25519_generate_version_1(t *testing.T) {
413434
inst := NewTestInstance(t, runtime.HOST_API_TEST_RUNTIME)
414435

lib/runtime/wasmer/test_helpers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func setupConfig(t *testing.T, targetRuntime string, tt *trie.Trie, lvl log.Lvl,
7171
ns := runtime.NodeStorage{
7272
LocalStorage: runtime.NewInMemoryDB(t),
7373
PersistentStorage: runtime.NewInMemoryDB(t), // we're using a local storage here since this is a test runtime
74+
BaseDB: runtime.NewInMemoryDB(t), // we're using a local storage here since this is a test runtime
7475
}
7576
cfg := &Config{
7677
Imports: ImportsNodeRuntime,

0 commit comments

Comments
 (0)