From 1df4b5d88cad11f427a6b93af54f638a1bd4b637 Mon Sep 17 00:00:00 2001 From: Timothy Wu Date: Wed, 21 Jun 2023 01:14:52 -0400 Subject: [PATCH] instance_tests, move genesis to runtime --- dot/core/helpers_test.go | 6 +- dot/digest/helpers_test.go | 4 +- dot/helpers_test.go | 4 +- dot/node.go | 3 +- dot/node_integration_test.go | 2 +- dot/rpc/helpers_test.go | 4 +- dot/rpc/modules/helpers_test.go | 4 +- dot/state/helpers_test.go | 4 +- dot/sync/syncer_integration_test.go | 2 +- lib/babe/helpers_test.go | 4 +- lib/runtime/{wasmer => }/genesis.go | 2 +- lib/runtime/{wasmer => }/genesis_test.go | 2 +- lib/runtime/wasmer/exports_test.go | 10 +- lib/runtime/wazero/imports.go | 18 +- lib/runtime/wazero/imports_test.go | 28 - lib/runtime/wazero/instance.go | 52 +- lib/runtime/wazero/instance_test.go | 1222 +++++++++++++++++ .../wazero/testdata/digest.kusama.1482002.zip | Bin 0 -> 12591 bytes lib/runtime/wazero/testdata/digests.go | 42 + 19 files changed, 1346 insertions(+), 67 deletions(-) rename lib/runtime/{wasmer => }/genesis.go (98%) rename lib/runtime/{wasmer => }/genesis_test.go (99%) create mode 100644 lib/runtime/wazero/instance_test.go create mode 100644 lib/runtime/wazero/testdata/digest.kusama.1482002.zip create mode 100644 lib/runtime/wazero/testdata/digests.go diff --git a/dot/core/helpers_test.go b/dot/core/helpers_test.go index 27c40dbdff..b5fb19ffa1 100644 --- a/dot/core/helpers_test.go +++ b/dot/core/helpers_test.go @@ -47,7 +47,7 @@ func createTestService(t *testing.T, genesisFilePath string, gen, err := genesis.NewGenesisFromJSONRaw(genesisFilePath) require.NoError(t, err) - genesisTrie, err := wasmer.NewTrieFromGenesis(*gen) + genesisTrie, err := runtime.NewTrieFromGenesis(*gen) require.NoError(t, err) // Extrinsic and context related stuff @@ -266,7 +266,7 @@ func newWestendLocalWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) @@ -287,7 +287,7 @@ func getWestendDevRuntimeCode(t *testing.T) (code []byte) { westendDevGenesis, err := genesis.NewGenesisFromJSONRaw(path) require.NoError(t, err) - genesisTrie, err := wasmer.NewTrieFromGenesis(*westendDevGenesis) + genesisTrie, err := runtime.NewTrieFromGenesis(*westendDevGenesis) require.NoError(t, err) trieState := rtstorage.NewTrieState(&genesisTrie) diff --git a/dot/digest/helpers_test.go b/dot/digest/helpers_test.go index ab0c91826e..10298488a9 100644 --- a/dot/digest/helpers_test.go +++ b/dot/digest/helpers_test.go @@ -9,7 +9,7 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" "github.com/stretchr/testify/require" @@ -24,7 +24,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/dot/helpers_test.go b/dot/helpers_test.go index 29f6b8312a..88a22bbb37 100644 --- a/dot/helpers_test.go +++ b/dot/helpers_test.go @@ -12,7 +12,7 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + runtime "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" "github.com/stretchr/testify/require" @@ -38,7 +38,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/dot/node.go b/dot/node.go index 1a9374647f..214d119df7 100644 --- a/dot/node.go +++ b/dot/node.go @@ -33,7 +33,6 @@ import ( "github.com/ChainSafe/gossamer/lib/grandpa" "github.com/ChainSafe/gossamer/lib/keystore" "github.com/ChainSafe/gossamer/lib/runtime" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" "github.com/ChainSafe/gossamer/lib/services" "github.com/ChainSafe/gossamer/lib/utils" ) @@ -149,7 +148,7 @@ func (*nodeBuilder) initNode(config *cfg.Config) error { } // create trie from genesis - t, err := wasmer.NewTrieFromGenesis(*gen) + t, err := runtime.NewTrieFromGenesis(*gen) if err != nil { return fmt.Errorf("failed to create trie from genesis: %w", err) } diff --git a/dot/node_integration_test.go b/dot/node_integration_test.go index cfb1be0aa7..77132d2c14 100644 --- a/dot/node_integration_test.go +++ b/dot/node_integration_test.go @@ -99,7 +99,7 @@ func TestNewNode(t *testing.T) { return nil, fmt.Errorf("failed to load genesis from file: %w", err) } // create trie from genesis - trie, err := wasmer.NewTrieFromGenesis(*gen) + trie, err := runtime.NewTrieFromGenesis(*gen) if err != nil { return nil, fmt.Errorf("failed to create trie from genesis: %w", err) } diff --git a/dot/rpc/helpers_test.go b/dot/rpc/helpers_test.go index 26633eed29..0e981800d2 100644 --- a/dot/rpc/helpers_test.go +++ b/dot/rpc/helpers_test.go @@ -9,7 +9,7 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" "github.com/stretchr/testify/require" @@ -24,7 +24,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/dot/rpc/modules/helpers_test.go b/dot/rpc/modules/helpers_test.go index 41e9708253..fad1310ce0 100644 --- a/dot/rpc/modules/helpers_test.go +++ b/dot/rpc/modules/helpers_test.go @@ -8,7 +8,7 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" "github.com/stretchr/testify/require" @@ -31,7 +31,7 @@ func newWestendLocalGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/dot/state/helpers_test.go b/dot/state/helpers_test.go index 98156691e1..44abfc4de5 100644 --- a/dot/state/helpers_test.go +++ b/dot/state/helpers_test.go @@ -11,7 +11,7 @@ import ( "github.com/ChainSafe/gossamer/dot/types" "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/genesis" - "github.com/ChainSafe/gossamer/lib/runtime/wasmer" + "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/trie" "github.com/ChainSafe/gossamer/lib/utils" "github.com/stretchr/testify/require" @@ -98,7 +98,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/dot/sync/syncer_integration_test.go b/dot/sync/syncer_integration_test.go index 76a6e816ed..2f2fc1fcfd 100644 --- a/dot/sync/syncer_integration_test.go +++ b/dot/sync/syncer_integration_test.go @@ -130,7 +130,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) parentHash := common.NewHash([]byte{0}) diff --git a/lib/babe/helpers_test.go b/lib/babe/helpers_test.go index 9839d3254f..e262545fc2 100644 --- a/lib/babe/helpers_test.go +++ b/lib/babe/helpers_test.go @@ -365,7 +365,7 @@ func newWestendLocalGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) genesisHeader = *types.NewHeader(common.NewHash([]byte{0}), @@ -384,7 +384,7 @@ func newWestendDevGenesisWithTrieAndHeader(t *testing.T) ( require.NoError(t, err) gen = *genesisPtr - genesisTrie, err = wasmer.NewTrieFromGenesis(gen) + genesisTrie, err = runtime.NewTrieFromGenesis(gen) require.NoError(t, err) genesisHeader = *types.NewHeader(common.NewHash([]byte{0}), diff --git a/lib/runtime/wasmer/genesis.go b/lib/runtime/genesis.go similarity index 98% rename from lib/runtime/wasmer/genesis.go rename to lib/runtime/genesis.go index 7c9883fcf3..5912886bf1 100644 --- a/lib/runtime/wasmer/genesis.go +++ b/lib/runtime/genesis.go @@ -1,7 +1,7 @@ // Copyright 2022 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package wasmer +package runtime import ( "errors" diff --git a/lib/runtime/wasmer/genesis_test.go b/lib/runtime/genesis_test.go similarity index 99% rename from lib/runtime/wasmer/genesis_test.go rename to lib/runtime/genesis_test.go index b261f4e397..6c68683b4b 100644 --- a/lib/runtime/wasmer/genesis_test.go +++ b/lib/runtime/genesis_test.go @@ -1,7 +1,7 @@ // Copyright 2022 ChainSafe Systems (ON) // SPDX-License-Identifier: LGPL-3.0-only -package wasmer +package runtime import ( "testing" diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go index 6e7e709bdb..18f2b9ba91 100644 --- a/lib/runtime/wasmer/exports_test.go +++ b/lib/runtime/wasmer/exports_test.go @@ -46,7 +46,7 @@ func Test_Instance_Version(t *testing.T) { instanceBuilder: func(t *testing.T) instanceVersioner { genesisPath := utils.GetKusamaGenesisPath(t) kusamaGenesis := genesisFromRawJSON(t, genesisPath) - genesisTrie, err := NewTrieFromGenesis(kusamaGenesis) + genesisTrie, err := runtime.NewTrieFromGenesis(kusamaGenesis) require.NoError(t, err) cfg := Config{ @@ -170,7 +170,7 @@ func balanceKey(t *testing.T, pub []byte) []byte { func TestWestendRuntime_ValidateTransaction(t *testing.T) { genesisPath := utils.GetWestendDevRawGenesisPath(t) gen := genesisFromRawJSON(t, genesisPath) - genTrie, err := NewTrieFromGenesis(gen) + genTrie, err := runtime.NewTrieFromGenesis(gen) require.NoError(t, err) // set state to genesis state @@ -472,7 +472,7 @@ func TestInstance_ExecuteBlock_WestendRuntime(t *testing.T) { func TestInstance_ApplyExtrinsic_WestendRuntime(t *testing.T) { genesisPath := utils.GetWestendDevRawGenesisPath(t) gen := genesisFromRawJSON(t, genesisPath) - genTrie, err := NewTrieFromGenesis(gen) + genTrie, err := runtime.NewTrieFromGenesis(gen) require.NoError(t, err) // set state to genesis state @@ -529,7 +529,7 @@ func TestInstance_ExecuteBlock_PolkadotRuntime(t *testing.T) { func TestInstance_ExecuteBlock_PolkadotRuntime_PolkadotBlock1(t *testing.T) { genesisPath := utils.GetPolkadotGenesisPath(t) gen := genesisFromRawJSON(t, genesisPath) - genTrie, err := NewTrieFromGenesis(gen) + genTrie, err := runtime.NewTrieFromGenesis(gen) require.NoError(t, err) expectedGenesisRoot := common.MustHexToHash("0x29d0d972cd27cbc511e9589fcb7a4506d5eb6a9e8df205f00472e5ab354a4e17") @@ -579,7 +579,7 @@ func TestInstance_ExecuteBlock_PolkadotRuntime_PolkadotBlock1(t *testing.T) { func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1(t *testing.T) { genesisPath := utils.GetKusamaGenesisPath(t) gen := genesisFromRawJSON(t, genesisPath) - genTrie, err := NewTrieFromGenesis(gen) + genTrie, err := runtime.NewTrieFromGenesis(gen) require.NoError(t, err) expectedGenesisRoot := common.MustHexToHash("0xb0006203c3a6e6bd2c6a17b1d4ae8ca49a31da0f4579da950b127774b44aef6b") diff --git a/lib/runtime/wazero/imports.go b/lib/runtime/wazero/imports.go index cb468d0718..8cd02cde61 100644 --- a/lib/runtime/wazero/imports.go +++ b/lib/runtime/wazero/imports.go @@ -1713,15 +1713,11 @@ func ext_offchain_submit_transaction_version_1(ctx context.Context, m api.Module } func ext_offchain_timestamp_version_1(ctx context.Context, m api.Module) uint64 { - logger.Trace("executing...") - now := time.Now().Unix() return uint64(now) } func ext_offchain_sleep_until_version_1(ctx context.Context, m api.Module, deadline uint64) { - logger.Trace("executing...") - dur := time.Until(time.UnixMilli(int64(deadline))) if dur > 0 { time.Sleep(dur) @@ -2038,7 +2034,12 @@ func ext_storage_get_version_1(ctx context.Context, m api.Module, keySpan uint64 value := storage.Get(key) logger.Debugf("value: 0x%x", value) - valueSpan, err := write(m, rtCtx.Allocator, scale.MustMarshal(&value)) + var option *[]byte + if value != nil { + option = &value + } + + valueSpan, err := write(m, rtCtx.Allocator, scale.MustMarshal(option)) if err != nil { logger.Errorf("failed to allocate: %s", err) panic(err) @@ -2060,7 +2061,12 @@ func ext_storage_next_key_version_1(ctx context.Context, m api.Module, keySpan u "key: 0x%x; next key 0x%x", key, next) - nextSpan, err := write(m, rtCtx.Allocator, scale.MustMarshal(&next)) + var option *[]byte + if len(next) > 0 { + option = &next + } + + nextSpan, err := write(m, rtCtx.Allocator, scale.MustMarshal(option)) if err != nil { logger.Errorf("failed to allocate: %s", err) panic(err) diff --git a/lib/runtime/wazero/imports_test.go b/lib/runtime/wazero/imports_test.go index 649f58fbe3..2a255ff263 100644 --- a/lib/runtime/wazero/imports_test.go +++ b/lib/runtime/wazero/imports_test.go @@ -28,7 +28,6 @@ import ( "github.com/ChainSafe/gossamer/lib/trie/proof" "github.com/ChainSafe/gossamer/pkg/scale" "github.com/golang/mock/gomock" - "github.com/klauspost/compress/zstd" "github.com/stretchr/testify/require" ) @@ -91,27 +90,8 @@ func NewTestInstanceWithTrie(t *testing.T, targetRuntime string, tt *trie.Trie) return r } -func decompressWasm(code []byte) ([]byte, error) { - compressionFlag := []byte{82, 188, 83, 118, 70, 219, 142, 5} - if !bytes.HasPrefix(code, compressionFlag) { - return code, nil - } - - decoder, err := zstd.NewReader(nil) - if err != nil { - return nil, fmt.Errorf("creating zstd reader: %s", err) - } - bytes, err := decoder.DecodeAll(code[len(compressionFlag):], nil) - if err != nil { - return nil, err - } - return bytes, err -} - // NewInstanceFromFile instantiates a runtime from a .wasm file func NewInstanceFromFile(fp string, cfg Config) (*Instance, error) { - fmt.Println(fp) - // Reads the WebAssembly module as bytes. // Retrieve WASM binary bytes, err := ioutil.ReadFile(fp) @@ -119,14 +99,6 @@ func NewInstanceFromFile(fp string, cfg Config) (*Instance, error) { return nil, fmt.Errorf("Failed to read wasm file: %s", err) } - if strings.Contains(fp, "compact") { - var err error - bytes, err = decompressWasm(bytes) - if err != nil { - return nil, err - } - } - return NewInstance(bytes, cfg) } diff --git a/lib/runtime/wazero/instance.go b/lib/runtime/wazero/instance.go index f18baa34ec..00a6ce8cc7 100644 --- a/lib/runtime/wazero/instance.go +++ b/lib/runtime/wazero/instance.go @@ -17,6 +17,7 @@ import ( "github.com/ChainSafe/gossamer/lib/runtime/offchain" "github.com/ChainSafe/gossamer/lib/transaction" "github.com/ChainSafe/gossamer/pkg/scale" + "github.com/klauspost/compress/zstd" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" ) @@ -50,8 +51,27 @@ type Config struct { CodeHash common.Hash } +func decompressWasm(code []byte) ([]byte, error) { + compressionFlag := []byte{82, 188, 83, 118, 70, 219, 142, 5} + if !bytes.HasPrefix(code, compressionFlag) { + return code, nil + } + + decoder, err := zstd.NewReader(nil) + if err != nil { + return nil, fmt.Errorf("creating zstd reader: %s", err) + } + bytes, err := decoder.DecodeAll(code[len(compressionFlag):], nil) + if err != nil { + return nil, err + } + return bytes, err +} + // NewInstance instantiates a runtime from raw wasm bytecode func NewInstance(code []byte, cfg Config) (instance *Instance, err error) { + logger.Patch(log.SetLevel(cfg.LogLvl), log.SetCallerFunc(true)) + ctx := context.Background() rt := wazero.NewRuntime(ctx) @@ -328,19 +348,27 @@ func NewInstance(code []byte, cfg Config) (instance *Instance, err error) { panic(err) } + code, err = decompressWasm(code) + if err != nil { + return nil, err + } + mod, err := rt.Instantiate(ctx, code) if err != nil { - panic(err) + return nil, err } global := mod.ExportedGlobal("__heap_base") if global == nil { - panic("huh?") + return nil, fmt.Errorf("wazero error: nil global for __heap_base") } + hb := api.DecodeU32(global.Get()) + // hb = runtime.DefaultHeapBase + mem := mod.Memory() if mem == nil { - panic("wtf?") + return nil, fmt.Errorf("wazero error: nil memory for module") } allocator := runtime.NewAllocator(mem, hb) @@ -378,6 +406,9 @@ func (i *Instance) Exec(function string, data []byte) (result []byte, err error) // Store the data into memory mem := i.Module.Memory() + if mem == nil { + panic("nil memory") + } ok := mem.Write(inputPtr, data) if !ok { panic("wtf?") @@ -389,7 +420,8 @@ func (i *Instance) Exec(function string, data []byte) (result []byte, err error) } ctx := context.WithValue(context.Background(), runtimeContextKey, i.Context) - values, err := runtimeFunc.Call(ctx, uint64(inputPtr), uint64(dataLength)) + + values, err := runtimeFunc.Call(ctx, api.EncodeI32(int32(inputPtr)), api.EncodeI32(int32(dataLength))) if err != nil { return nil, fmt.Errorf("running runtime function: %w", err) } @@ -737,9 +769,15 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( return nil } -func (in *Instance) RandomSeed() {} -func (in *Instance) OffchainWorker() {} -func (in *Instance) GenerateSessionKeys() {} +func (in *Instance) RandomSeed() { + panic("unimplemented") +} +func (in *Instance) OffchainWorker() { + panic("unimplemented") +} +func (in *Instance) GenerateSessionKeys() { + panic("unimplemented") +} // GetCodeHash returns the code of the instance func (in *Instance) GetCodeHash() common.Hash { diff --git a/lib/runtime/wazero/instance_test.go b/lib/runtime/wazero/instance_test.go new file mode 100644 index 0000000000..052d6852a9 --- /dev/null +++ b/lib/runtime/wazero/instance_test.go @@ -0,0 +1,1222 @@ +// Copyright 2021 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package wazero_runtime + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/internal/log" + "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/genesis" + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/ChainSafe/gossamer/lib/runtime/storage" + "github.com/ChainSafe/gossamer/lib/runtime/wazero/testdata" + "github.com/ChainSafe/gossamer/lib/trie" + "github.com/ChainSafe/gossamer/lib/utils" + "github.com/ChainSafe/gossamer/pkg/scale" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// NewRuntimeFromGenesis creates a runtime instance from the genesis data +func NewRuntimeFromGenesis(cfg Config) (instance *Instance, err error) { + if cfg.Storage == nil { + return nil, errors.New("storage is nil") + } + + code := cfg.Storage.LoadCode() + if len(code) == 0 { + return nil, fmt.Errorf("cannot find :code in state") + } + + return NewInstance(code, cfg) +} + +// NewInstanceFromTrie returns a new runtime instance with the code provided in the given trie +func NewInstanceFromTrie(t *trie.Trie, cfg Config) (*Instance, error) { + code := t.Get(common.CodeKey) + if len(code) == 0 { + return nil, fmt.Errorf("cannot find :code in trie") + } + + return NewInstance(code, cfg) +} + +func mustHexTo64BArray(t *testing.T, inputHex string) (outputArray [64]byte) { + t.Helper() + copy(outputArray[:], common.MustHexToBytes(inputHex)) + return outputArray +} + +func genesisFromRawJSON(t *testing.T, jsonFilepath string) (gen genesis.Genesis) { + t.Helper() + + fp, err := filepath.Abs(jsonFilepath) + require.NoError(t, err) + + data, err := os.ReadFile(filepath.Clean(fp)) + require.NoError(t, err) + + err = json.Unmarshal(data, &gen) + require.NoError(t, err) + + return gen +} + +// this is generated by printing key ownership proof while running `test_generate_equivocation_report_blob` +// https://github.com/paritytech/substrate/blob/ded44948e2d5a398abcb4e342b0513cb690961bb/frame/grandpa/src/benchmarking.rs#L85 +var testKeyOwnershipProof types.OpaqueKeyOwnershipProof = types.OpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) //nolint:lll + +func Test_Instance_Version(t *testing.T) { + type instanceVersioner interface { + Version() (runtime.Version, error) + } + + testCases := map[string]struct { + instanceBuilder func(t *testing.T) instanceVersioner + expectedVersion runtime.Version + }{ + "kusama": { + instanceBuilder: func(t *testing.T) instanceVersioner { + genesisPath := utils.GetKusamaGenesisPath(t) + kusamaGenesis := genesisFromRawJSON(t, genesisPath) + genesisTrie, err := runtime.NewTrieFromGenesis(kusamaGenesis) + require.NoError(t, err) + + cfg := Config{ + Storage: storage.NewTrieState(&genesisTrie), + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + return instance + }, + expectedVersion: runtime.Version{ + SpecName: []byte("kusama"), + ImplName: []byte("parity-kusama"), + AuthoringVersion: 2, + SpecVersion: 1020, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x2}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x4}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x1}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x1}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x2}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x1}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + }, + }, + }, + "polkadot_v0929": { + instanceBuilder: func(t *testing.T) instanceVersioner { + return NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + }, + expectedVersion: runtime.Version{ + SpecName: []byte("polkadot"), + ImplName: []byte("parity-polkadot"), + AuthoringVersion: 0, + SpecVersion: 9290, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x4}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x6}, + {Name: [8]uint8{0x17, 0xa6, 0xbc, 0xd, 0x0, 0x62, 0xae, 0xb3}, Ver: 0x1}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x3}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x2}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x2}, + {Name: [8]uint8{0x49, 0xea, 0xaf, 0x1b, 0x54, 0x8a, 0xc, 0xb0}, Ver: 0x1}, + {Name: [8]uint8{0x91, 0xd5, 0xdf, 0x18, 0xb0, 0xd2, 0xcf, 0x58}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x3}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x2}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + {Name: [8]uint8{0xf3, 0xff, 0x14, 0xd5, 0xab, 0x52, 0x70, 0x59}, Ver: 0x1}, + }, + TransactionVersion: 14, + }, + }, + "westend_v0929": { + instanceBuilder: func(t *testing.T) instanceVersioner { + return NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + }, + expectedVersion: runtime.Version{ + SpecName: []byte("westend"), + ImplName: []byte("parity-westend"), + AuthoringVersion: 2, + SpecVersion: 9290, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x4}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x6}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x3}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x2}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x2}, + {Name: [8]uint8{0x49, 0xea, 0xaf, 0x1b, 0x54, 0x8a, 0xc, 0xb0}, Ver: 0x1}, + {Name: [8]uint8{0x91, 0xd5, 0xdf, 0x18, 0xb0, 0xd2, 0xcf, 0x58}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x3}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x2}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + {Name: [8]uint8{0xf3, 0xff, 0x14, 0xd5, 0xab, 0x52, 0x70, 0x59}, Ver: 0x1}, + {Name: [8]uint8{0x17, 0xa6, 0xbc, 0xd, 0x0, 0x62, 0xae, 0xb3}, Ver: 0x1}, + }, + TransactionVersion: 12, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + instance := testCase.instanceBuilder(t) + version, err := instance.Version() + require.NoError(t, err) + assert.Equal(t, testCase.expectedVersion, version) + }) + } +} + +func balanceKey(t *testing.T, pub []byte) []byte { + h0, err := common.Twox128Hash([]byte("System")) + require.NoError(t, err) + h1, err := common.Twox128Hash([]byte("Account")) + require.NoError(t, err) + h2, err := common.Blake2b128(pub) + require.NoError(t, err) + return append(append(append(h0, h1...), h2...), pub...) +} + +func TestWestendRuntime_ValidateTransaction(t *testing.T) { + genesisPath := utils.GetWestendDevRawGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + nodeStorage := runtime.NodeStorage{} + nodeStorage.BaseDB = runtime.NewInMemoryDB(t) + cfg.NodeStorage = nodeStorage + + rt, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + alicePub := common.MustHexToBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d") + aliceBalanceKey := balanceKey(t, alicePub) + + accInfo := types.AccountInfo{ + Nonce: 0, + Data: types.AccountData{ + Free: scale.MustNewUint128(big.NewInt(1152921504606846976)), + Reserved: scale.MustNewUint128(big.NewInt(0)), + MiscFrozen: scale.MustNewUint128(big.NewInt(0)), + FreeFrozen: scale.MustNewUint128(big.NewInt(0)), + }, + } + + encBal, err := scale.Marshal(accInfo) + require.NoError(t, err) + + rt.Context.Storage.Put(aliceBalanceKey, encBal) + // this key is System.UpgradedToDualRefCount -> set to true since all accounts have been upgraded to v0.9 format + rt.Context.Storage.Put(common.UpgradedToDualRefKey, []byte{1}) + + genesisHeader := &types.Header{ + Number: 0, + StateRoot: genTrie.MustHash(), + } + + extHex := runtime.NewTestExtrinsic(t, rt, genesisHeader.Hash(), genesisHeader.Hash(), + 0, signature.TestKeyringPairAlice, "System.remark", []byte{0xab, 0xcd}) + + genesisHashBytes := genesisHeader.Hash().ToBytes() + + validateTransactionArguments := [][]byte{ + {byte(types.TxnExternal)}, + common.MustHexToBytes(extHex), + genesisHashBytes} + + extrinsicsBytes := bytes.Join(validateTransactionArguments, nil) + + runtime.InitializeRuntimeToTest(t, rt, genesisHeader) + _, err = rt.ValidateTransaction(extrinsicsBytes) + require.NoError(t, err) +} + +func TestInstance_GrandpaAuthorities_NodeRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + auths, err := rt.GrandpaAuthorities() + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := ed25519.NewPublicKey(authABytes) + authB, _ := ed25519.NewPublicKey(authBBytes) + + expected := []types.Authority{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + require.Equal(t, expected, auths) +} + +func TestInstance_GrandpaAuthorities_PolkadotRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.POLKADOT_RUNTIME_v0929, tt) + + auths, err := rt.GrandpaAuthorities() + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := ed25519.NewPublicKey(authABytes) + authB, _ := ed25519.NewPublicKey(authBBytes) + + expected := []types.Authority{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + require.Equal(t, expected, auths) +} + +func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { + testCases := []struct { + name string + targetRuntime string + }{ + { + name: "with_polkadot_runtime", + targetRuntime: runtime.POLKADOT_RUNTIME_v0929, + }, + { + name: "with_westend_runtime", + targetRuntime: runtime.WESTEND_RUNTIME_v0929, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + tt := trie.NewEmptyTrie() + + randomnessValue, err := common.HexToHash("0x01") + require.NoError(t, err) + key := common.MustHexToBytes(genesis.BABERandomnessKeyHex) + tt.Put(key, randomnessValue[:]) + + authorityValue, err := common.HexToBytes("0x08eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key = common.MustHexToBytes(genesis.BABEAuthoritiesKeyHex) + tt.Put(key, authorityValue) + + rt := NewTestInstanceWithTrie(t, testCase.targetRuntime, tt) + + babeConfig, err := rt.BabeConfiguration() + require.NoError(t, err) + + require.NotEmpty(t, babeConfig.GenesisAuthorities) + + authorityID := babeConfig.GenesisAuthorities[0].Key + + const slot = uint64(10) + res, err := rt.BabeGenerateKeyOwnershipProof(slot, authorityID) + require.NoError(t, err) + require.Nil(t, res) + }) + } +} + +func TestInstance_BabeSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { + testCases := []struct { + name string + targetRuntime string + }{ + { + name: "with_polkadot_runtime", + targetRuntime: runtime.POLKADOT_RUNTIME_v0929, + }, + { + name: "with_westend_runtime", + targetRuntime: runtime.WESTEND_RUNTIME_v0929, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + tt := trie.NewEmptyTrie() + rt := NewTestInstanceWithTrie(t, testCase.targetRuntime, tt) + authorityID := types.AuthorityID{1} + const slot = uint64(1) + + keyOwnershipProof := testKeyOwnershipProof + + equivocationProof := types.BabeEquivocationProof{ + Offender: authorityID, + Slot: slot, + } + + err := rt.BabeSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, keyOwnershipProof) + require.NoError(t, err) + }) + } +} + +func TestInstance_BabeConfiguration_WestendRuntime_NoAuthorities(t *testing.T) { + rt := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + cfg, err := rt.BabeConfiguration() + require.NoError(t, err) + + expected := &types.BabeConfiguration{ + SlotDuration: 6000, + EpochLength: 600, + C1: 1, + C2: 4, + GenesisAuthorities: nil, + Randomness: [32]byte{}, + SecondarySlots: 2, + } + require.Equal(t, expected, cfg) +} + +func TestInstance_BabeConfiguration_WestendRuntime_WithAuthorities(t *testing.T) { + tt := trie.NewEmptyTrie() + + randomnessValue, err := common.HexToHash("0x01") + require.NoError(t, err) + key := common.MustHexToBytes(genesis.BABERandomnessKeyHex) + tt.Put(key, randomnessValue[:]) + + authorityValue, err := common.HexToBytes("0x08eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key = common.MustHexToBytes(genesis.BABEAuthoritiesKeyHex) + tt.Put(key, authorityValue) + + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + cfg, err := rt.BabeConfiguration() + require.NoError(t, err) + + authA, _ := common.HexToHash("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authB, _ := common.HexToHash("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + expectedAuthData := []types.AuthorityRaw{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + expected := &types.BabeConfiguration{ + SlotDuration: 6000, + EpochLength: 600, + C1: 1, + C2: 4, + GenesisAuthorities: expectedAuthData, + Randomness: [32]byte{1}, + SecondarySlots: 2, + } + + require.Equal(t, expected, cfg) +} + +func TestInstance_InitializeBlock_NodeRuntime(t *testing.T) { + rt := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + + header := &types.Header{ + Number: 1, + Digest: types.NewDigest(), + } + + err := rt.InitializeBlock(header) + require.NoError(t, err) +} + +func TestInstance_InitializeBlock_PolkadotRuntime(t *testing.T) { + rt := NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + + header := &types.Header{ + Number: 1, + Digest: types.NewDigest(), + } + + err := rt.InitializeBlock(header) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_WestendRuntime(t *testing.T) { + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + block := runtime.InitializeRuntimeToTest(t, instance, &types.Header{}) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(nil) + instance.SetContextStorage(parentState) + + _, err := instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ApplyExtrinsic_WestendRuntime(t *testing.T) { + genesisPath := utils.GetWestendDevRawGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(&genTrie) + instance.SetContextStorage(parentState) + + genesisHeader := &types.Header{ + Number: 0, + StateRoot: genTrie.MustHash(), + } + header := &types.Header{ + ParentHash: genesisHeader.Hash(), + Number: 1, + Digest: types.NewDigest(), + } + + err = instance.InitializeBlock(header) + require.NoError(t, err) + + extHex := runtime.NewTestExtrinsic(t, instance, genesisHeader.Hash(), genesisHeader.Hash(), + 0, signature.TestKeyringPairAlice, "System.remark", []byte{0xab, 0xcd}) + + res, err := instance.ApplyExtrinsic(common.MustHexToBytes(extHex)) + require.NoError(t, err) + require.Equal(t, []byte{0, 0}, res) +} + +func TestInstance_ExecuteBlock_PolkadotRuntime(t *testing.T) { + DefaultTestLogLvl = 0 + + instance := NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + + block := runtime.InitializeRuntimeToTest(t, instance, &types.Header{}) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(nil) + instance.SetContextStorage(parentState) + + _, err := instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_PolkadotRuntime_PolkadotBlock1(t *testing.T) { + genesisPath := utils.GetPolkadotGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + expectedGenesisRoot := common.MustHexToHash("0x29d0d972cd27cbc511e9589fcb7a4506d5eb6a9e8df205f00472e5ab354a4e17") + require.Equal(t, expectedGenesisRoot, genTrie.MustHash()) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := []byte{8, 40, 4, 3, 0, 11, 80, 149, 160, 81, 114, 1, 16, 4, 20, 0, 0} + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest data received from querying polkadot node + digestBytes := common.MustHexToBytes("0x0c0642414245b501010000000093decc0f00000000362ed8d6055645487fe42e9c8640be651f70a3a2a03658046b2b43f021665704501af9b1ca6e974c257e3d26609b5f68b5b0a1da53f7f252bbe5d94948c39705c98ffa4b869dd44ac29528e3723d619cc7edf1d3f7b7a57a957f6a7e9bdb270a044241424549040118fa3437b10f6e7af8f31362df3a179b991a8c56313d1bcd6307a4d0c734c1ae310100000000000000d2419bc8835493ac89eb09d5985281f5dff4bc6c7a7ea988fd23af05f301580a0100000000000000ccb6bef60defc30724545d57440394ed1c71ea7ee6d880ed0e79871a05b5e40601000000000000005e67b64cf07d4d258a47df63835121423551712844f5b67de68e36bb9a21e12701000000000000006236877b05370265640c133fec07e64d7ca823db1dc56f2d3584b3d7c0f1615801000000000000006c52d02d95c30aa567fda284acf25025ca7470f0b0c516ddf94475a1807c4d250100000000000000000000000000000000000000000000000000000000000000000000000000000005424142450101d468680c844b19194d4dfbdc6697a35bf2b494bda2c5a6961d4d4eacfbf74574379ba0d97b5bb650c2e8670a63791a727943bcb699dc7a228bdb9e0a98c9d089") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // polkadot block 1, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3"), + Number: 1, + StateRoot: common.MustHexToHash("0xc56fcd6e7a757926ace3e1ecff9b4010fc78b90d459202a339266a7f6360002f"), + ExtrinsicsRoot: common.MustHexToHash("0x9a87f6af64ef97aff2d31bebfdd59f8fe2ef6019278b634b2515a38f1c4c2420"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1(t *testing.T) { + genesisPath := utils.GetKusamaGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + expectedGenesisRoot := common.MustHexToHash("0xb0006203c3a6e6bd2c6a17b1d4ae8ca49a31da0f4579da950b127774b44aef6b") + require.Equal(t, expectedGenesisRoot, genTrie.MustHash()) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := []byte{8, 40, 4, 2, 0, 11, 144, 17, 14, 179, 110, 1, 16, 4, 20, 0, 0} + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x0c0642414245340201000000ef55a50f00000000044241424549040118ca239392960473fe1bc65f94ee27d890a49c1b200c006ff5dcc525330ecc16770100000000000000b46f01874ce7abbb5220e8fd89bede0adad14c73039d91e28e881823433e723f0100000000000000d684d9176d6eb69887540c9a89fa6097adea82fc4b0ff26d1062b488f352e179010000000000000068195a71bdde49117a616424bdc60a1733e96acb1da5aeab5d268cf2a572e94101000000000000001a0575ef4ae24bdfd31f4cb5bd61239ae67c12d4e64ae51ac756044aa6ad8200010000000000000018168f2aad0081a25728961ee00627cfe35e39833c805016632bf7c14da5800901000000000000000000000000000000000000000000000000000000000000000000000000000000054241424501014625284883e564bc1e4063f5ea2b49846cdddaa3761d04f543b698c1c3ee935c40d25b869247c36c6b8a8cbbd7bb2768f560ab7c276df3c62df357a7e3b1ec8d") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // kusama block 1, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe"), + Number: 1, + StateRoot: common.MustHexToHash("0xfabb0c6e92d29e8bb2167f3c6fb0ddeb956a4278a3cf853661af74a076fc9cb7"), + ExtrinsicsRoot: common.MustHexToHash("0xa35fb7f7616f5c979d48222b3d2fa7cb2331ef73954726714d91ca945cc34fd8"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock3784(t *testing.T) { + gossTrie3783 := newTrieFromPairs(t, "../test_data/kusama/block3783.out") + expectedRoot := common.MustHexToHash("0x948338bc0976aee78879d559a1f42385407e5a481b05a91d2a9386aa7507e7a0") + require.Equal(t, expectedRoot, gossTrie3783.MustHash()) + + // set state to genesis state + state3783 := storage.NewTrieState(gossTrie3783) + + cfg := Config{ + Storage: state3783, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(gossTrie3783, cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := common.MustHexToBytes("0x10280402000bb00d69b46e0114040900193b10041400009101041300eaaec5728cd6ea9160ff92a49bb45972c532d2163241746134726aaa5b2f72129d8650715320f23765c6306503669f69bf684b188dea73b1e247dd1dd166513b1c13daa387c35f24ac918d2fa772b73cffd20204a8875e48a1b11bb3229deb7f00") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 4, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245340203000000bd64a50f0000000005424142450101bc0d6850dba8d32ea1dbe26cb4ac56da6cca662c7cc642dc8eed32d2bddd65029f0721436eafeebdf9b4f17d1673c6bc6c3c51fe3dda3121a5fc60c657a5808b") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // kusama block 3784, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x4843b4aa38cf2e3e2f6fae401b98dd705bed668a82dd3751dc38f1601c814ca8"), + Number: 3784, + StateRoot: common.MustHexToHash("0xac44cc18ec22f0f3fca39dfe8725c0383af1c982a833e081fbb2540e46eb09a5"), + ExtrinsicsRoot: common.MustHexToHash("0x52b7d4852fc648cb8f908901e1e36269593c25050c31718454bca74b69115d12"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock901442(t *testing.T) { + ksmTrie901441 := newTrieFromPairs(t, "../test_data/kusama/block901441.out") + expectedRoot := common.MustHexToHash("0x3a2ef7ee032f5810160bb8f3ffe3e3377bb6f2769ee9f79a5425973347acd504") + require.Equal(t, expectedRoot, ksmTrie901441.MustHash()) + + // set state to genesis state + state901441 := storage.NewTrieState(ksmTrie901441) + + cfg := Config{ + Storage: state901441, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie901441, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280402000b207eb80a70011c040900fa0437001004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245340244000000aeffb30f00000000054241424501011cbef2a084a774c34d9990c7bfc6b4d2d5e9f5b59feca792cd2bb89a890c2a6f09668b5e8224879f007f49f299d25fbb3c0f30d94fb8055e07fa8a4ed10f8083") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + // kusama block 901442, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x68d9c5f75225f09d7ce493eff8aabac7bae8b65cb81a2fd532a99fbb8c663931"), + Number: 901442, + StateRoot: common.MustHexToHash("0x6ea065f850894c5b58cb1a73ec887e56842851943641149c57cea357cae4f596"), + ExtrinsicsRoot: common.MustHexToHash("0x13483a4c148fff5f072e86b5af52bf031556514e9c87ea19f9e31e7b13c0c414"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1377831(t *testing.T) { + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block1377830.out") + expectedRoot := common.MustHexToHash("0xe4de6fecda9e9e35f937d159665cf984bc1a68048b6c78912de0aeb6bd7f7e99") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x08280402000b60c241c070011004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245b50101020000008abebb0f00000000045553c32a949242580161bcc35d7c3e492e66defdcf4525d7a338039590012f42660acabf1952a2d5d01725601705404d6ac671507a6aa2cf09840afbdfbb006f48062dae16c56b8dc5c6ea6ffba854b7e8f46e153e98c238cbe7bbb1556f0b0542414245010136914c6832dd5ba811a975a3b654d76a1ec81684f4b03d115ce2e694feadc96411930438fde4beb008c5f8e26cfa2f5b554fa3814b5b73d31f348446fd4fd688") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + // kusama block 1377831, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xca387b3cc045e8848277069d8794cbf077b08218c0b55f74d81dd750b14e768c"), + Number: 1377831, + StateRoot: common.MustHexToHash("0x7e5569e652c4b1a3cecfcf5e5e64a97fe55071d34bab51e25626ec20cae05a02"), + ExtrinsicsRoot: common.MustHexToHash("0x7f3ea0ed63b4053d9b75e7ee3e5b3f6ce916e8f59b7b6c5e966b7a56ea0a563a"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1482003(t *testing.T) { + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block1482002.out") + expectedRoot := common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280402000b10c3e3e570011c04090042745a001004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := testdata.DigestKusama1482002(t) + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + require.Equal(t, 4, len(digest.Types)) + + // kusama block 1482003, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x587f6da1bfa71a675f10dfa0f63edfcf168e8ece97eb5f526aaf0e8a8e82db3f"), + Number: 1482003, + StateRoot: common.MustHexToHash("0xd2de750002f33968437bdd54912dd4f55c3bddc5a391a8e0b8332568e1efea8d"), + ExtrinsicsRoot: common.MustHexToHash("0xdf5da95780b77e83ad0bf820d5838f07a0d5131aa95a75f8dfbd01fbccb300bd"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock4939774(t *testing.T) { + // t.Skip("skip for now as block4939773 is too large") + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block4939773.out") + expectedRoot := common.MustHexToHash("0xc45748e6e8632b44fc32b04cc4380098a9584cbd63ffbc59adce189574fc36fe") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x08280402000b80eb3cd17501710984c2292bcf6f34fc2d25f7a1ebaec41c3239536f12f75417c73f7c5aca53308668016ec90c2318ee45af373755527436c4d7a257c481fdc3214634eb4b5c6711ae181827c378843da82c72191647667607ee97e0f0335f14d0876c63503b5f2b8986650304001f010200083e1f2bfd408d3b8d2266ce9b6f2d40acef27b773414537be72576ee3e6108b256eb45e26258d7ac737c3ad3af8cd1b2208d45c472ba19ebfc3e2fb834a6e904d01de574b00010000007506180228040052dac5497bbdd42583d07aa46102790d54aacdcbfac8877189e3b609117a29150b00a0724e180904001cf8853df87ca8588405e30c46a434d636c86561b955b09e2e9b27fc296bf4290b005039278c040400f49db9c8894863a7dd213be93b1c440b145cc19d4927b4c29fe5fa25e8a1667f0b005039278c040400e05f031d874257a24232076830a073a6af6851c07735de201edfc412ca8853180b005039278c0404009289e88ec986066d04f7d93d80f7a3c9794580b5e59d2a7af6b19745dd148f6f0b005039278c0404006c8aff52c496b64b476ca22e58fc54822b435abbbbcaf0c9dd7cf1ab573227790b005039278c04040044e31f7c4afa3b055696923ccb405da2ee2d9eefccf568aa3c6855dbff573e5f0b005039278c040400469ec0f872af2503a9251666fd089d0e84d3f6c8b761ee94b0e868788e0f60500b005039278c040400b41cc00e4ee2945ce9974dbb355265e39c9cf325c176147d7f6b1631af38ce590b005039278c040400d8e2f26a12d4bfc513fd32c1e5a7f14e930c3ef37997bf4e3de2fed51eed515a0b005039278c040048227b8300000000") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + digestBytes := common.MustHexToBytes("0x080642414245b50101ef0100000815f30f000000004014ed1a99f017ea2c0d879d7317f51106938f879b296ff92c64319c0c70fe453d72035395da8d53e885def26e63cf90461ee549d0864f9691a4f401b31c1801730c014bc0641b307e8a30692e7d074b4656993b40d6f08698bc49dea40c11090542414245010192ed24972a8108b9bad1a8785b443efe72d4bc2069ab40eac65519fb01ff04250f44f6202d30ca88c30fee385bc8d7f51df15dddacf4e5d53788d260ce758c89") //nolint:lll + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xac08290f49cb9760a3a4c5a49351af76ba9432add29178e5cc27d4451f9126c9"), + Number: 4939774, + StateRoot: common.MustHexToHash("0x5d66f43cdbf1740b8ca41f0cd016602f1648fb08b74fe49f5f078845071d0a54"), + ExtrinsicsRoot: common.MustHexToHash("0x5d887e118ee6320aca38e49cbd98adc25472c6efbf77a695ab0d6c476a4ec6e9"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_PolkadotBlock1089328(t *testing.T) { + dotTrie := newTrieFromPairs(t, "../test_data/polkadot/block1089327.json") + expectedRoot := common.MustHexToHash("0x87ed9ebe7fb645d3b5b0255cc16e78ed022d9fbb52486105436e15a74557535b") + require.Equal(t, expectedRoot, dotTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(dotTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(dotTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280403000be02ab6d873011004140000b90384468e34dbdcc8da24e44b0f0d34d97ccad5ce0281e465db0cc1d8e1423d50d90a018a89185c693f77b050fa35d1f80b19608b72a6e626110e835caedf949668a12b0ad7b786accf2caac0ec874941ccea9825d50b6bb5870e1400f0e56bb4c18b87a5021501001d00862e432e0cf75693899c62691ac0f48967f815add97ae85659dcde8332708551001b000cf4da8aea0e5649a8bedbc1f08e8a8c0febe50cd5b1c9ce0da2164f19aef40f01014a87a7d3673e5c80aec79973682140828a0d1c3899f4f3cc953bd02673e11a022aaa4f269e3f1a90156db29df88f780b1540b610aeb5cd347ee703c5dff48485") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245b501017b000000428edd0f00000000c4fd75c7535d8eec375d70d21cc62262247b599aa67d8a9cf2f7d1b8cb93cd1f9539f04902c33d4c0fe47f723dfed8505d31de1c04d0036a9df233ff902fce0d70060908faa4b3f481e54cbd6a52dfc20c3faac82f746d84dc03c2f824a89a0d0542414245010122041949669a56c8f11b3e3e7c803e477ad24a71ed887bc81c956b59ea8f2b30122e6042494aab60a75e0db8fdff45951e456e6053bd64eb5722600e4a13038b") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x21dc35454805411be396debf3e1d5aad8d6e9d0d7679cce0cc632ba8a647d07c"), + Number: 1089328, + StateRoot: common.MustHexToHash("0x257b1a7f6bc0287fcbf50676dd29817f2f7ae193cb65b31962e351917406fa23"), + ExtrinsicsRoot: common.MustHexToHash("0x950173af1d9fdcd0be5428fc3eaf05d5f34376bd3882d9a61b348fa2dc641012"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_DecodeSessionKeys(t *testing.T) { + keys := "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d34309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc38520426026" //nolint:lll + pubkeys, err := common.HexToBytes(keys) + require.NoError(t, err) + + pukeysBytes, err := scale.Marshal(pubkeys) + require.NoError(t, err) + + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + decoded, err := instance.DecodeSessionKeys(pukeysBytes) + require.NoError(t, err) + + var decodedKeys *[]struct { + Data []uint8 + Type [4]uint8 + } + + err = scale.Unmarshal(decoded, &decodedKeys) + require.NoError(t, err) + + require.NotNil(t, decodedKeys) + require.Len(t, *decodedKeys, 6) +} + +func TestInstance_PaymentQueryInfo(t *testing.T) { + tests := []struct { + extB []byte + ext string + errMessage string + expect *types.RuntimeDispatchInfo + }{ + { + // Was made with @polkadot/api on https://github.com/danforbes/polkadot-js-scripts/tree/create-signed-tx + ext: "0xd1018400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01bc2b6e35929aabd5b8bc4e5b0168c9bee59e2bb9d6098769f6683ecf73e44c776652d947a270d59f3d37eb9f9c8c17ec1b4cc473f2f9928ffdeef0f3abd43e85d502000000012844616e20466f72626573", //nolint:lll + expect: &types.RuntimeDispatchInfo{ + Weight: 0, + Class: 0, + PartialFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(12800000000), + }, + }, + }, + { + // incomplete extrinsic + ext: "0x4ccde39a5684e7a56da23b22d4d9fbadb023baa19c56495432884d0640000000000000000000000000000000", + errMessage: "running runtime function: wasm error", + }, + { + // incomplete extrinsic + extB: nil, + errMessage: "running runtime function: wasm error", + }, + } + + for _, test := range tests { + var err error + var extBytes []byte + + if test.ext == "" { + extBytes = test.extB + } else { + extBytes, err = common.HexToBytes(test.ext) + require.NoError(t, err) + } + + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + info, err := ins.PaymentQueryInfo(extBytes) + + if test.errMessage != "" { + assert.ErrorContains(t, err, test.errMessage) + continue + } + require.NoError(t, err) + + require.NoError(t, err) + require.NotNil(t, info) + require.Equal(t, test.expect, info) + } +} + +func newTrieFromPairs(t *testing.T, filename string) *trie.Trie { + data, err := os.ReadFile(filename) + require.NoError(t, err) + + rpcPairs := make(map[string]interface{}) + err = json.Unmarshal(data, &rpcPairs) + require.NoError(t, err) + pairs := rpcPairs["result"].([]interface{}) + + entries := make(map[string]string) + for _, pair := range pairs { + pairArr := pair.([]interface{}) + entries[pairArr[0].(string)] = pairArr[1].(string) + } + + tr, err := trie.LoadFromMap(entries) + require.NoError(t, err) + return &tr +} + +func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) { + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + tests := []struct { + callHex string + errMessage string + expect *types.RuntimeDispatchInfo + }{ + { + // call generated by using palkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // and removing first byte (encoding) and second byte (unknown) + callHex: "0x0001084564", + expect: &types.RuntimeDispatchInfo{ + Weight: 0, + Class: 0, + PartialFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(1500000000), + }, + }, + }, + { + // call removing encoding (first byte), polkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // polkadot.js/api returns error: RPC-CORE: call(method: Text, data: Bytes, at?: BlockHash): + // Bytes:: -32000: Client error: Execution failed: Execution aborted due to trap: wasm trap: wasm + //`unreachable` instruction executed + callHex: "0x040001084564", + errMessage: "running runtime function: wasm error", + }, + { + // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") + // polkadot.js/api returns error: Error: createType(Call):: findMetaCall: Unable to find Call with index + // [44, 4]/[44,4] + callHex: "0x2c0400011c45642074657374", + errMessage: "running runtime function: wasm error", + }, + } + + for _, test := range tests { + var err error + var callBytes []byte + + callBytes, err = common.HexToBytes(test.callHex) + require.NoError(t, err) + + info, err := ins.QueryCallInfo(callBytes) + + if test.errMessage != "" { + assert.ErrorContains(t, err, test.errMessage) + continue + } + + require.NoError(t, err) + require.NotNil(t, info) + require.Equal(t, test.expect, info) + } +} + +func TestInstance_TransactionPaymentCallApi_QueryCallFeeDetails(t *testing.T) { + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + tests := []struct { + callHex string + errMessage string + expect *types.FeeDetails + }{ + { + // call generated by using palkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // and removing first byte (encoding) and second byte (unknown) + callHex: "0x0001084564", + expect: &types.FeeDetails{ + InclusionFee: types.InclusionFee{ + BaseFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(256000000001), + }, + LenFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(128000000000), + }, + AdjustedWeightFee: &scale.Uint128{}, + }, + Tip: &scale.Uint128{}, + }, + }, + { + // call removing encoding (first byte), polkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // when calling polkadot node (v0.9.29) with polkadot.js/api the node returns error: RPC-CORE: call( + // method: Text, data: Bytes, at?: BlockHash): Bytes:: -32000: Client error: Execution failed: + // Execution aborted due to trap: wasm trap: wasm `unreachable` instruction executed + callHex: "0x040001084564", + errMessage: "running runtime function: wasm error", + }, + { + // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") + // when calling polkadot (v0.9.29) with polkadot.js/api the node returns error: Error: createType( + //Call):: findMetaCall: Unable to find Call with index [44, 4]/[44,4] + callHex: "0x18040001084564", + errMessage: "running runtime function: wasm error", + }, + } + + for _, test := range tests { + extBytes, err := common.HexToBytes(test.callHex) + require.NoError(t, err) + + details, err := ins.QueryCallFeeDetails(extBytes) + + if test.errMessage != "" { + assert.ErrorContains(t, err, test.errMessage) + continue + } + + require.NoError(t, err) + require.NotNil(t, details) + require.Equal(t, test.expect, details) + } +} + +func TestInstance_GrandpaGenerateKeyOwnershipProof(t *testing.T) { + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") + identityPubKey, _ := ed25519.NewPublicKey(identity) + authorityID := identityPubKey.AsBytes() + + opaqueKeyOwnershipProof, err := instance.GrandpaGenerateKeyOwnershipProof(uint64(0), authorityID) + // Since the input is not valid with respect to the instance, an empty proof is returned + require.NoError(t, err) + require.Nil(t, opaqueKeyOwnershipProof) +} + +func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { + identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") + identityPubKey, _ := ed25519.NewPublicKey(identity) + runtime := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + + keyOwnershipProofRaw := types.GrandpaOpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, + 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) + keyOwnershipProof := scale.MustMarshal(keyOwnershipProofRaw) + + var opaqueKeyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof + err := scale.Unmarshal(keyOwnershipProof, &opaqueKeyOwnershipProof) + require.NoError(t, err) + + firstVote := types.GrandpaVote{ + Hash: common.MustHexToHash("0x4801b8e62d31167d30c893cc1970f6a0e289420282a4b245b75f2c46fb308af1"), + Number: 10, + } + secondVote := types.GrandpaVote{ + Hash: common.MustHexToHash("0xc314327941fdd924bc67fd72651c40aececd485ca3e878c21e02abb40feae5bd"), + Number: 10, + } + + firstSignatureArray := mustHexTo64BArray(t, "0xd7292caacc62504365f179892a7399f233944bf261f8a3f66260f70e0016f2d"+ + "b63922726b015c82dc7131f4730fbec61f71672a571453e51029bfb469070900f") + + secondSignatureArray := mustHexTo64BArray(t, "0xb3c408b74905dfedfffa66f99f16fe8b938fd8df76a92225228a1ca07523"+ + "0b99a2d9e173c561952e1e378b701915ca188d2c832ef92a3fab8e455f32570c0807") + + grandpaEquivocation := types.GrandpaEquivocation{ + RoundNumber: 1, + ID: identityPubKey.AsBytes(), + FirstVote: firstVote, + FirstSignature: firstSignatureArray, + SecondVote: secondVote, + SecondSignature: secondSignatureArray, + } + preVoteEquivocation := types.PreVote(grandpaEquivocation) + equivocationVote := types.NewGrandpaEquivocation() + err = equivocationVote.Set(preVoteEquivocation) + require.NoError(t, err) + + equivocationProof := types.GrandpaEquivocationProof{ + SetID: 1, + Equivocation: *equivocationVote, + } + err = runtime.GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, opaqueKeyOwnershipProof) + require.NoError(t, err) +} diff --git a/lib/runtime/wazero/testdata/digest.kusama.1482002.zip b/lib/runtime/wazero/testdata/digest.kusama.1482002.zip new file mode 100644 index 0000000000000000000000000000000000000000..6d26f43cb3f326f1932bd6c0e019f6abc909ea61 GIT binary patch literal 12591 zcmZ{rLy#>Dtf1SrZQHhO+ct08wr$?Faoe_S+xF@C-<#c3O;SlJi)5Xo@+rxJf}sHc z0YL%9WV@)!`VWLSG64axaRULN1K|OgSzDUBx-r z4r$L+o(79om)N_YRy*P%L&LxT;FnUn{AmK75!%~!kYqyOL-TZB@C8h9+!~hT>@tgG z$xIIkaskEvL!1)Da=e}+hLr6`le8u{9fcuGeK9TmwG*LUAktP4`qV5lFxwFXQ}K=g zcgg@@#VTi8fJP!Zm0gNtod)TwWro9=uckPaZ7x6Bg<&1QXgTcZq>$^)>fbmpB~Gmr z%+=7k|F3olw{(jAFve3n=Stk$4vHe(N^0OM67A)|oD_+&>8MG-BDN{qFxFOggHRpo z@yJ(d}@GaN8VCz4r}h7s%%=Yq zYpG|r7)|%@NB6Yqw-Daj3zhMH@;~{mTJ;C3zra_mnU)kJI0hG5rT{I)-)OGLudD#k z@nr5PyC0gOFe_Nnmn9N2Z0+G-lP4$9M61b%|KCOsDfyoI{6o z)MVsr8;^P2Zjz9W-4cs}f-Sc!xj{p!SNL@O9=iga<0ZB=PZzI|Wsu`-;aoP0J!kZr zPr{H_XU{>I*yY4?x(&7_vzopYd8sDmi9O-m0XHE|&&N?dVDxJE$%y(*ONzc%-@Cx& zxwq-b!;-Ro00Y#5lD+_S2j!ndKVc@a6fS|KsgeMTu`X?-#+>Lx4G?E5M{7_B)Rc@_ zL!1HF; z;rNL}#KtGKdR*m>vSFTe22J*eCR>iOXO?eh_e9lD`xDO=F_u2z_;%hf=Pe0{`cieY}} zYoK8q`jCK+M$7Ke3FTLBzv>59QalsR3(t+9%sMj@aVqk?)DrkG)smMLM{G{}PV0WO z2i(z&h~vJ~k-l-UkC!fgl!6@S&E+C&(LRA)*IJS!unbFnA+ZJQ3sS}k3M3hap+uFt znJ#jxYKTkHfKF25-qsljF$u+);A(yO>-dQ^QbVGHnKKS(SQ>5X%jAK)K0mrq=1j?^ z-&Cbuz>oZR+Edt}H{;M`5%?9J(5Ld(@%o_opD@aW{#sW6Nn^2Bm){tZBtV5cj*C4K z7RP_L=792Nbm8~vt(X#e2JqI}u8s?4-Fp+W;s`zSr~l{O!)Be99)de2CVw%!4GI#` z)*=i(UMBab$C0KMjuhxHpT&2>b6{Eaw{u=9F;fFD;LD#hj7WVY9xqbXy)MEGp55*v1}&>5d})xhI3AD{;0R431qvt5; zsm|Qbj^P5SZ5gU?&tE=qtN=><_g@d*247x7MgndMRw< zw0d@RrO~7#WVd6qv+;Op!$yg^_7hT+{hMuFpFR;zEXGNMO_zT~(jG?b$7|ZAvFF3o z0K<+XoJ&YoG!l_2D-t2{Gy0WyT>e^*4RLNVqn)L9kPo#fiiWgyZTmYKH;`a2*L1wA zSs1cgajk8G(ObKD4_Xw-6NE9(9&${YCf!n$V4c8Gh0|yg8$CyHwU;fq%#N0Lj8$S7 z=sMSd?!7fjS*ky1_#4ZI@3u15jv4pl4 zRD{FCU>>J*z-?3DqY5PI&&B~w}C=p`) zkf;6TqZ>WmbLp(23FnG05B)IOMxX#Qk!|hR^3Ak4_gPa=ce}A#8@~PvH4uuRSbCn{ zkw-HO3kceY&N@fPT}WWKI)%=7REs13BUJ?anc+jmp<1A*B<1?H@Op%l#g7(OYFiQ` zA^#aFY_V?$;bc$;!h|tLP;hMiRirDmSUfdyOx$lMV3FN7p!}M{n0y7o^AVN7(>Qde zYj*m4s6lS*RZ-LC7%H5V)R?j3G3dxeLib zDGgT8fjftl_+ukjRDs{igS>#+LwwnGPBQqH(oDjZ7t?o0GMVw7KYHOaUN;>S6%4&p zz)O}KOcVL#8s&aGjbSgOEM0+V9pnoZUV#)xB$LB|Wv9(S` zxstK)i05Hoph1Q!6GiLps=*O{#%Y%VhdZCzh8Q{Paa)p!$iWeZl{`PH(>-gEmaX~U zrCJl5gz@9g(xTa@5X&PKic>x&&SdhDDl^3&aZghP;EYiZ8?6 zvVh69u+NLS*1QY0Uu%V$*Y$fuU366`IQQ>#jbAHh!uv1v%#}RwFToP6_F8(>=t6V3 z#Br*^>5c}DZB^5|#j7B$ruBb^jw2zKgcd{cE(3#b}bb^W-Zs#FiJ7AW?Z(4hUYX~Kn? zaf3(Er%I<&4FoMBMUl7R7sx-|qBhDp6~SF*a^zJkYELYrF)mdcj+u#|UXe5!$xH;W zYnqF;jMAh6WO+)0OD0-neMkR|F}SU7*_e?bvhCTi!FekxDXY^|0r*~3jH6eTJL2@g zNM86nF2azr0~*PIW^dCp1Ov1~Bwk|*52ev-Q;ejh!k#U6hICf2L`r-t+lFM1>i~T} zxCnzl(N`y~bo6*+C)cF3z1z`EL{KkZCc(1lw-_>3E%D|#KG$%%m>a`&YJ#}!u@HMO zhbIqSBF`pc=3;w2KHXh@3@}?IybgR>Rpy(e(5g>4>Z@aOVE>k|o8B=;1l~9X;p4f4 zd?CBD!Dui2OFRkqAD#85#%KElV0J4+qT|(=}!sL&7@5ho*0ZFsG6yUEHU;v7VkwdMbkex-=5j- zjZL6SXwmF>C?1Gw4zm4wm1tW-+s+Bd;<~<=bOPogzuI~8in{24OVq8AYo`p5?I#Hn z4?WSgk)$f_@;zC+h&nBsZ}*!+JBg8^qz?bKTOs|T?l4tk*Ke}OOVQ4H$?vc4QMPb| zo~qZFzRAl-Y+l?%&O@-8`1uHdBgvwN828T4tDml#nI(+lKB2RKT0L_7M37!d1tNk= z=Rmq3B-c2DL4-}qs1dA_tR&TM+qx<217V@Dwb5X|Io$I_KCb-YPzUYKA*~S7fn!oh zjs=sGtVNE2z|TkL>MuB+hK{R&f|~-Rx-sppX`*tkg$mr|?k4imfc{VPMP~Doox-{q z($W$WOQJXkt0+LZB2o+&11Tj>P`op+Guk$*=!#>?3R>~1!0Ff6i9-aWQN>fJsO$0Lutaq;qn@YM0lV9S}EnF-BNW-745%$ZIVa(^cFL!&q= ziIf4QS*a)pQu`irqiBg{NUZHn5O?u(+8Y4>RL_52PQqng6lp;WzNqeq!F#l5ZXWf^THuP5eQnm-V*^ApXeGTGhq)c4lV6@^rc zFv!yCTOmav9sx|*=OfVaMn6?Kq#lOz49+J`-&$YdAWx?{*p+eug6x&`Hjv0xK2?r#r%stK`)kBCG_) z0-*$9ob%ZV$s5*Zy`lXdiZvakdi17=G}<`_scK9Qim6c~^S zC<%l|h=IOk0v(E$s?)$9)#DNe@!==2yMtc7%-Z=4{5ti$8IMq0Zd)+I`xH4`*<&;JM{t2K(kO6V9y?n$0)%B^>aW=2Hj zm!w~5&$~89L^Il`AH7MhU*UDOt3c~kq_bbB?g}rW*FSI#)IUL@><9P4TL2)mz zr_)Wg4*m+fEh_gy47#WteQkbH$miwa0(fn1&$CJ@=&c?HA9hp5WH5;hf4qDZh!}FL zCqKTJRJS02N1u&I+uQn-?3*E8RoJKZsQ?8NE(ZJgrqzufp>VMW^#2;1X{pI=rv#MVe@Ut+o zH;yAUY58k$K}*K4ZCdP`?nqJLmiRz#=lqJY++234+x2q$Y_@a&Rt$Fhk(xzVlUvAQZ$I*jyt;W;hY2jG3#fdpt5;lU6nmutR3-QHO3ZvdGhYoOqmyZ6Bm#4>Bsxd6Irb}1N{Xay{Ky2=EXu5*gIgteIax1OAVSl}+C zu$bwWM4`jyGT_Md*dfy8sW&+OaN99SXE!he8LtuYJ5KIF_{op!$eZwp8<1r!6mjaZ zprclCm3^jrafwZgGylfiiR>E>E3ZQ5*+iKML1H2lwQ~P!oC=3gIG_Ds~;_ zI6vn3t3UTlQ(?}lXx$kpSPpKuPbGg$l~Dk!kE;C@9hCOA4j$v9A&tL*uU}cF8`q@e zs>^lW6H|n?NePI^(&9hGuAjP8`(j(Lc%~cYEd) zdN5PmUG@6y%G@Vi?BNhiXZ_QyU3N$?k2!NO)iYnKw)DC0Ki=ZEP=7BJd&9XFY-Od6e(wI13~Y zV9VO`;{OrEnRk22)IlX$P;U3dTc~;2dh)9T-w#gv%9g7nD>qK;f0J-?wv4bc?NP5z zkoXt$t;wF)t;KV^pERmm)2g1jh1jOpETmuk@KvU2?~PtmM;+<*ifj+FQQb$dR>v*im`5? zpmw{Y5na9IY;}fW2iVcM$*V|!OkSOa_c;niF2x7w49q=v+j4PB&Q+t5t*6U2DttF< z-*RPJ@%Vdq036{{6Rr?pRFAH5A2-Zm7js3MQ%N;XNffT`%)2hLIKddnUoBVI#CozK zm2Qm(Edv9wJ6d3*AJNq;5o=_4LtmW@OA<;fva896g>4imMpbCy3A>(b?d^y zI1lxO1YDYEBy|T25p_(0dgJ@kmlTy-w5)dp$1duyhp>*ZijLNS0`PGH@xyv#{wUb$ z_=LkXe5v!s(?Iww-!m=xELR!)M2HW!9jB|prR)92yfh@cLMZ_gz{+gi5osHUGEjcq$fxuk@qL5%gy;@&4htGCOH7~nNz`F zHmO~`m2A6Mr9mL_x1)GdH+6c+E;{DIccnF#1oE5j*48?xr9``tPl1|5Mk0b^u)-BZ zk=INybiY1XrjwXN$Pn>SGB1r=i?Yh#^vA7*PnnWclHbd9;4A!LEd<3DzffU7=@R+i z*`@j=%KXqA&E74SqvzSoqWVNR@Nb81uBsTg^QPXyY9A4285&>I@W?;je^hzH29~in zs|ypGGfP>EfxUB>1bf~gL5RTb{={(fp+$%HP7$|M8XR2TW_S%+;*^glx73x8o0CL(x&3N z8-Xr=dK*4SMR}a9?rbng&~Db?GxvDRlEI^3KoxuVJ+oMRl~5)hS+o)UJLTumIn-X_ z5q$XnQ@Qx1`>Ok!WwNnrV(AaouhdJhQaK$07`tfHsZ{lI3az+5-LM&j_JseZLzux6 zbB_5*powPErnAp^Z95a_50xs(!%#^i0*!{zCanV}T;kfLv|G!K(`EziytiJmNo{b` zSC&g$YhJZuRqau?K)70K=6EyN-R34f!p$va zusGccw&{;_<~}o+8sT=grI!7u+t+QTvuS7Ag}M7T;+OI)r-ue-{x6{CDu+>D>JPL9 zj|)K)j29>KQ@!GV9;5+Tf+*^1q>Hu zut?mfx|(WhuILF&miKbB0MFSMT+r@1_(e-b`wWpnM>D)(c52@X%uv2%W~4+t4)A9B zo-^*TgeB5qCM@-ek>1!3(8C7R)oK57J-9zinh3xBr^_;wWHzG!2f1>mhHP@uPdpeZ zHvgR!a(j{S#{J$-*$8NkR!2kSD0+)Bowa2ims}sN!uR=82H{xQikumc{6%%~jtz)+ z1Ha{TL1y&op2QjUpwgWpdG(8X5j7u|CLu4*loA(ZTv~*DDBgG*ecr!(wHQ!`-}VaV z{XD%}p7}wLsAI%neO^tmCgdH7XMr(WKOn!%25=3iGkP z&PrtDW&(M?_{P9T%n?{3$N7he4un|>=pcuWnTn?HcTg_u;S4RDMmfi`MYZAeHO zl48o{2>rmb?mY$6v`9NACW$L^QYX%+Pb1CF56uF5q7?u0Rt+;VF8-W4{dL}+B4>R#elJP&${V|Er^ zfrf9&356yWVLVmsid$!;Wdzw&(G=>L>{^a9X-^n;4s=1I&Yud_7ywXt5PLQGvd?I0 z0aNO}eSD2Zk=Kk=60oR}zq($5&i5vKd1%8s z)Y&f=YH)2ToN*#s0wkifVP9>Yo~4Khbj+0zI;J4_Da+7=Q^rG6^?tD>NyL}*_9aw` z?(o^#>~+XhT9Wf78AJ$0v>MqvyX4wMTdd#sa60`LpV{sV+PjL#wfq(Hg-}l6UXZ(8 z(c%}V!LDos_y}<`@$$wF+{t|W{=g9-5ywseg{(}J{VcM}I2<1(4Qv9HAsM4w0e#_e zJpG`~i~0UbrvYh*xDPC{sr)Z;126|F&3fQR^WOeN6NSghu2CH=)e;<$Lw!qP3CwBi zrYl8HCqF`H5);U98NxTYa}UaYT#fz#t(HM?Z;>Al(eNZZ1?wK)`A${&DrIb1-yF@J zAxlZ&x0)eg0)o4H6mCV3d-U~xw3eI;f!gc+PJ5M>x&^|*I>mjV4qNO%+lg442rFYp zhC<4A%)cLz@Q6HBj9JyVnKUYmkf=2QVP2?iKa~7FNDB*vuw5?^) z_ZG;Gz4QeL|(#)f}21{CuM&b+g6{pwd4brK#F%)C%Z-S#q;07b`u31 zd$vAfPKpX>ug$w-BT1@I7%u=vxqg4F4mqt|jWQ)l-~O!6Jc>QuVU8`tN2&EQO8@g+ z%;nXna`J8)4z@MbVbo%#n93<(;*FNQvW-ETSGqHwNk1Y-4^TWm~9U(fJk^dkz24+-A_ z5Q$~rnFaZ5y3JX%z6del;Plxdp4*bmEF9WB<>zbx93Nes;sJL%F%#45DkFBX(!GVC z-d#uk(NoaLS`r;h_mr*(S?EtPzJ5eLn-a8aSMMrnKx!B(N z&?bNsp`~yZXfOEw%@W76k`|BYqxDuF2G=?Vh~+>s*>nNv$l&By5V<=Zaq-pst*TVq zpWQP~!XbFR@_*gTh}75+-~-}8ShB)5S#5@@c=PfG9_mf7lPr}koJJ1W!oSH^Pv8arWB3-ne6!gCDx^6iCb8Cabzk9@kkXjl3H z;2Wlg?|Rh{xeV-*9S23Be_f}Jh&C7LPMM~I8Bl(dFom`X3>vF-91Lc*FEK?aBUK2Y znRo0Vjx@3N$SGmp)x>FO0$H}?&PG2t+A?ogfmA-zX`KZR2!18T(C}E~D&r9X6auTv z;42F&@%7-=+{J;u@krw_GhUKTO#=JP)>Eaod{BLwg{D|_;jzj8Y>6F#j@zd3+muJ+ zTr{67J%JIo+c+)wWo2`4D^gceg2ZlNSqKTd)J9xqtXX&xdT8XEBuL6X9=iDc#722e z&O6SuAE_Y&9dejbm{TlS#6)OgpA{R^@d1e!PSv|UMJ1XWF;o0Te99GHl)Nph#h`C-jtcqAQZ(7p18+f^las8O z11Uip1H(-gmp67cxGY$Il58rfG543eBgl0$C%&LaWR=6_E>hX5`?)TzrxUV;K%W_z z#2HPK|21wc&WHEG%HC7#;lP>TZ;0YuM?koZ;(`^5;*gSkL~ zncK}nF#8j3{6f!xQ9wAHnI`_tZ9MH8irdAO?AyVIz?eKXvCfgeC`sg%A{GbfTq2t? zG+dKqHzH#{Wt~LxZHmDq@z{KRlv^*1N7tihV0bR3vD2^gC#k^k?+pv`e{qXGvPmBs z)$sVa5T?V-3N$RA(6>KY8pmNGN&J8sW48Z!QbgO(*=t{0N`hOAqVj`(X4OAd*U*5N>FqwZi^XKl(RI9=H_Imqx`>XR_ z>?m$Z6#%>kX*i=BVzIOgW3PB7?w<4R?YEKOv&gl)0h-`Pt8ImFOgl!K|oEUwbRb46)e6mi-MN4 z=#2+owXdvS+6t^sI+b-g;^lz5#72&a&$<-64qp#JGEQ7%SM+_IQDRVyl7S zH;6&B=~PjPj9p(RR&9`zU7Rbd2OyJuq%D0gkA1{W>X(n`cLM z60`tGvMt`Z1 zr4cp9&0k4O2e`}ShcvO%#!@U)c}|uJ#?sD1+O$DOBu}v!I;oXi4aH=VGl=x_*Nt$8 zYJGu=!fJNHM|D{v3AADMt|O*QGd{FfdGNV=#Gghv@AH1Qeq3jvzz^M98Y9@6X6WNW zs*}kR0Q-=QFH4Kj_dVqjPutOwhuug@&7dFW{`bQ`&(KY#HnN=_o!y25v^~-#-Z0Jk z+sfyFWd|cP?8R*9Z32 zniFkQ73E;DFirf0*5jPM$f-JM#rLuWaH1?4O&WPA6j6_$IW4x%D8E4Ji-R^JmUaY8 zlWdms89gS@C*GBDX~q2M!2w^C9m7mYS7(1KB5m}(gE&2#Ao$QB^dZ=ygdhzbO7k~- z#OeG_3#}%lPGsXP`L#2lmJgZrQIBvgQ4u`nK_!l2&Z_Up6J>Z8%8yH1Bs!Rr3hZEa zmc8gc0Aiy;U~Ovhfc^f7M*)T`v7jb$u{e{=xlRmwcdrxbA??P^IIS%= zBdB|zBa4oAG?upzh9_wTHRk|nK38rBev!HhzMxo{!sAP$}uU=y{dC^@f!-d*R}z{fp}mq z)4W#Hux@61k&$o5xi##+7!)zM#bl&=8}G20E|tWEq`c|3?~0!5R(d{rN6enX((47M zGqoJXxGQJ5ZKl^I(vDe>ql%2LW2-XRW87S38` zF{bMVukB4#AC_Y?;)c)Cde4etBK9Nh!IG1SyXDId>pCpUp)5uT{;m1p{+!k?NBq48 z&*~A>-cf)ZsCPZ z-U;oswIy(-QBH@SHG$e%%wQ9`6O7|kdM4_ujnhKgkz#p2zxHwux1>Dj!;|0|=tkBC zN~yxsBb=R@brlc^zFm1(3JMjD8^8~JUrb;%5H2m10dNwy>&INJ_r zV8Bx+S!@f{{p?v4+W_UzL{_ij;vuY!y@c-MYrXd7<&y2pk2*OD+Q|1=X+8bfiKu(W@`Di{b&$t`9h{# z?ntlgr_T;$iV*48xyR1@r#W{|6>cz^2myk0VIaU0*iI@8i zZ=VgOb{)jwK&XPsq-Wtc>3sncgVYN7^`b@oAj@P7t25 zU0hce-V+7^!+hhPQsAzhj#?9%!tRUbw_38B*_g|dI()?rS=7DdCpUOTX|IAkVor$f zw*_*|Th18Zjb|!JhtsU-V;f##i10b;5o|fJk`n7_aL44pKvMMHUDr;lz-%MacDgr; z!**g^b5M1L2dHnf$DtXYKYs%G0Z--xwLlgv6K5bPes3SQql!_Xt#vZg;j`l&;T4nc z?E80DnnXH}L1Sz@?>dq786!U{&6$ziKW-&^X7(7rUV)}W9K-wGg4i!j0oS4_LW|*K zCyO9>vYUcl?_QL2ZcEAZhtfF{LF^(%c`{2lw?5E?4}yX)w-^Y@I>gjlvfvj>9%Kau z;Px=dQ7EwG6sX2I{rVnSbtvj19&%0U zw17lV+XHOYLwU z&)+y9&+=PZ?x-m*_}GCL>>|stcD+vlhRwtq=nIoNoBN*Gn`d8bVSXpc9Wb0j%6^Q} zR-CWJy)(z>f+WDwRPn=nN$*4x13YjULrhg6F^9vgPoMbwAwUj4>z5@7;cmLg)~mo6 zG$MQa**?SAeVcFubxi^=S0#2OTdD;b^hD>MSG&4UXrkN}Yq_?6y#G|^>CHdxJXkoU zHoqnTJ%7wvt4qsId4ksgtfF53M3`*b0&}>d4Bd)RFXn8fKvup9I=P7vGm*rKGppvZ zXEZ=)h)Cm&x8l@W;_PL2$*KkY(;#1>dEy{H{9zGSdNfEc5|j(PlO1yO;))ZKw4$Z) zF1)=^8~8r(s%eqVNUEqqTNdYc=9t|0Er^z!sfF_=bAirGmF|16tZCQFHIUbaX}gJ9 z80tTNo1A=WOd;JNHsP%Y{oD;U7O7?@zV;7@{iEugX)efOs+v}_Le_qUGyDzJbBnp6`E#N~urVV#l6Y@V(W?zWw>Prf}aqx+z zcT7g=)CUdkl0$f*SS3f^ylo9$0DUnh%}>;9R($X6%xJzV+|DN zHaJH)FR<%qMXZ0$9d)z`^Ae+pC=&}DEOFNQv03LJ1ZRznTYj@4v{*d|dgJ59&`Z{W z;xr@*eB7&+f((yG(}Hhc%Vq9?e$GFYzW+Gn%{kvig+Lk-m*tu{j$%Dsp7-y?Xh*YO zI$$m+aEeB*KcR!2!U>G=8&V;>uVcEhA2np-(2tqGdWF6Ak+GA*f;38Zwys8#x=~QhCg?3;D}7E3hZS8dgg=1xl_7v- zi{Ttsm52FwuyO@w+3P|)sN)wP^!s*)Ffgzn1v6QCw6s|f3cbEu?m4km4S@P|T$drL zIO`SuTEm$wqOvZI!jgqLW4$KM_z`Xj@JXQfgKb43P3bPzy8!(os3Z#vLIC>z;}@|0 r2TS;02@Lw5@c*G1!2d7J@c)nuO0wV(|5F6~pX&Y>d;h~CfPnrF76Wjb literal 0 HcmV?d00001 diff --git a/lib/runtime/wazero/testdata/digests.go b/lib/runtime/wazero/testdata/digests.go new file mode 100644 index 0000000000..2369408922 --- /dev/null +++ b/lib/runtime/wazero/testdata/digests.go @@ -0,0 +1,42 @@ +// Copyright 2021 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package testdata + +import ( + "archive/zip" + "bytes" + _ "embed" + "io" + "testing" + + "github.com/stretchr/testify/require" +) + +//go:embed digest.kusama.1482002.zip +var digestKusama1482002Zip []byte + +// DigestKusama1482002 returns the bytes of the Kusama digest +// for block 1482002. +func DigestKusama1482002(t *testing.T) (b []byte) { + bytesReader := bytes.NewReader(digestKusama1482002Zip) + + zipReader, err := zip.NewReader(bytesReader, int64(bytesReader.Len())) + require.NoError(t, err) + + require.Len(t, zipReader.File, 1) + zipFile := zipReader.File[0] + + file, err := zipFile.Open() + require.NoError(t, err) + + defer func() { + err := file.Close() + require.NoError(t, err) + }() + + b, err = io.ReadAll(file) + require.NoError(t, err) + + return b +}