├── .gitignore
├── .gitmodules
├── .python-version
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── build
├── node_template_runtime.wasm
├── polkadot_runtime-v9400.compact.compressed.wasm
└── runtime.wasm
├── config
└── module.go
├── constants
├── aura
│ ├── aura.go
│ └── call.go
├── balances
│ ├── call.go
│ └── deposit.go
├── currency.go
├── grandpa
│ ├── call.go
│ └── grandpa.go
├── keys.go
├── metadata
│ └── metadata.go
├── runtime_version.go
├── system
│ └── call.go
├── testable
│ └── call.go
├── timestamp
│ ├── call.go
│ ├── identifier.go
│ └── period.go
├── transaction_payment
│ ├── call.go
│ └── multipliers.go
└── weight.go
├── docs
├── README.md
├── docs
│ ├── assets
│ │ ├── images
│ │ │ ├── overview
│ │ │ │ └── host-runtime-interaction.svg
│ │ │ └── tutorials
│ │ │ │ ├── polkadot-js-accounts-balances.png
│ │ │ │ ├── polkadot-js-accounts.png
│ │ │ │ ├── polkadot-js-click-logo.png
│ │ │ │ ├── polkadot-js-local-network.png
│ │ │ │ ├── polkadot-js-switch-dev-local-network.png
│ │ │ │ ├── polkadot-js-transfer-inspect.png
│ │ │ │ ├── polkadot-js-transfer-sign-submit.png
│ │ │ │ ├── polkadot-js-transfer-success.png
│ │ │ │ └── polkadot-js-transfer.png
│ │ └── logo
│ │ │ ├── GOSEMBLE-Logo-Color-Dark.svg
│ │ │ ├── GOSEMBLE-Logo-Color-Light.svg
│ │ │ ├── GOSEMBLE-Logo-Dark.svg
│ │ │ └── GOSEMBLE-Logo-Light.svg
│ ├── development
│ │ ├── build.md
│ │ ├── file-structure.md
│ │ ├── inspect.md
│ │ ├── install.md
│ │ ├── test.md
│ │ └── toolchain-setup.md
│ ├── index.md
│ ├── overview
│ │ ├── modules.md
│ │ ├── runtime-architecture.md
│ │ └── toolchain.md
│ ├── reference
│ │ └── resources.md
│ ├── stylesheets
│ │ └── extra.css
│ └── tutorials
│ │ ├── start-a-network.md
│ │ └── transfer-funds.md
└── mkdocs.yml
├── env
├── allocator.go
├── allocator_nonwasm.go
├── crypto.go
├── crypto_nonwasm.go
├── hashing.go
├── hashing_nonwasm.go
├── log.go
├── log_nonwasm.go
├── miscellaneous.go
├── miscellaneous_nonwasm.go
├── storage.go
├── storage_nonwasm.go
├── trie.go
└── trie_nonwasm.go
├── execution
├── extrinsic
│ ├── checked.go
│ ├── interfaces.go
│ ├── payload.go
│ ├── unchecked.go
│ └── unsigned_validator.go
├── inherent
│ ├── check_inherents.go
│ └── inherent.go
└── types
│ ├── block.go
│ ├── call.go
│ ├── checked_extrinsic.go
│ ├── unchecked.go
│ └── unchecked_test.go
├── frame
├── account_nonce
│ └── account_nonce.go
├── aura
│ ├── aura.go
│ ├── hooks.go
│ └── module
│ │ └── module.go
├── balances
│ ├── dispatchables
│ │ ├── deposit.go
│ │ ├── force_free.go
│ │ ├── force_transfer.go
│ │ ├── set_balance.go
│ │ ├── transfer.go
│ │ ├── transfer_all.go
│ │ ├── transfer_keep_alive.go
│ │ ├── types.go
│ │ └── withdraw.go
│ ├── errors
│ │ └── errors.go
│ ├── events
│ │ └── events.go
│ └── module
│ │ └── module.go
├── block_builder
│ └── block_builder.go
├── core
│ └── core.go
├── executive
│ ├── executive.go
│ └── hooks.go
├── grandpa
│ ├── grandpa.go
│ └── module
│ │ └── module.go
├── metadata
│ └── metadata.go
├── offchain_worker
│ └── offchain_worker.go
├── session_keys
│ └── session_keys.go
├── support
│ ├── storage_value.go
│ └── transactional.go
├── system
│ ├── dispatchables
│ │ └── remark.go
│ ├── event.go
│ ├── events.go
│ ├── extensions
│ │ ├── check_genesis.go
│ │ ├── check_mortality.go
│ │ ├── check_non_zero_sender.go
│ │ ├── check_nonce.go
│ │ ├── check_spec_version.go
│ │ ├── check_tx_version.go
│ │ ├── check_weight.go
│ │ └── extensions.go
│ ├── hooks.go
│ ├── limits.go
│ ├── module
│ │ └── module.go
│ ├── storage.go
│ └── system.go
├── tagged_transaction_queue
│ └── tagged_transaction_queue.go
├── testable
│ ├── dispatchables
│ │ └── test_call.go
│ ├── module
│ │ └── module.go
│ └── testable.go
├── timestamp
│ ├── dispatchables
│ │ └── set.go
│ ├── hooks.go
│ ├── module
│ │ └── module.go
│ └── timestamp.go
└── transaction_payment
│ ├── charge_transaction_payment.go
│ ├── events.go
│ ├── module
│ └── module.go
│ └── transaction_payment.go
├── go.mod
├── go.sum
├── primitives
├── crypto
│ ├── crypto.go
│ └── crypto_nonwasm.go
├── hashing
│ ├── hashing.go
│ └── hashing_nonwasm.go
├── log
│ ├── log.go
│ └── log_nonwasm.go
├── storage
│ ├── storage.go
│ └── storage_nonwasm.go
├── trie
│ ├── trie.go
│ └── trie_nonwasm.go
└── types
│ ├── account_data.go
│ ├── account_info.go
│ ├── apply_extrinsic_result.go
│ ├── apply_extrinsic_result_test.go
│ ├── arithmetic_error.go
│ ├── authority.go
│ ├── balance_status.go
│ ├── call.go
│ ├── call_index_test.go
│ ├── check_inherents_result.go
│ ├── checked_extrinsic.go
│ ├── constant_multiplier.go
│ ├── dec_ref_status.go
│ ├── digest.go
│ ├── digest_item.go
│ ├── dispatch_class.go
│ ├── dispatch_errors.go
│ ├── dispatch_errors_test.go
│ ├── dispatch_info.go
│ ├── dispatch_outcome.go
│ ├── dispatch_outcome_test.go
│ ├── dispatch_result.go
│ ├── era.go
│ ├── era_test.go
│ ├── event.go
│ ├── existence_requirement.go
│ ├── extra.go
│ ├── extrinsic_signature.go
│ ├── extrinsic_signature_payload.go
│ ├── extrinsic_signature_payload_test.go
│ ├── extrinsic_signature_test.go
│ ├── fee_details.go
│ ├── hash.go
│ ├── header.go
│ ├── identity_fee.go
│ ├── inc_ref_status.go
│ ├── inclusion_fee.go
│ ├── inherent_data.go
│ ├── inherent_data_test.go
│ ├── interfaces.go
│ ├── is_fatal_error.go
│ ├── last_runtime_upgrade_info.go
│ ├── lookup.go
│ ├── metadata.go
│ ├── metadata_extrinsic.go
│ ├── metadata_module.go
│ ├── metadata_type_definition.go
│ ├── module.go
│ ├── multi_address.go
│ ├── multi_signature.go
│ ├── multi_signature_test.go
│ ├── pays.go
│ ├── perthings.go
│ ├── phase.go
│ ├── post_dispatch_info.go
│ ├── pre.go
│ ├── public_key.go
│ ├── reasons.go
│ ├── runtime_dispatch_info.go
│ ├── runtime_origin.go
│ ├── runtime_version.go
│ ├── session_key.go
│ ├── signature.go
│ ├── timestamp_error.go
│ ├── token_error.go
│ ├── transaction_errors.go
│ ├── transaction_errors_test.go
│ ├── transaction_source.go
│ ├── transaction_validity_result.go
│ ├── transactional_error.go
│ ├── transactional_outcome.go
│ ├── valid_transaction.go
│ ├── versioned_authority_list.go
│ ├── weight.go
│ ├── weight_to_fee.go
│ └── withdraw_reasons.go
├── runtime
├── account_nonce_test.go
├── aura_test.go
├── balances_force_free_test.go
├── balances_force_transfer_test.go
├── balances_set_balance_test.go
├── balances_transfer_all_test.go
├── balances_transfer_keep_alive_test.go
├── balances_transfer_test.go
├── block_builder_apply_extrinsic_test.go
├── block_builder_check_inherents_test.go
├── block_builder_inherent_extrinsics_test.go
├── core_execute_block_test.go
├── core_initialize_block_test.go
├── core_version_test.go
├── grandpa_test.go
├── metadata_test.go
├── offchain_worker_test.go
├── runtime.go
├── runtime_test.go
├── session_keys_test.go
├── transaction_payment_test.go
├── transactional_test.go
└── validate_transaction_test.go
└── utils
└── utils.go
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 |
3 | # JetBrains iDEA
4 | .idea
5 |
6 | .DS_Store
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "gossamer"]
2 | path = gossamer
3 | url = git@github.com:LimeChain/gossamer.git
4 | [submodule "tinygo"]
5 | path = tinygo
6 | url = git@github.com:LimeChain/tinygo.git
7 | [submodule "goscale"]
8 | path = goscale
9 | url = git@github.com:LimeChain/goscale.git
10 | [submodule "substrate"]
11 | path = substrate
12 | url = git@github.com:LimeChain/substrate.git
13 |
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
1 | 3.11.2
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | 0.0.0 (TODO)
3 | ---
4 | - **toolchain**
5 | - add separate Dockerfile and build script for building TinyGo with prebuild LLVM and dependencies for faster
6 | builds.
7 | - add new target similar to Rust's `wasm32-unknown-unknown` aimed to support Polkadot's Wasm MVP.
8 | - linker flag to declare memory as imported.
9 | - linker flags to export `__heap_base`, `__data_end` globals.
10 | - linker flags to export `__indirect_function_table`.
11 | - disable the scheduler to remove the support of *goroutines* and channels (and JS/WASI exports).
12 | - remove the unsupported features by Wasm MVP (bulk memory operations, lang. ext) and add implementation
13 | of `memmove`, `memset`, `memcpy`, use opt flag as part of the target.
14 | - remove the exported allocation functions.
15 | - implement GC that can work with external memory allocator.
16 | - **scale codec**
17 | - implement SCALE codec with minimal reflection
18 | - **runtime apis**
19 | - Core API.
20 | - `Core_version`
21 | - `Core_execute_block`
22 | - `Core_initialize_block`
23 | - Metadata API.
24 | - `Metadata_metadata`
25 | - BlockBuilder API.
26 | - `BlockBuilder_apply_extrinsic`
27 | - `BlockBuilder_finalize_block`
28 | - `BlockBuilder_inherent_extrinsics`
29 | - `BlockBuilder_check_inherents`
30 | - TaggedTransactionQueue API.
31 | - `TaggedTransactionQueue_validate_transaction`
32 | - OffchainWorker API.
33 | - `OffchainWorkerApi_offchain_worker`
34 | - Grandpa API.
35 | - `GrandpaApi_grandpa_authorities`
36 | - SessionKeys API.
37 | - `SessionKeys_generate_session_keys`
38 | - `SessionKeys_decode_session_keys`
39 | - AccountNonce API.
40 | - `AccountNonceApi_account_nonce`
41 | - TransactionPayment API.
42 | - `TransactionPaymentApi_query_info`
43 | - `TransactionPaymentApi_query_fee_details`
44 | - `TransactionPaymentCallApi_query_call_info`
45 | - `TransactionPaymentCallApi_query_call_fee_details`
46 | - Aura API.
47 | - `AuraApi_slot_duration`
48 | - `AuraApi_authorities`
49 | - **development & tests**
50 | - setup development and test environment by utilizing Gossamer and Substrate hosts.
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | CURRENT_DIR = $(shell pwd)
3 | SRC_DIR = /src/examples/wasm/gosemble
4 | BUILD_PATH = build/runtime.wasm
5 | IMAGE = polkawasm/tinygo
6 | TAG = 0.25.0
7 | BRANCH_CONSERVATIVE_GC = new-polkawasm-target-release-$(TAG)
8 | BRANCH_EXTALLOC_GC = new-polkawasm-target-extallocleak-gc-release-$(TAG)
9 |
10 | .PHONY: build
11 | build:
12 | @if [[ "$(GC)" == "conservative" ]]; then \
13 | cd tinygo; \
14 | git checkout $(BRANCH_CONSERVATIVE_GC); \
15 | cd ..; \
16 | docker build --tag $(IMAGE):$(TAG) -f tinygo/Dockerfile.polkawasm tinygo; \
17 | docker run --rm -v $(CURRENT_DIR):$(SRC_DIR) -w $(SRC_DIR) $(IMAGE):$(TAG) /bin/bash -c "tinygo build -target=polkawasm -o=$(SRC_DIR)/$(BUILD_PATH) $(SRC_DIR)/runtime/"; \
18 | echo "build - tinygo version: ${TAG}, gc: conservative"; \
19 | else \
20 | cd tinygo; \
21 | git checkout $(BRANCH_EXTALLOC_GC); \
22 | cd ..; \
23 | docker build --tag $(IMAGE):$(TAG)-extallocleak -f tinygo/Dockerfile.polkawasm tinygo; \
24 | docker run --rm -v $(CURRENT_DIR):$(SRC_DIR) -w $(SRC_DIR) $(IMAGE):$(TAG)-extallocleak /bin/bash -c "tinygo build -target=polkawasm -o=$(SRC_DIR)/$(BUILD_PATH) $(SRC_DIR)/runtime/"; \
25 | echo "build - tinygo version: ${TAG}, gc: extallocleak"; \
26 | fi
27 |
28 | build-local:
29 | @cd tinygo; \
30 | go install;
31 | @tinygo version
32 | @tinygo build -target=polkawasm -o=$(BUILD_PATH) runtime/runtime.go
33 |
34 | start-network:
35 | cp build/runtime.wasm substrate/bin/node-template/runtime.wasm; \
36 | cd substrate/bin/node-template; \
37 | cargo build --release; \
38 | cd ../..; \
39 | WASMTIME_BACKTRACE_DETAILS=1 ./target/release/node-template --dev --execution Wasm
40 |
41 | test: test_unit test_integration
42 |
43 | # TODO: ignore the integration tests
44 | test_unit:
45 | @go test --tags "nonwasmenv" -v `go list ./... | grep -v runtime`
46 |
47 | # GOARCH=amd64 is required to run the integration tests in gossamer
48 | test_integration:
49 | @GOARCH=amd64 go test --tags="nonwasmenv" -v ./runtime/... -timeout 2000s
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gosemble
2 |
3 | > **Warning**
4 | > The Gosemble is in pre-production
5 |
6 | Go implementation of Polkadot/Substrate compatible runtimes. For more details, check
7 | the [Official Documentation](https://limechain.github.io/gosemble/)
8 |
9 | ### Quick Start
10 |
11 | #### Prerequisites
12 |
13 | - [Git](https://git-scm.com/downloads)
14 | - [Go 1.19+](https://golang.org/doc/install)
15 | - [Docker](https://docs.docker.com/install/)
16 | - [Rust](https://docs.substrate.io/install/)
17 |
18 | #### Clone the repository
19 |
20 | ```bash
21 | git clone https://github.com/LimeChain/gosemble.git
22 | cd gosemble
23 | ```
24 |
25 | #### Pull all necessary git submodules
26 |
27 | ```bash
28 | git submodule update --init --recursive
29 | ```
30 |
31 | #### Build
32 |
33 | To build a runtime, execute:
34 |
35 | ```bash
36 | make build
37 | ```
38 |
39 | #### Start a local network
40 |
41 | After the runtime is built, start a local network using Substrate host:
42 |
43 | ```bash
44 | make start-network
45 | ```
46 |
47 | #### Run Tests
48 |
49 | After the Runtime is built, execute the tests with the help of [Gossamer](https://github.com/LimeChain/gossamer), which
50 | is used to import necessary Polkadot Host functionality and interact with the Runtime.
51 |
52 | ```bash
53 | make test_unit
54 | make test_integration
55 | ```
56 |
--------------------------------------------------------------------------------
/build/node_template_runtime.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/build/node_template_runtime.wasm
--------------------------------------------------------------------------------
/build/polkadot_runtime-v9400.compact.compressed.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/build/polkadot_runtime-v9400.compact.compressed.wasm
--------------------------------------------------------------------------------
/build/runtime.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/build/runtime.wasm
--------------------------------------------------------------------------------
/config/module.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants/aura"
6 | "github.com/LimeChain/gosemble/constants/balances"
7 | "github.com/LimeChain/gosemble/constants/grandpa"
8 | "github.com/LimeChain/gosemble/constants/system"
9 | "github.com/LimeChain/gosemble/constants/testable"
10 | "github.com/LimeChain/gosemble/constants/timestamp"
11 | "github.com/LimeChain/gosemble/constants/transaction_payment"
12 | am "github.com/LimeChain/gosemble/frame/aura/module"
13 | bm "github.com/LimeChain/gosemble/frame/balances/module"
14 | gm "github.com/LimeChain/gosemble/frame/grandpa/module"
15 | sm "github.com/LimeChain/gosemble/frame/system/module"
16 | tm "github.com/LimeChain/gosemble/frame/testable/module"
17 | tsm "github.com/LimeChain/gosemble/frame/timestamp/module"
18 | tpm "github.com/LimeChain/gosemble/frame/transaction_payment/module"
19 | "github.com/LimeChain/gosemble/primitives/types"
20 | )
21 |
22 | // Modules contains all the modules used by the runtime.
23 | var Modules = map[sc.U8]types.Module{
24 | system.ModuleIndex: sm.NewSystemModule(),
25 | timestamp.ModuleIndex: tsm.NewTimestampModule(),
26 | aura.ModuleIndex: am.NewAuraModule(),
27 | grandpa.ModuleIndex: gm.NewGrandpaModule(),
28 | balances.ModuleIndex: bm.NewBalancesModule(),
29 | transaction_payment.ModuleIndex: tpm.NewTransactionPaymentModule(),
30 | testable.ModuleIndex: tm.NewTestingModule(),
31 | }
32 |
--------------------------------------------------------------------------------
/constants/aura/aura.go:
--------------------------------------------------------------------------------
1 | package aura
2 |
3 | const MaxAuthorities = 100
4 |
5 | var (
6 | EngineId = [4]byte{'a', 'u', 'r', 'a'}
7 | KeyTypeId = [4]byte{'a', 'u', 'r', 'a'}
8 | )
9 |
--------------------------------------------------------------------------------
/constants/aura/call.go:
--------------------------------------------------------------------------------
1 | package aura
2 |
3 | const (
4 | ModuleIndex = 2
5 | )
6 |
--------------------------------------------------------------------------------
/constants/balances/call.go:
--------------------------------------------------------------------------------
1 | package balances
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | ModuleIndex = sc.U8(4)
7 | FunctionTransferIndex = 0
8 | FunctionSetBalanceIndex = 1
9 | FunctionForceTransferIndex = 2
10 | FunctionTransferKeepAliveIndex = 3
11 | FunctionTransferAllIndex = 4
12 | FunctionForceFreeIndex = 5
13 | )
14 |
--------------------------------------------------------------------------------
/constants/balances/deposit.go:
--------------------------------------------------------------------------------
1 | package balances
2 |
3 | import (
4 | "math/big"
5 |
6 | "github.com/LimeChain/gosemble/constants"
7 | )
8 |
9 | const (
10 | MaxLocks = 50
11 | MaxReserves = 50
12 | )
13 |
14 | var (
15 | existentialDeposit = 1 * constants.Dollar
16 | ExistentialDeposit = big.NewInt(0).SetUint64(existentialDeposit)
17 | )
18 |
--------------------------------------------------------------------------------
/constants/currency.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | import "math/big"
4 |
5 | const (
6 | MilliCents = Cents / 1000
7 | Cents = Dollar / 100
8 | Dollar = Units
9 | Units uint64 = 10_000_000_000
10 | )
11 |
12 | var (
13 | Zero = big.NewInt(0)
14 | )
15 |
--------------------------------------------------------------------------------
/constants/grandpa/call.go:
--------------------------------------------------------------------------------
1 | package grandpa
2 |
3 | const (
4 | ModuleIndex = 3
5 | )
6 |
--------------------------------------------------------------------------------
/constants/grandpa/grandpa.go:
--------------------------------------------------------------------------------
1 | package grandpa
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | var (
6 | AuthorityVersion sc.U8 = 1
7 | EngineId = [4]byte{'f', 'r', 'n', 'k'}
8 | KeyTypeId = [4]byte{'g', 'r', 'a', 'n'}
9 | )
10 |
--------------------------------------------------------------------------------
/constants/keys.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | var (
4 | KeySystem = []byte("System")
5 | KeyAccount = []byte("Account")
6 | KeyAllExtrinsicsLen = []byte("AllExtrinsicsLen")
7 | KeyAura = []byte("Aura")
8 | KeyAuthorities = []byte("Authorities")
9 | KeyBalances = []byte("Balances")
10 | KeyBlockHash = []byte("BlockHash")
11 | KeyBlockWeight = []byte("BlockWeight")
12 | KeyCurrentSlot = []byte("CurrentSlot")
13 | KeyDidUpdate = []byte("DidUpdate")
14 | KeyDigest = []byte("Digest")
15 | KeyEventCount = []byte("EventCount")
16 | KeyEvents = []byte("Events")
17 | KeyEventTopics = []byte("EventTopics")
18 | KeyExecutionPhase = []byte("ExecutionPhase")
19 | KeyExtrinsicCount = []byte("ExtrinsicCount")
20 | KeyExtrinsicData = []byte("ExtrinsicData")
21 | KeyExtrinsicIndex = []byte(":extrinsic_index")
22 | KeyGrandpaAuthorities = []byte(":grandpa_authorities")
23 | KeyLastRuntimeUpgrade = []byte("LastRuntimeUpgrade")
24 | KeyNextFeeMultiplier = []byte("NextFeeMultiplier")
25 | KeyNow = []byte("Now")
26 | KeyNumber = []byte("Number")
27 | KeyParentHash = []byte("ParentHash")
28 | KeyTimestamp = []byte("Timestamp")
29 | KeyTotalIssuance = []byte("TotalIssuance")
30 | KeyTransactionPayment = []byte("TransactionPayment")
31 | TransactionLevelKey = []byte(":transaction_level:")
32 | )
33 |
--------------------------------------------------------------------------------
/constants/metadata/metadata.go:
--------------------------------------------------------------------------------
1 | package metadata
2 |
3 | // Metadata types and their corresponding type id.
4 | const (
5 | PrimitiveTypesBool = iota
6 | PrimitiveTypesChar
7 | PrimitiveTypesString
8 | PrimitiveTypesU8
9 | PrimitiveTypesU16
10 | PrimitiveTypesU32
11 | PrimitiveTypesU64
12 | PrimitiveTypesU128
13 | PrimitiveTypesU256
14 | PrimitiveTypesI8
15 | PrimitiveTypesI16
16 | PrimitiveTypesI32
17 | PrimitiveTypesI64
18 | PrimitiveTypesI128
19 | PrimitiveTypesI256
20 |
21 | TypesFixedSequence4U8
22 | TypesFixedSequence20U8
23 | TypesFixedSequence32U8
24 | TypesFixedSequence64U8
25 | TypesFixedSequence65U8
26 |
27 | TypesSequenceU8
28 | TypesFixedU128
29 |
30 | TypesCompactU32
31 | TypesCompactU64
32 | TypesCompactU128
33 |
34 | TypesH256
35 |
36 | TypesVecBlockNumEventIndex
37 | TypesSystemEvent
38 | TypesSystemEventStorage
39 | TypesEventRecord
40 |
41 | TypesPhase
42 | TypesDispatchInfo
43 | TypesDispatchClass
44 | TypesPays
45 |
46 | TypesDispatchError
47 | TypesModuleError
48 | TypesTokenError
49 | TypesArithmeticError
50 | TypesTransactionalError
51 |
52 | TypesBalancesEvent
53 | TypesBalanceStatus
54 | TypesVecTopics
55 | TypesLastRuntimeUpgradeInfo
56 | TypesSystemErrors
57 | TypesBlockLength
58 | TypesPerDispatchClassU32
59 | TypesDbWeight
60 |
61 | TypesRuntimeApis
62 | TypesRuntimeVecApis
63 | TypesApiId
64 |
65 | TypesAuraStorageAuthorities
66 | TypesSequencePubKeys
67 | TypesAuthorityId
68 | TypesSr25519PubKey
69 | TypesAuraSlot
70 |
71 | TypesBalancesErrors
72 |
73 | TypesTransactionPaymentReleases
74 | TypesTransactionPaymentEvent
75 |
76 | TypesEmptyTuple
77 | TypesTupleU32U32
78 | TypesTupleApiIdU32
79 |
80 | TypesAddress32
81 | TypesMultiAddress
82 |
83 | TypesAccountData
84 | TypesAccountInfo
85 |
86 | TypesWeight
87 | TypesOptionWeight
88 | TypesPerDispatchClassWeight
89 | TypesPerDispatchClassWeightsPerClass
90 | TypesWeightPerClass
91 | TypesBlockWeights
92 |
93 | TypesDigestItem
94 | TypesSliceDigestItem
95 | TypesDigest
96 | TypesEra
97 |
98 | TypesSignatureEd25519
99 | TypesSignatureSr25519
100 | TypesSignatureEcdsa
101 | TypesMultiSignature
102 |
103 | TypesRuntimeEvent
104 | TypesRuntimeVersion
105 | RuntimeCall
106 |
107 | SystemCalls
108 | TimestampCalls
109 | GrandpaCalls
110 | BalancesCalls
111 |
112 | UncheckedExtrinsic
113 | SignedExtra
114 |
115 | CheckNonZeroSender
116 | CheckSpecVersion
117 | CheckTxVersion
118 | CheckGenesis
119 | CheckMortality
120 | CheckNonce
121 | CheckWeight
122 | ChargeTransactionPayment
123 |
124 | Runtime
125 | )
126 |
--------------------------------------------------------------------------------
/constants/runtime_version.go:
--------------------------------------------------------------------------------
1 | package constants
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/primitives/types"
6 | )
7 |
8 | // If the runtime behavior changes, increment spec_version and set impl_version to 0.
9 | // If only runtime implementation changes and behavior does not,
10 | // then leave spec_version as is and increment impl_version.
11 |
12 | const SpecName = "node-template"
13 | const ImplName = "node-template"
14 | const AuthoringVersion = 1
15 | const SpecVersion = 100
16 | const ImplVersion = 1
17 | const TransactionVersion = 1
18 | const StateVersion = 1
19 | const StorageVersion = 0
20 |
21 | const BlockHashCount = sc.U32(2400)
22 |
23 | // RuntimeVersion contains the version identifiers of the Runtime.
24 | var RuntimeVersion = types.RuntimeVersion{
25 | SpecName: sc.Str(SpecName),
26 | ImplName: sc.Str(ImplName),
27 | AuthoringVersion: sc.U32(AuthoringVersion),
28 | SpecVersion: sc.U32(SpecVersion),
29 | ImplVersion: sc.U32(ImplVersion),
30 | // Api Names are Blake2bHash8("ApiName")
31 | // Example: common.MustBlake2b8([]byte("Core") -> [223 106 203 104 153 7 96 155]
32 | Apis: sc.Sequence[types.ApiItem]{
33 | {
34 | Name: sc.NewFixedSequence[sc.U8](8, 223, 106, 203, 104, 153, 7, 96, 155), // Core
35 | Version: sc.U32(4),
36 | },
37 | {
38 | Name: sc.NewFixedSequence[sc.U8](8, 55, 227, 151, 252, 124, 145, 245, 228), // Metadata
39 | Version: sc.U32(1),
40 | },
41 | {
42 | Name: sc.NewFixedSequence[sc.U8](8, 64, 254, 58, 212, 1, 248, 149, 154), // BlockBuilder
43 | Version: sc.U32(6),
44 | },
45 | {
46 | Name: sc.NewFixedSequence[sc.U8](8, 210, 188, 152, 151, 238, 208, 143, 21), // TaggedTransactionQueue
47 | Version: sc.U32(3),
48 | },
49 | {
50 | Name: sc.NewFixedSequence[sc.U8](8, 247, 139, 39, 139, 229, 63, 69, 76), // OffchainWorkerApi
51 | Version: sc.U32(2),
52 | },
53 | {
54 | Name: sc.NewFixedSequence[sc.U8](8, 221, 113, 141, 92, 197, 50, 98, 212), // AuraApi
55 | Version: sc.U32(1),
56 | },
57 | {
58 | Name: sc.NewFixedSequence[sc.U8](8, 171, 60, 5, 114, 41, 31, 235, 139), // SessionKeys
59 | Version: sc.U32(1),
60 | },
61 | {
62 | Name: sc.NewFixedSequence[sc.U8](8, 237, 153, 197, 172, 178, 94, 237, 245), // GrandpaApi
63 | Version: sc.U32(3),
64 | },
65 | {
66 | Name: sc.NewFixedSequence[sc.U8](8, 188, 157, 137, 144, 79, 91, 146, 63), // AccountNonceApi
67 | Version: sc.U32(1),
68 | },
69 | {
70 | Name: sc.NewFixedSequence[sc.U8](8, 55, 200, 187, 19, 80, 169, 162, 168), // TransactionPaymentApi
71 | Version: sc.U32(3),
72 | },
73 | {
74 | Name: sc.NewFixedSequence[sc.U8](8, 243, 255, 20, 213, 171, 82, 112, 89), // TransactionPaymentCallApi
75 | Version: sc.U32(3),
76 | },
77 | },
78 | TransactionVersion: sc.U32(TransactionVersion),
79 | StateVersion: sc.U8(StateVersion),
80 | }
81 |
--------------------------------------------------------------------------------
/constants/system/call.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | ModuleIndex = sc.U8(0)
7 | FunctionRemarkIndex = 0
8 | )
9 |
--------------------------------------------------------------------------------
/constants/testable/call.go:
--------------------------------------------------------------------------------
1 | package testable
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | ModuleIndex = sc.U8(255)
7 | FunctionTestIndex = 255
8 | )
9 |
--------------------------------------------------------------------------------
/constants/timestamp/call.go:
--------------------------------------------------------------------------------
1 | package timestamp
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | ModuleIndex = sc.U8(1)
7 | FunctionSetIndex = 0
8 | )
9 |
--------------------------------------------------------------------------------
/constants/timestamp/identifier.go:
--------------------------------------------------------------------------------
1 | package timestamp
2 |
3 | var (
4 | InherentIdentifier = [8]byte{'t', 'i', 'm', 's', 't', 'a', 'p', '0'}
5 | )
6 |
--------------------------------------------------------------------------------
/constants/timestamp/period.go:
--------------------------------------------------------------------------------
1 | package timestamp
2 |
3 | const (
4 | MaxTimestampDriftMillis = 30 * 1_000 // 30 Seconds
5 | MinimumPeriod = 1 * 1_000 // 1 second
6 | )
7 |
--------------------------------------------------------------------------------
/constants/transaction_payment/call.go:
--------------------------------------------------------------------------------
1 | package transaction_payment
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | ModuleIndex = sc.U8(5)
7 | )
8 |
--------------------------------------------------------------------------------
/constants/transaction_payment/multipliers.go:
--------------------------------------------------------------------------------
1 | package transaction_payment
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | const (
6 | OperationalFeeMultiplier = sc.U8(5)
7 | )
8 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to MkDocs
2 |
3 | For full documentation visit [mkdocs.org](https://www.mkdocs.org).
4 |
5 | # Install
6 |
7 | ```bash
8 | pip install mkdocs mkdocs-material
9 | ```
10 |
11 | ## Commands
12 |
13 | * `mkdocs new [dir-name]` - Create a new project.
14 | * `mkdocs serve` - Start the live-reloading docs server.
15 | * `mkdocs build` - Build the documentation site.
16 | * `mkdocs -h` - Print help message and exit.
17 |
18 | ## Project layout
19 |
20 | mkdocs.yml # The configuration file.
21 | docs/
22 | index.md # The documentation homepage.
23 | ... # Other markdown pages, images and other files.
24 |
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-accounts-balances.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-accounts-balances.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-accounts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-accounts.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-click-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-click-logo.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-local-network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-local-network.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-switch-dev-local-network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-switch-dev-local-network.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-transfer-inspect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-transfer-inspect.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-transfer-sign-submit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-transfer-sign-submit.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-transfer-success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-transfer-success.png
--------------------------------------------------------------------------------
/docs/docs/assets/images/tutorials/polkadot-js-transfer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VeteranSoftDev/gosemble/856b7a7b8adf10f9344389e1902e5398b0b81843/docs/docs/assets/images/tutorials/polkadot-js-transfer.png
--------------------------------------------------------------------------------
/docs/docs/assets/logo/GOSEMBLE-Logo-Color-Dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/docs/assets/logo/GOSEMBLE-Logo-Color-Light.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/docs/assets/logo/GOSEMBLE-Logo-Dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/docs/assets/logo/GOSEMBLE-Logo-Light.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/docs/development/build.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Build
4 | permalink: /development/build
5 | ---
6 |
7 | By utilizing our [Toolchain](../../overview/toolchain), there are currently two options to choose from for the GC
8 | implementation. Modify the `GC` environment variable to switch between them.
9 |
10 | ### Extalloc GC
11 |
12 | It works with the host's external allocator as per specification.
13 |
14 | ```bash
15 | make build
16 | ```
17 |
18 | ### Conservative GC
19 |
20 | It is used only for **development** and **testing** and works by using a different heap base offset from the allocator's
21 | one (as a workaround), so the GC can use a separate heap region for its allocations and not interfere with the
22 | allocator's region.
23 |
24 | ```bash
25 | GC="conservative" make build
26 | ```
--------------------------------------------------------------------------------
/docs/docs/development/file-structure.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: File structure
4 | permalink: /development/file-structure
5 | ---
6 |
7 | * `build` - the output directory for the compiled Wasm file.
8 | * `config` - configuration of the used runtime modules (pallets).
9 | * `constants` - constants used in the runtime.
10 | * `env` - stubs for the host-provided functions.
11 | * `execution` - runtime execution logic.
12 | * `frame` - runtime modules (pallets).
13 | * `primitives` - runtime primitives.
14 | * `runtime` - runtime entry point and tests.
15 | * `utils` - utility functions.
16 | * `tinygo` - submodule for the TinyGo compiler, used for WASM compilation.
17 | * `goscale` - submodule for the SCALE codec.
18 | * `gossamer` - submodule for the Gossamer host, used during development and for running tests.
19 | * `substrate` - submodule for the Substrate host, used for running a network.
--------------------------------------------------------------------------------
/docs/docs/development/install.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Install
4 | permalink: /development/install
5 | ---
6 |
7 | **Prerequisites**
8 |
9 | * [Git](https://git-scm.com/downloads)
10 | * [Go 1.19+](https://golang.org/doc/install)
11 | * [Docker](https://docs.docker.com/install/)
12 | * [Rust](https://docs.substrate.io/install/)
13 |
14 | Clone the [Gosemble](https://github.com/LimeChain/gosemble.git) repository.
15 |
16 | ```bash
17 | git clone https://github.com/LimeChain/gosemble.git
18 | cd gosemble
19 | ```
20 |
21 | Pull all necessary git submodules.
22 |
23 | ```bash
24 | git submodule update --init --recursive
25 | ```
26 |
--------------------------------------------------------------------------------
/docs/docs/development/test.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /development/test
4 | ---
5 |
6 | Currently, the project contains unit and integration tests. Integration tests use [Gossamer](https://github.com/LimeChain/gossamer), which
7 | imports all the necessary Host functions and interacts with the Runtime.
8 |
9 | ```bash
10 | make test
11 | ```
12 |
13 | or
14 |
15 | ```bash
16 | make test_unit
17 | make test_integration
18 | ```
19 |
20 | ### Debug
21 |
22 | To aid the debugging process, there is a set of imported functions that can be called within the Runtime to log messages.
23 |
24 | ```go
25 | func Critical(message string) // logs and aborts the execution
26 | func Warn(message string)
27 | func Info(message string)
28 | func Debug(message string)
29 | func Trace(message string)
30 | ```
--------------------------------------------------------------------------------
/docs/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /
4 | ---
5 |
6 | **Go implementation of Polkadot/Substrate compatible runtimes**
7 |
8 | The following project is based on [**previous research**](https://github.com/LimeChain/gosemble-research), funded by
9 | [**Web3 Foundation**](https://web3.foundation) **Grants**, and developed and maintained by [**LimeChain
10 | **](https://limechain.tech). The research provides conclusions if _Go_ is a suitable choice for writing Polkadot
11 | Runtimes and further aids the development of a _Go_ toolchain, capable of producing compatible runtimes.
12 |
13 | While there are several implementations of Polkadot Hosts in [Rust](https://github.com/paritytech/substrate),
14 | [C++](https://github.com/soramitsu/kagome), and [Go](https://github.com/ChainSafe/gossamer), the only option for writing
15 | Polkadot Runtimes is in [Rust](https://github.com/paritytech/substrate). Writing Polkadot Runtimes in _Go_ is exciting,
16 | mainly because of _Go_'s simplicity and automatic memory management. It is a modern, powerful, and fast language, backed
17 | by Google and used in many of their software, thus making it an ideal candidate for implementing Polkadot Runtimes.
18 |
19 |
--------------------------------------------------------------------------------
/docs/docs/overview/modules.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Modules
4 | permalink: /overview/modules
5 | ---
6 |
7 | Currently supported:
8 |
9 | * **System** - The most fundamental module that provides low-level types, storage, and functions which are essential for other modules.
10 | * **Timestamp** - This module provides timestamp capabilities, which are required by many other pallets.
11 | * **Balances** - This module manages token balances. It's crucial for any blockchain that supports a native currency.
12 | * **Aura** - This module provides block production capabilities for the PoA consensus mechanism.
13 |
--------------------------------------------------------------------------------
/docs/docs/overview/toolchain.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Toolchain
4 | permalink: /overview/toolchain
5 | ---
6 |
7 | Since we use a [modified version of TinyGo](https://github.com/LimeChain/tinygo) for compiling Go to Wasm, some of Go's
8 | language capabilities cannot be applied due to the limited support in TinyGo which also affects some of the design
9 | decisions.
10 |
--------------------------------------------------------------------------------
/docs/docs/reference/resources.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Resources
4 | permalink: /reference/resources
5 | ---
6 |
7 | ### Polkadot
8 |
9 | * [General](https://polkadot.network/)
10 | * [Wiki](https://wiki.polkadot.network/)
11 | * [Specification](https://spec.polkadot.network/)
12 |
13 | ### Substrate
14 |
15 | * [Docs](https://docs.substrate.io/)
16 |
17 | ### W3F
18 |
19 | * [Research](https://web3.foundation/research/)
20 |
21 | ### WebAssembly
22 |
23 | * [Specification](https://webassembly.org/specs/)
24 |
25 | ### Go / TinyGo
26 |
27 | * [Go Docs](https://go.dev/doc/)
28 | * [TinyGo Docs](https://tinygo.org/docs/)
--------------------------------------------------------------------------------
/docs/docs/stylesheets/extra.css:
--------------------------------------------------------------------------------
1 | [data-md-color-primary="pink"] {
2 | --md-primary-fg-color: #fe0088;
3 | --md-primary-fg-color--light: #fd3ea4;
4 | --md-primary-fg-color--dark: #c3185d;
5 | --md-primary-bg-color: #f1f1f1;
6 | }
7 |
8 | .md-header,
9 | .md-tabs {
10 | background: #28133e;
11 | }
12 |
13 | .md-header__title {
14 | visibility: hidden;
15 | }
--------------------------------------------------------------------------------
/env/allocator.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Allocator: Provides functionality for calling into the memory allocator.
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_allocator_free_version_1
11 | func ExtAllocatorFreeVersion1(ptr int32)
12 |
13 | //go:wasm-module env
14 | //go:export ext_allocator_malloc_version_1
15 | func ExtAllocatorMallocVersion1(size int32) int32
16 |
--------------------------------------------------------------------------------
/env/allocator_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Allocator: Provides functionality for calling into the memory allocator.
7 | */
8 |
9 | func ExtAllocatorFreeVersion1(ptr int32) {
10 | panic("not implemented")
11 | }
12 |
13 | func ExtAllocatorMallocVersion1(size int32) int32 {
14 | panic("not implemented")
15 | }
16 |
--------------------------------------------------------------------------------
/env/crypto.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Crypto: Interfaces for working with crypto related types from within the runtime.
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_crypto_ed25519_generate_version_1
11 | func ExtCryptoEd25519GenerateVersion1(key_type_id int32, seed int64) int32
12 |
13 | //go:wasm-module env
14 | //go:export ext_crypto_ed25519_verify_version_1
15 | func ExtCryptoEd25519VerifyVersion1(sig int32, msg int64, key int32) int32
16 |
17 | //go:wasm-module env
18 | //go:export ext_crypto_finish_batch_verify_version_1
19 | func ExtCryptoFinishBatchVerifyVersion1() int32
20 |
21 | //go:wasm-module env
22 | //go:export ext_crypto_secp256k1_ecdsa_recover_version_2
23 | func ExtCryptoSecp256k1EcdsaRecoverVersion2(sig int32, msg int32) int64
24 |
25 | //go:wasm-module env
26 | //go:export ext_crypto_secp256k1_ecdsa_recover_compressed_version_2
27 | func ExtCryptoSecp256k1EcdsaRecoverCompressedVersion2(sig int32, msg int32) int64
28 |
29 | //go:wasm-module env
30 | //go:export ext_crypto_sr25519_generate_version_1
31 | func ExtCryptoSr25519GenerateVersion1(key_type_id int32, seed int64) int32
32 |
33 | //go:wasm-module env
34 | //go:export ext_crypto_sr25519_public_keys_version_1
35 | func ExtCryptoSr25519PublicKeysVersion1(key_type_id int32) int64
36 |
37 | //go:wasm-module env
38 | //go:export ext_crypto_sr25519_sign_version_1
39 | func ExtCryptoSr25519SignVersion1(key_type_id int32, key int32, msg int64) int64
40 |
41 | //go:wasm-module env
42 | //go:export ext_crypto_sr25519_verify_version_2
43 | func ExtCryptoSr25519VerifyVersion2(sig int32, msg int64, key int32) int32
44 |
45 | //go:wasm-module env
46 | //go:export ext_crypto_start_batch_verify_version_1
47 | func ExtCryptoStartBatchVerifyVersion1()
48 |
--------------------------------------------------------------------------------
/env/crypto_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Crypto: Interfaces for working with crypto related types from within the runtime.
7 | */
8 |
9 | func ExtCryptoEd25519GenerateVersion1(key_type_id int32, seed int64) int32 {
10 | panic("not implemented")
11 | }
12 |
13 | func ExtCryptoEd25519VerifyVersion1(sig int32, msg int64, key int32) int32 {
14 | panic("not implemented")
15 | }
16 |
17 | func ExtCryptoFinishBatchVerifyVersion1() int32 {
18 | panic("not implemented")
19 | }
20 |
21 | func ExtCryptoSecp256k1EcdsaRecoverVersion2(sig int32, msg int32) int64 {
22 | panic("not implemented")
23 | }
24 |
25 | func ExtCryptoSecp256k1EcdsaRecoverCompressedVersion2(sig int32, msg int32) int64 {
26 | panic("not implemented")
27 | }
28 |
29 | func ExtCryptoSr25519GenerateVersion1(key_type_id int32, seed int64) int32 {
30 | panic("not implemented")
31 | }
32 |
33 | func ExtCryptoSr25519PublicKeysVersion1(key_type_id int32) int64 {
34 | panic("not implemented")
35 | }
36 |
37 | func ExtCryptoSr25519SignVersion1(key_type_id int32, key int32, msg int64) int64 {
38 | panic("not implemented")
39 | }
40 |
41 | func ExtCryptoSr25519VerifyVersion2(sig int32, msg int64, key int32) int32 {
42 | panic("not implemented")
43 | }
44 |
45 | func ExtCryptoStartBatchVerifyVersion1() {
46 | panic("not implemented")
47 | }
48 |
--------------------------------------------------------------------------------
/env/hashing.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Hashing: Interface that provides functions for hashing with different algorithms.
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_hashing_blake2_128_version_1
11 | func ExtHashingBlake2128Version1(data int64) int32
12 |
13 | //go:wasm-module env
14 | //go:export ext_hashing_blake2_256_version_1
15 | func ExtHashingBlake2256Version1(data int64) int32
16 |
17 | //go:wasm-module env
18 | //go:export ext_hashing_keccak_256_version_1
19 | func ExtHashingKeccak256Version1(data int64) int32
20 |
21 | //go:wasm-module env
22 | //go:export ext_hashing_twox_128_version_1
23 | func ExtHashingTwox128Version1(data int64) int32
24 |
25 | //go:wasm-module env
26 | //go:export ext_hashing_twox_64_version_1
27 | func ExtHashingTwox64Version1(data int64) int32
28 |
--------------------------------------------------------------------------------
/env/hashing_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Hashing: Interface that provides functions for hashing with different algorithms.
7 | */
8 |
9 | func ExtHashingBlake2128Version1(data int64) int32 {
10 | panic("not implemented")
11 | }
12 |
13 | func ExtHashingBlake2256Version1(data int64) int32 {
14 | panic("not implemented")
15 | }
16 |
17 | func ExtHashingKeccak256Version1(data int64) int32 {
18 | panic("not implemented")
19 | }
20 |
21 | func ExtHashingTwox128Version1(data int64) int32 {
22 | panic("not implemented")
23 | }
24 |
25 | func ExtHashingTwox64Version1(data int64) int32 {
26 | panic("not implemented")
27 | }
28 |
--------------------------------------------------------------------------------
/env/log.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Log: Request to print a log message on the host. Note that this will be
7 | only displayed if the host is enabled to display log messages with given level and target.
8 | */
9 |
10 | //go:wasm-module env
11 | //go:export ext_logging_log_version_1
12 | func ExtLoggingLogVersion1(level int32, target int64, message int64)
13 |
14 | //go:wasm-module env
15 | //go:export ext_logging_max_level_version_1
16 | func ExtLoggingMaxLevelVersion1() int32
17 |
--------------------------------------------------------------------------------
/env/log_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Log: Request to print a log message on the host. Note that this will be
7 | only displayed if the host is enabled to display log messages with given level and target.
8 | */
9 |
10 | func ExtLoggingLogVersion1(level int32, target int64, message int64) {
11 | panic("not implemented")
12 | }
13 |
14 | func ExtLoggingMaxLevelVersion1() int32 {
15 | panic("not implemented")
16 | }
17 |
--------------------------------------------------------------------------------
/env/miscellaneous.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Miscellaneous: Interface that provides miscellaneous functions for communicating between the runtime and the node.
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_misc_print_hex_version_1
11 | func ExtMiscPrintHexVersion1(data int64)
12 |
13 | //go:wasm-module env
14 | //go:export ext_misc_print_utf8_version_1
15 | func ExtMiscPrintUtf8Version1(data int64)
16 |
17 | //go:wasm-module env
18 | //go:export ext_misc_runtime_version_version_1
19 | func ExtMiscRuntimeVersionVersion1(data int64) int64
20 |
--------------------------------------------------------------------------------
/env/miscellaneous_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Miscellaneous: Interface that provides miscellaneous functions for communicating between the runtime and the node.
7 | */
8 |
9 | func ExtMiscPrintHexVersion1(data int64) {
10 | panic("not implemented")
11 | }
12 |
13 | func ExtMiscPrintUtf8Version1(data int64) {
14 | panic("not implemented")
15 | }
16 |
17 | func ExtMiscRuntimeVersionVersion1(data int64) int64 {
18 | panic("not implemented")
19 | }
20 |
--------------------------------------------------------------------------------
/env/storage.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Storage: Interface for manipulating the storage from within the runtime.
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_storage_append_version_1
11 | func ExtStorageAppendVersion1(key int64, value int64)
12 |
13 | //go:wasm-module env
14 | //go:export ext_storage_clear_version_1
15 | func ExtStorageClearVersion1(key_data int64)
16 |
17 | //go:wasm-module env
18 | //go:export ext_storage_clear_prefix_version_2
19 | func ExtStorageClearPrefixVersion2(prefix int64, limit int64) int64
20 |
21 | //go:wasm-module env
22 | //go:export ext_storage_exists_version_1
23 | func ExtStorageExistsVersion1(key int64) int32
24 |
25 | //go:wasm-module env
26 | //go:export ext_storage_get_version_1
27 | func ExtStorageGetVersion1(key int64) int64
28 |
29 | //go:wasm-module env
30 | //go:export ext_storage_next_key_version_1
31 | func ExtStorageNextKeyVersion1(key int64) int64
32 |
33 | //go:wasm-module env
34 | //go:export ext_storage_read_version_1
35 | func ExtStorageReadVersion1(key int64, value_out int64, offset int32) int64
36 |
37 | //go:wasm-module env
38 | //go:export ext_storage_root_version_2
39 | func ExtStorageRootVersion2(key int32) int64
40 |
41 | //go:wasm-module env
42 | //go:export ext_storage_set_version_1
43 | func ExtStorageSetVersion1(key int64, value int64)
44 |
45 | //go:wasm-module env
46 | //go:export ext_storage_start_transaction_version_1
47 | func ExtStorageStartTransactionVersion1()
48 |
49 | //go:wasm-module env
50 | //go:export ext_storage_commit_transaction_version_1
51 | func ExtStorageCommitTransactionVersion()
52 |
53 | //go:wasm-module env
54 | //go:export ext_storage_rollback_transaction_version_1
55 | func ExtStorageRollbackTransactionVersion1()
56 |
--------------------------------------------------------------------------------
/env/storage_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Storage: Interface for manipulating the storage from within the runtime.
7 | */
8 |
9 | func ExtStorageAppendVersion1(key int64, value int64) int64 {
10 | panic("not implemented")
11 | }
12 |
13 | func ExtStorageClearVersion1(key_data int64) {
14 | panic("not implemented")
15 | }
16 |
17 | func ExtStorageClearPrefixVersion2(prefix int64, limit int64) int64 {
18 | panic("not implemented")
19 | }
20 |
21 | func ExtStorageCommitTransactionVersion() {
22 | panic("not implemented")
23 | }
24 |
25 | func ExtStorageExistsVersion1(key int64) int32 {
26 | panic("not implemented")
27 | }
28 |
29 | func ExtStorageGetVersion1(key int64) int64 {
30 | panic("not implemented")
31 | }
32 |
33 | func ExtStorageNextKeyVersion1(key int64) int64 {
34 | panic("not implemented")
35 | }
36 |
37 | func ExtStorageReadVersion1(key int64, value_out int64, offset int32) int64 {
38 | panic("not implemented")
39 | }
40 |
41 | func ExtStorageRollbackTransactionVersion1() {
42 | panic("not implemented")
43 | }
44 |
45 | func ExtStorageRootVersion2(key int32) int64 {
46 | panic("not implemented")
47 | }
48 |
49 | func ExtStorageSetVersion1(key int64, value int64) {
50 | panic("not implemented")
51 | }
52 |
53 | func ExtStorageStartTransactionVersion1() {
54 | panic("not implemented")
55 | }
56 |
--------------------------------------------------------------------------------
/env/trie.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Trie: Interface that provides trie related functionality
7 | */
8 |
9 | //go:wasm-module env
10 | //go:export ext_trie_blake2_256_ordered_root_version_2
11 | func ExtTrieBlake2256OrderedRootVersion2(input int64, version int32) int32
12 |
--------------------------------------------------------------------------------
/env/trie_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package env
4 |
5 | /*
6 | Trie: Interface that provides trie related functionality
7 | */
8 |
9 | func ExtTrieBlake2256OrderedRootVersion2(input int64, version int32) int32 {
10 | panic("not implemented")
11 | }
12 |
--------------------------------------------------------------------------------
/execution/extrinsic/interfaces.go:
--------------------------------------------------------------------------------
1 | package extrinsic
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | primitives "github.com/LimeChain/gosemble/primitives/types"
6 | )
7 |
8 | type Applyable interface {
9 | Apply(validator UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo], err primitives.TransactionValidityError)
10 | }
11 |
12 | type Validatable interface {
13 | Validate(validator UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError)
14 | }
15 |
16 | // UnsignedValidator provides validation for unsigned extrinsics.
17 | //
18 | // This trait provides two functions [`pre_dispatch`](Self::pre_dispatch) and
19 | // [`validate_unsigned`](Self::validate_unsigned). The [`pre_dispatch`](Self::pre_dispatch)
20 | // function is called right before dispatching the call wrapped by an unsigned extrinsic. The
21 | // [`validate_unsigned`](Self::validate_unsigned) function is mainly being used in the context of
22 | // the transaction pool to check the validity of the call wrapped by an unsigned extrinsic.
23 | type UnsignedValidator interface {
24 | // PreDispatch validates the call right before dispatch.
25 | //
26 | // This method should be used to prevent transactions already in the pool
27 | // (i.e. passing [`validate_unsigned`](Self::validate_unsigned)) from being included in blocks
28 | // in case they became invalid since being added to the pool.
29 | //
30 | // By default it's a good idea to call [`validate_unsigned`](Self::validate_unsigned) from
31 | // within this function again to make sure we never include an invalid transaction. Otherwise
32 | // the implementation of the call or this method will need to provide proper validation to
33 | // ensure that the transaction is valid.
34 | //
35 | // Changes made to storage *WILL* be persisted if the call returns `Ok`.
36 | PreDispatch(call *primitives.Call) (ok sc.Empty, err primitives.TransactionValidityError)
37 |
38 | // ValidateUnsigned returns the validity of the call
39 | //
40 | // This method has no side-effects. It merely checks whether the call would be rejected
41 | // by the runtime in an unsigned extrinsic.
42 | //
43 | // The validity checks should be as lightweight as possible because every node will execute
44 | // this code before the unsigned extrinsic enters the transaction pool and also periodically
45 | // afterwards to ensure the validity. To prevent dos-ing a network with unsigned
46 | // extrinsics, these validity checks should include some checks around uniqueness, for example,
47 | // like checking that the unsigned extrinsic was send by an authority in the active set.
48 | //
49 | // Changes made to storage should be discarded by caller.
50 | ValidateUnsigned(source primitives.TransactionSource, call *primitives.Call) (ok primitives.ValidTransaction, err primitives.TransactionValidityError)
51 | }
52 |
--------------------------------------------------------------------------------
/execution/extrinsic/payload.go:
--------------------------------------------------------------------------------
1 | package extrinsic
2 |
3 | import (
4 | system "github.com/LimeChain/gosemble/frame/system/extensions"
5 | primitives "github.com/LimeChain/gosemble/primitives/types"
6 | )
7 |
8 | // NewSignedPayload creates a new `SignedPayload`.
9 | // It may fail if `additional_signed` of `Extra` is not available.
10 | func NewSignedPayload(call primitives.Call, extra primitives.SignedExtra) (primitives.SignedPayload, primitives.TransactionValidityError) {
11 | additionalSigned, err := system.Extra(extra).AdditionalSigned()
12 | if err != nil {
13 | return primitives.SignedPayload{}, err
14 | }
15 |
16 | return primitives.SignedPayload{
17 | Call: call,
18 | Extra: extra,
19 | AdditionalSigned: additionalSigned,
20 | }, nil
21 | }
22 |
--------------------------------------------------------------------------------
/execution/extrinsic/unchecked.go:
--------------------------------------------------------------------------------
1 | package extrinsic
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/execution/types"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | type Unchecked types.UncheckedExtrinsic
10 |
11 | func (uxt Unchecked) Check(lookup primitives.AccountIdLookup) (ok types.CheckedExtrinsic, err primitives.TransactionValidityError) {
12 | switch uxt.Signature.HasValue {
13 | case true:
14 | signer, signature, extra := uxt.Signature.Value.Signer, uxt.Signature.Value.Signature, uxt.Signature.Value.Extra
15 |
16 | signedAddress, err := lookup.Lookup(signer)
17 | if err != nil {
18 | return ok, err
19 | }
20 |
21 | rawPayload, err := NewSignedPayload(uxt.Function, extra)
22 | if err != nil {
23 | return ok, err
24 | }
25 |
26 | if !signature.Verify(rawPayload.UsingEncoded(), signedAddress) {
27 | err := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadProof())
28 | return ok, err
29 | }
30 |
31 | function, extra, _ := rawPayload.Call, rawPayload.Extra, rawPayload.AdditionalSigned
32 |
33 | ok = types.CheckedExtrinsic{
34 | Signed: sc.NewOption[primitives.AccountIdExtra](primitives.AccountIdExtra{Address32: signedAddress, SignedExtra: extra}),
35 | Function: function,
36 | }
37 | case false:
38 | ok = types.CheckedExtrinsic{
39 | Signed: sc.NewOption[primitives.AccountIdExtra](nil),
40 | Function: uxt.Function,
41 | }
42 | }
43 |
44 | return ok, err
45 | }
46 |
--------------------------------------------------------------------------------
/execution/extrinsic/unsigned_validator.go:
--------------------------------------------------------------------------------
1 | package extrinsic
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/config"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | type UnsignedValidatorForChecked struct{}
10 |
11 | // PreDispatch validates the dispatch call before execution.
12 | // Inherent call is accepted for being dispatched
13 | func (v UnsignedValidatorForChecked) PreDispatch(call *primitives.Call) (sc.Empty, primitives.TransactionValidityError) {
14 | module, ok := config.Modules[(*call).ModuleIndex()]
15 | if !ok {
16 | return sc.Empty{}, nil
17 | }
18 |
19 | return module.PreDispatch(*call)
20 | }
21 |
22 | // ValidateUnsigned returns the validity of the dispatch call.
23 | // Inherent call is not validated as unsigned
24 | func (v UnsignedValidatorForChecked) ValidateUnsigned(_source primitives.TransactionSource, call *primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) {
25 | module, ok := config.Modules[(*call).ModuleIndex()]
26 | if !ok {
27 | return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator())
28 | }
29 |
30 | return module.ValidateUnsigned(_source, *call)
31 | }
32 |
--------------------------------------------------------------------------------
/execution/inherent/check_inherents.go:
--------------------------------------------------------------------------------
1 | package inherent
2 |
3 | import (
4 | tsc "github.com/LimeChain/gosemble/constants/timestamp"
5 | "github.com/LimeChain/gosemble/execution/types"
6 | "github.com/LimeChain/gosemble/frame/timestamp"
7 | primitives "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | func CheckExtrinsics(data primitives.InherentData, block types.Block) primitives.CheckInherentsResult {
11 | result := primitives.NewCheckInherentsResult()
12 |
13 | for _, extrinsic := range block.Extrinsics {
14 | // Inherents are before any other extrinsics.
15 | // And signed extrinsics are not inherents.
16 | if extrinsic.IsSigned() {
17 | break
18 | }
19 |
20 | isInherent := false
21 | call := extrinsic.Function
22 |
23 | switch call.ModuleIndex() {
24 | case tsc.ModuleIndex:
25 | switch call.FunctionIndex() {
26 | case tsc.FunctionSetIndex:
27 | isInherent = true
28 | err := timestamp.CheckInherent(call.Args(), data)
29 | if err != nil {
30 | err := result.PutError(tsc.InherentIdentifier, err.(primitives.IsFatalError))
31 | if err != nil {
32 | panic(err)
33 | }
34 |
35 | if result.FatalError {
36 | return result
37 | }
38 | }
39 | }
40 | }
41 |
42 | // Inherents are before any other extrinsics.
43 | // No module marked it as inherent thus it is not.
44 | if !isInherent {
45 | break
46 | }
47 | }
48 |
49 | // TODO: go through all required pallets with required inherents
50 |
51 | return result
52 | }
53 |
--------------------------------------------------------------------------------
/execution/inherent/inherent.go:
--------------------------------------------------------------------------------
1 | package inherent
2 |
3 | import (
4 | "github.com/LimeChain/gosemble/execution/types"
5 | )
6 |
7 | // EnsureInherentsAreFirst checks if the inherents are before non-inherents.
8 | func EnsureInherentsAreFirst(block types.Block) int {
9 | signedExtrinsicFound := false
10 |
11 | for i, extrinsic := range block.Extrinsics {
12 | isInherent := false
13 |
14 | if extrinsic.IsSigned() {
15 | // Signed extrinsics are not inherents
16 | isInherent = false
17 | } else {
18 | call := extrinsic.Function
19 | // Iterate through all calls and check if the given call is inherent
20 | if call.IsInherent() {
21 | isInherent = true
22 | }
23 | }
24 |
25 | if !isInherent {
26 | signedExtrinsicFound = true
27 | }
28 |
29 | if signedExtrinsicFound && isInherent {
30 | return i
31 | }
32 | }
33 |
34 | return -1
35 | }
36 |
--------------------------------------------------------------------------------
/execution/types/block.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | type Block struct {
11 | Header types.Header
12 | Extrinsics sc.Sequence[UncheckedExtrinsic]
13 | }
14 |
15 | func (b Block) Encode(buffer *bytes.Buffer) {
16 | buffer.Write(b.Header.Bytes())
17 | buffer.Write(b.Extrinsics.Bytes())
18 | }
19 |
20 | func (b Block) Bytes() []byte {
21 | return sc.EncodedBytes(b)
22 | }
23 |
24 | func DecodeBlock(buffer *bytes.Buffer) Block {
25 | header := types.DecodeHeader(buffer)
26 |
27 | size := sc.DecodeCompact(buffer)
28 | length := size.ToBigInt()
29 | extrinsics := make([]UncheckedExtrinsic, length.Int64())
30 |
31 | for i := 0; i < len(extrinsics); i++ {
32 | extrinsics[i] = DecodeUncheckedExtrinsic(buffer)
33 | }
34 |
35 | return Block{
36 | Header: header,
37 | Extrinsics: extrinsics,
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/execution/types/call.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 |
7 | sc "github.com/LimeChain/goscale"
8 |
9 | "github.com/LimeChain/gosemble/config"
10 | "github.com/LimeChain/gosemble/primitives/log"
11 | primitives "github.com/LimeChain/gosemble/primitives/types"
12 | )
13 |
14 | func DecodeCall(buffer *bytes.Buffer) primitives.Call {
15 | moduleIndex := sc.DecodeU8(buffer)
16 | functionIndex := sc.DecodeU8(buffer)
17 |
18 | module, ok := config.Modules[moduleIndex]
19 | if !ok {
20 | log.Critical(fmt.Sprintf("module with index [%d] not found", moduleIndex))
21 | }
22 |
23 | function, ok := module.Functions()[functionIndex]
24 | if !ok {
25 | log.Critical(fmt.Sprintf("function index [%d] for module [%d] not found", functionIndex, moduleIndex))
26 | }
27 |
28 | function = function.DecodeArgs(buffer)
29 |
30 | return function
31 | }
32 |
--------------------------------------------------------------------------------
/execution/types/checked_extrinsic.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | primitives "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | // CheckedExtrinsic is the definition of something that the external world might want to say; its
11 | // existence implies that it has been checked and is good, particularly with
12 | // regards to the signature.
13 | //
14 | // TODO: make it generic
15 | // generic::CheckedExtrinsic;
16 | type CheckedExtrinsic struct {
17 | Version sc.U8
18 |
19 | // Who this purports to be from and the number of extrinsics have come before
20 | // from the same signer, if anyone (note this is not a signature).
21 | Signed sc.Option[primitives.AccountIdExtra]
22 | Function primitives.Call
23 | }
24 |
25 | func (cxt CheckedExtrinsic) Encode(buffer *bytes.Buffer) {
26 | cxt.Version.Encode(buffer)
27 | cxt.Signed.Encode(buffer)
28 | cxt.Function.Encode(buffer)
29 | }
30 |
31 | func (cxt CheckedExtrinsic) Bytes() []byte {
32 | return sc.EncodedBytes(cxt)
33 | }
34 |
--------------------------------------------------------------------------------
/frame/account_nonce/account_nonce.go:
--------------------------------------------------------------------------------
1 | package account_nonce
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/frame/system"
7 | "github.com/LimeChain/gosemble/primitives/types"
8 | "github.com/LimeChain/gosemble/utils"
9 | )
10 |
11 | // AccountNonce returns the account nonce of given AccountId.
12 | // It takes two arguments:
13 | // - dataPtr: Pointer to the data in the Wasm memory.
14 | // - dataLen: Length of the data.
15 | // which represent the SCALE-encoded AccountId.
16 | // Returns a pointer-size of the SCALE-encoded nonce of the AccountId.
17 | // [Specification](https://spec.polkadot.network/chap-runtime-api#sect-accountnonceapi-account-nonce)
18 | func AccountNonce(dataPtr int32, dataLen int32) int64 {
19 | b := utils.ToWasmMemorySlice(dataPtr, dataLen)
20 | buffer := bytes.NewBuffer(b)
21 |
22 | publicKey := types.DecodePublicKey(buffer)
23 | nonce := system.StorageGetAccount(publicKey).Nonce
24 |
25 | return utils.BytesToOffsetAndSize(nonce.Bytes())
26 | }
27 |
--------------------------------------------------------------------------------
/frame/aura/hooks.go:
--------------------------------------------------------------------------------
1 | package aura
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants"
6 | "github.com/LimeChain/gosemble/primitives/hashing"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | "github.com/LimeChain/gosemble/primitives/storage"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | )
11 |
12 | func OnInitialize() types.Weight {
13 | slot := currentSlotFromDigests()
14 |
15 | if slot.HasValue {
16 | newSlot := slot.Value
17 |
18 | auraHash := hashing.Twox128(constants.KeyAura)
19 | currentSlotHash := hashing.Twox128(constants.KeyCurrentSlot)
20 |
21 | currentSlot := storage.GetDecode(append(auraHash, currentSlotHash...), sc.DecodeU64)
22 |
23 | if currentSlot >= newSlot {
24 | log.Critical("Slot must increase")
25 | }
26 |
27 | storage.Set(append(auraHash, currentSlotHash...), newSlot.Bytes())
28 |
29 | totalAuthorities := totalAuthorities()
30 | if totalAuthorities.HasValue {
31 | _ = currentSlot % totalAuthorities.Value
32 |
33 | // TODO: implement once Session module is added
34 | /*
35 | if T::DisabledValidators::is_disabled(authority_index as u32) {
36 | panic!(
37 | "Validator with index {:?} is disabled and should not be attempting to author blocks.",
38 | authority_index,
39 | );
40 | }
41 | */
42 | }
43 |
44 | return constants.DbWeight.ReadsWrites(2, 1)
45 | } else {
46 | return constants.DbWeight.Reads(1)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/frame/balances/dispatchables/deposit.go:
--------------------------------------------------------------------------------
1 | package dispatchables
2 |
3 | import (
4 | "math/big"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants"
8 | "github.com/LimeChain/gosemble/constants/balances"
9 | "github.com/LimeChain/gosemble/frame/balances/errors"
10 | "github.com/LimeChain/gosemble/frame/balances/events"
11 | "github.com/LimeChain/gosemble/frame/system"
12 | "github.com/LimeChain/gosemble/primitives/types"
13 | )
14 |
15 | // DepositIntoExisting deposits `value` into the free balance of an existing target account `who`.
16 | // If `value` is 0, it does nothing.
17 | func DepositIntoExisting(who types.Address32, value sc.U128) (types.Balance, types.DispatchError) {
18 | if value.ToBigInt().Cmp(constants.Zero) == 0 {
19 | return sc.NewU128FromUint64(uint64(0)), nil
20 | }
21 |
22 | result := tryMutateAccount(who, func(from *types.AccountData, isNew bool) sc.Result[sc.Encodable] {
23 | if isNew {
24 | return sc.Result[sc.Encodable]{
25 | HasError: true,
26 | Value: types.NewDispatchErrorModule(types.CustomModuleError{
27 | Index: balances.ModuleIndex,
28 | Error: sc.U32(errors.ErrorDeadAccount),
29 | Message: sc.NewOption[sc.Str](nil),
30 | }),
31 | }
32 | }
33 |
34 | sum := new(big.Int).Add(from.Free.ToBigInt(), value.ToBigInt())
35 |
36 | from.Free = sc.NewU128FromBigInt(sum)
37 |
38 | system.DepositEvent(events.NewEventDeposit(who.FixedSequence, value))
39 |
40 | return sc.Result[sc.Encodable]{}
41 | })
42 |
43 | if result.HasError {
44 | return types.Balance{}, result.Value.(types.DispatchError)
45 | }
46 |
47 | return value, nil
48 | }
49 |
--------------------------------------------------------------------------------
/frame/balances/dispatchables/types.go:
--------------------------------------------------------------------------------
1 | package dispatchables
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | "github.com/LimeChain/gosemble/constants"
9 | "github.com/LimeChain/gosemble/frame/balances/events"
10 | "github.com/LimeChain/gosemble/frame/system"
11 | "github.com/LimeChain/gosemble/primitives/hashing"
12 | "github.com/LimeChain/gosemble/primitives/storage"
13 | "github.com/LimeChain/gosemble/primitives/types"
14 | )
15 |
16 | type NegativeImbalance struct {
17 | types.Balance
18 | }
19 |
20 | func NewNegativeImbalance(balance types.Balance) NegativeImbalance {
21 | return NegativeImbalance{balance}
22 | }
23 |
24 | func (ni NegativeImbalance) Drop() {
25 | key := append(hashing.Twox128(constants.KeyBalances), hashing.Twox128(constants.KeyTotalIssuance)...)
26 |
27 | issuance := storage.GetDecode(key, sc.DecodeU128)
28 |
29 | issuanceBn := issuance.ToBigInt()
30 | sub := new(big.Int).Sub(issuanceBn, ni.ToBigInt())
31 |
32 | if sub.Cmp(issuanceBn) > 0 {
33 | sub = issuanceBn
34 | }
35 |
36 | storage.Set(key, sc.NewU128FromBigInt(sub).Bytes())
37 | }
38 |
39 | type PositiveImbalance struct {
40 | types.Balance
41 | }
42 |
43 | func NewPositiveImbalance(balance types.Balance) PositiveImbalance {
44 | return PositiveImbalance{balance}
45 | }
46 |
47 | func (pi PositiveImbalance) Drop() {
48 | key := append(hashing.Twox128(constants.KeyBalances), hashing.Twox128(constants.KeyTotalIssuance)...)
49 |
50 | issuance := storage.GetDecode(key, sc.DecodeU128)
51 |
52 | issuanceBn := issuance.ToBigInt()
53 | add := new(big.Int).Add(issuanceBn, pi.ToBigInt())
54 |
55 | if add.Cmp(issuanceBn) < 0 {
56 | add = issuanceBn
57 | }
58 |
59 | storage.Set(key, sc.NewU128FromBigInt(add).Bytes())
60 | }
61 |
62 | type DustCleanerValue struct {
63 | AccountId types.Address32
64 | NegativeImbalance NegativeImbalance
65 | }
66 |
67 | func (dcv DustCleanerValue) Encode(buffer *bytes.Buffer) {
68 | dcv.AccountId.Encode(buffer)
69 | dcv.NegativeImbalance.Encode(buffer)
70 | }
71 |
72 | func (dcv DustCleanerValue) Bytes() []byte {
73 | return sc.EncodedBytes(dcv)
74 | }
75 |
76 | func (dcv DustCleanerValue) Drop() {
77 | system.DepositEvent(events.NewEventDustLost(dcv.AccountId.FixedSequence, dcv.NegativeImbalance.Balance))
78 | dcv.NegativeImbalance.Drop()
79 | }
80 |
--------------------------------------------------------------------------------
/frame/balances/dispatchables/withdraw.go:
--------------------------------------------------------------------------------
1 | package dispatchables
2 |
3 | import (
4 | "math/big"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants"
8 | "github.com/LimeChain/gosemble/constants/balances"
9 | "github.com/LimeChain/gosemble/frame/balances/errors"
10 | "github.com/LimeChain/gosemble/frame/balances/events"
11 | "github.com/LimeChain/gosemble/frame/system"
12 | "github.com/LimeChain/gosemble/primitives/types"
13 | )
14 |
15 | // Withdraw withdraws `value` free balance from `who`, respecting existence requirements.
16 | // Does not do anything if value is 0.
17 | func Withdraw(who types.Address32, value sc.U128, reasons sc.U8, liveness types.ExistenceRequirement) (types.Balance, types.DispatchError) {
18 | if value.ToBigInt().Cmp(constants.Zero) == 0 {
19 | return sc.NewU128FromUint64(uint64(0)), nil
20 | }
21 |
22 | result := tryMutateAccount(who, func(account *types.AccountData, _ bool) sc.Result[sc.Encodable] {
23 | newFromAccountFree := new(big.Int).Sub(account.Free.ToBigInt(), value.ToBigInt())
24 |
25 | if newFromAccountFree.Cmp(constants.Zero) < 0 {
26 | return sc.Result[sc.Encodable]{
27 | HasError: true,
28 | Value: types.NewDispatchErrorModule(types.CustomModuleError{
29 | Index: balances.ModuleIndex,
30 | Error: sc.U32(errors.ErrorInsufficientBalance),
31 | Message: sc.NewOption[sc.Str](nil),
32 | }),
33 | }
34 | }
35 |
36 | existentialDeposit := balances.ExistentialDeposit
37 | sumNewFreeReserved := new(big.Int).Add(newFromAccountFree, account.Reserved.ToBigInt())
38 | sumFreeReserved := new(big.Int).Add(account.Free.ToBigInt(), account.Reserved.ToBigInt())
39 |
40 | wouldBeDead := sumNewFreeReserved.Cmp(existentialDeposit) < 0
41 | wouldKill := wouldBeDead && (sumFreeReserved.Cmp(existentialDeposit) >= 0)
42 |
43 | if !(liveness == types.ExistenceRequirementAllowDeath || !wouldKill) {
44 | return sc.Result[sc.Encodable]{
45 | HasError: true,
46 | Value: types.NewDispatchErrorModule(types.CustomModuleError{
47 | Index: balances.ModuleIndex,
48 | Error: sc.U32(errors.ErrorKeepAlive),
49 | Message: sc.NewOption[sc.Str](nil),
50 | }),
51 | }
52 | }
53 |
54 | err := ensureCanWithdraw(who, value.ToBigInt(), types.Reasons(reasons), newFromAccountFree)
55 | if err != nil {
56 | return sc.Result[sc.Encodable]{
57 | HasError: true,
58 | Value: err,
59 | }
60 | }
61 |
62 | account.Free = sc.NewU128FromBigInt(newFromAccountFree)
63 |
64 | system.DepositEvent(events.NewEventWithdraw(who.FixedSequence, value))
65 |
66 | return sc.Result[sc.Encodable]{
67 | HasError: false,
68 | Value: value,
69 | }
70 | })
71 |
72 | if result.HasError {
73 | return types.Balance{}, result.Value.(types.DispatchError)
74 | }
75 |
76 | return value, nil
77 | }
78 |
--------------------------------------------------------------------------------
/frame/balances/errors/errors.go:
--------------------------------------------------------------------------------
1 | package errors
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | // Balances module errors.
6 | const (
7 | ErrorVestingBalance sc.U8 = iota
8 | ErrorLiquidityRestrictions
9 | ErrorInsufficientBalance
10 | ErrorExistentialDeposit
11 | ErrorKeepAlive
12 | ErrorExistingVestingSchedule
13 | ErrorDeadAccount
14 | ErrorTooManyReserves
15 | )
16 |
--------------------------------------------------------------------------------
/frame/core/core.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/constants"
7 | "github.com/LimeChain/gosemble/execution/types"
8 | "github.com/LimeChain/gosemble/frame/executive"
9 | primitives "github.com/LimeChain/gosemble/primitives/types"
10 | "github.com/LimeChain/gosemble/utils"
11 | )
12 |
13 | type Core interface {
14 | Version(dataPtr int32, dataLen int32) int64
15 | ExecuteBlock(dataPtr int32, dataLen int32)
16 | InitializeBlock(dataPtr int32, dataLen int32)
17 | }
18 |
19 | // Version returns a pointer-size SCALE-encoded Runtime version.
20 | // [Specification](https://spec.polkadot.network/#defn-rt-core-version)
21 | func Version() int64 {
22 | buffer := &bytes.Buffer{}
23 | constants.RuntimeVersion.Encode(buffer)
24 |
25 | return utils.BytesToOffsetAndSize(buffer.Bytes())
26 | }
27 |
28 | // InitializeBlock starts the execution of a particular block.
29 | // It takes two arguments:
30 | // - dataPtr: Pointer to the data in the Wasm memory.
31 | // - dataLen: Length of the data.
32 | // which represent the SCALE-encoded header of the block.
33 | // [Specification](https://spec.polkadot.network/#sect-rte-core-initialize-block)
34 | func InitializeBlock(dataPtr int32, dataLen int32) {
35 | data := utils.ToWasmMemorySlice(dataPtr, dataLen)
36 | buffer := bytes.NewBuffer(data)
37 |
38 | header := primitives.DecodeHeader(buffer)
39 | executive.InitializeBlock(header)
40 | }
41 |
42 | // ExecuteBlock executes the provided block.
43 | // It takes two arguments:
44 | // - dataPtr: Pointer to the data in the Wasm memory.
45 | // - dataLen: Length of the data.
46 | // which represent the SCALE-encoded block.
47 | // [Specification](https://spec.polkadot.network/#sect-rte-core-execute-block)
48 | func ExecuteBlock(dataPtr int32, dataLen int32) {
49 | data := utils.ToWasmMemorySlice(dataPtr, dataLen)
50 | buffer := bytes.NewBuffer(data)
51 |
52 | block := types.DecodeBlock(buffer)
53 | executive.ExecuteBlock(block)
54 | }
55 |
--------------------------------------------------------------------------------
/frame/executive/hooks.go:
--------------------------------------------------------------------------------
1 | package executive
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/LimeChain/gosemble/frame/system"
7 | "github.com/LimeChain/gosemble/frame/timestamp"
8 | "github.com/LimeChain/gosemble/primitives/log"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | )
11 |
12 | func IdleAndFinalizeHook(blockNumber types.BlockNumber) {
13 | weight := system.StorageGetBlockWeight()
14 |
15 | maxWeight := system.DefaultBlockWeights().MaxBlock
16 | remainingWeight := maxWeight.SaturatingSub(weight.Total())
17 |
18 | if remainingWeight.AllGt(types.WeightZero()) {
19 | // TODO: call on_idle hook for each pallet
20 | usedWeight := onIdle(blockNumber, remainingWeight)
21 | system.RegisterExtraWeightUnchecked(usedWeight, types.NewDispatchClassMandatory())
22 | }
23 |
24 | // Each pallet (babe, grandpa) has its own on_finalize that has to be implemented once it is supported
25 | timestamp.OnFinalize()
26 | }
27 |
28 | func onRuntimeUpgrade() types.Weight {
29 | return types.WeightFromParts(200, 0)
30 | }
31 |
32 | func onIdle(n types.BlockNumber, remainingWeight types.Weight) types.Weight {
33 | log.Trace(fmt.Sprintf("on_idle %v, %v)", n, remainingWeight))
34 | return types.WeightFromParts(175, 0)
35 | }
36 |
--------------------------------------------------------------------------------
/frame/grandpa/grandpa.go:
--------------------------------------------------------------------------------
1 | package grandpa
2 |
3 | import (
4 | "fmt"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants"
8 | "github.com/LimeChain/gosemble/constants/grandpa"
9 | "github.com/LimeChain/gosemble/primitives/log"
10 | "github.com/LimeChain/gosemble/primitives/storage"
11 | "github.com/LimeChain/gosemble/primitives/types"
12 | "github.com/LimeChain/gosemble/utils"
13 | )
14 |
15 | // Authorities returns the current set of authorities, including their respective weights.
16 | // Returns a pointer-size of the SCALE-encoded set of authorities with their weights.
17 | // [Specification](https://spec.polkadot.network/chap-runtime-api#sect-rte-grandpa-auth)
18 | func Authorities() int64 {
19 | versionedAuthorityList := storage.GetDecode(constants.KeyGrandpaAuthorities, types.DecodeVersionedAuthorityList)
20 |
21 | authorities := versionedAuthorityList.AuthorityList
22 | if versionedAuthorityList.Version != grandpa.AuthorityVersion {
23 | log.Warn(fmt.Sprintf("unknown Grandpa authorities version: [%d]", versionedAuthorityList.Version))
24 | authorities = sc.Sequence[types.Authority]{}
25 | }
26 |
27 | return utils.BytesToOffsetAndSize(authorities.Bytes())
28 | }
29 |
--------------------------------------------------------------------------------
/frame/grandpa/module/module.go:
--------------------------------------------------------------------------------
1 | package module
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants/grandpa"
6 | "github.com/LimeChain/gosemble/constants/metadata"
7 | primitives "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | type GrandpaModule struct {
11 | }
12 |
13 | func NewGrandpaModule() GrandpaModule {
14 | return GrandpaModule{}
15 | }
16 |
17 | func (gm GrandpaModule) Functions() map[sc.U8]primitives.Call {
18 | return map[sc.U8]primitives.Call{}
19 | }
20 |
21 | func (gm GrandpaModule) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) {
22 | return sc.Empty{}, nil
23 | }
24 |
25 | func (gm GrandpaModule) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) {
26 | return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator())
27 | }
28 |
29 | func (gm GrandpaModule) Metadata() (sc.Sequence[primitives.MetadataType], primitives.MetadataModule) {
30 | return gm.metadataTypes(), primitives.MetadataModule{
31 | Name: "Grandpa",
32 | Storage: sc.Option[primitives.MetadataModuleStorage]{},
33 | Call: sc.NewOption[sc.Compact](nil),
34 | Event: sc.NewOption[sc.Compact](nil),
35 | Constants: sc.Sequence[primitives.MetadataModuleConstant]{},
36 | Error: sc.NewOption[sc.Compact](nil),
37 | Index: grandpa.ModuleIndex,
38 | }
39 | }
40 |
41 | func (gm GrandpaModule) metadataTypes() sc.Sequence[primitives.MetadataType] {
42 | return sc.Sequence[primitives.MetadataType]{
43 | primitives.NewMetadataTypeWithParams(metadata.GrandpaCalls, "Grandpa calls", sc.Sequence[sc.Str]{"pallet_grandpa", "pallet", "Call"}, primitives.NewMetadataTypeDefinitionVariant(
44 | // TODO: types
45 | sc.Sequence[primitives.MetadataDefinitionVariant]{}),
46 | sc.Sequence[primitives.MetadataTypeParameter]{
47 | primitives.NewMetadataEmptyTypeParameter("T"),
48 | primitives.NewMetadataEmptyTypeParameter("I"),
49 | }),
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/frame/offchain_worker/offchain_worker.go:
--------------------------------------------------------------------------------
1 | package offchain_worker
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/frame/system"
8 | "github.com/LimeChain/gosemble/primitives/hashing"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | "github.com/LimeChain/gosemble/utils"
11 | )
12 |
13 | // OffchainWorker starts an off-chain task for an imported block.
14 | // It takes two arguments:
15 | // - dataPtr: Pointer to the data in the Wasm memory.
16 | // - dataLen: Length of the data.
17 | // which represent the SCALE-encoded header of the block.
18 | // [Specification](https://spec.polkadot.network/chap-runtime-api#id-offchainworkerapi_offchain_worker)
19 | func OffchainWorker(dataPtr int32, dataLen int32) {
20 | b := utils.ToWasmMemorySlice(dataPtr, dataLen)
21 | buffer := bytes.NewBuffer(b)
22 |
23 | header := types.DecodeHeader(buffer)
24 |
25 | system.Initialize(header.Number, header.ParentHash, header.Digest)
26 |
27 | hash := hashing.Blake256(header.Bytes())
28 |
29 | system.StorageSetBlockHash(header.Number, types.NewBlake2bHash(sc.BytesToSequenceU8(hash)...))
30 |
31 | // TODO:
32 | /*
33 | >::offchain_worker(*header.number(),)
34 | */
35 | }
36 |
--------------------------------------------------------------------------------
/frame/session_keys/session_keys.go:
--------------------------------------------------------------------------------
1 | package session_keys
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants/aura"
8 | "github.com/LimeChain/gosemble/constants/grandpa"
9 | "github.com/LimeChain/gosemble/primitives/crypto"
10 | "github.com/LimeChain/gosemble/primitives/types"
11 | "github.com/LimeChain/gosemble/utils"
12 | )
13 |
14 | // GenerateSessionKeys generates a set of session keys with an optional seed.
15 | // The keys should be stored within the keystore exposed by the Host Api.
16 | // It takes two arguments:
17 | // - dataPtr: Pointer to the data in the Wasm memory.
18 | // - dataLen: Length of the data.
19 | // which represent the SCALE-encoded optional seed.
20 | // Returns a pointer-size of the SCALE-encoded set of keys.
21 | // [Specification](https://spec.polkadot.network/chap-runtime-api#id-sessionkeys_generate_session_keys)
22 | func GenerateSessionKeys(dataPtr int32, dataLen int32) int64 {
23 | b := utils.ToWasmMemorySlice(dataPtr, dataLen)
24 | buffer := bytes.NewBuffer(b)
25 |
26 | seed := sc.DecodeOptionWith(buffer, sc.DecodeSequence[sc.U8])
27 |
28 | auraPubKey := crypto.ExtCryptoSr25519GenerateVersion1(aura.KeyTypeId[:], seed.Bytes())
29 | grandpaPubKey := crypto.ExtCryptoEd25519GenerateVersion1(grandpa.KeyTypeId[:], seed.Bytes())
30 |
31 | res := sc.BytesToSequenceU8(append(auraPubKey, grandpaPubKey...))
32 |
33 | return utils.BytesToOffsetAndSize(res.Bytes())
34 | }
35 |
36 | // DecodeSessionKeys decodes the given session keys.
37 | // It takes two arguments:
38 | // - dataPtr: Pointer to the data in the Wasm memory.
39 | // - dataLen: Length of the data.
40 | // which represent the SCALE-encoded keys.
41 | // Returns a pointer-size of the SCALE-encoded set of raw keys and their respective key type.
42 | // [Specification](https://spec.polkadot.network/chap-runtime-api#id-sessionkeys_decode_session_keys)
43 | func DecodeSessionKeys(dataPtr int32, dataLen int32) int64 {
44 | b := utils.ToWasmMemorySlice(dataPtr, dataLen)
45 | buffer := bytes.NewBuffer(b)
46 | sequence := sc.DecodeSequenceWith(buffer, sc.DecodeU8)
47 |
48 | buffer = bytes.NewBuffer(sc.SequenceU8ToBytes(sequence))
49 | sessionKeys := sc.Sequence[types.SessionKey]{
50 | types.NewSessionKey(sc.FixedSequenceU8ToBytes(types.DecodePublicKey(buffer)), aura.KeyTypeId),
51 | types.NewSessionKey(sc.FixedSequenceU8ToBytes(types.DecodePublicKey(buffer)), grandpa.KeyTypeId),
52 | }
53 |
54 | result := sc.NewOption[sc.Sequence[types.SessionKey]](sessionKeys)
55 | return utils.BytesToOffsetAndSize(result.Bytes())
56 | }
57 |
--------------------------------------------------------------------------------
/frame/support/storage_value.go:
--------------------------------------------------------------------------------
1 | package support
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/hashing"
8 | "github.com/LimeChain/gosemble/primitives/storage"
9 | )
10 |
11 | type StorageValue[T sc.Encodable] struct {
12 | prefix []byte
13 | name []byte
14 | decodeFunc func(buffer *bytes.Buffer) T
15 | }
16 |
17 | func NewStorageValue[T sc.Encodable](prefix []byte, name []byte, decodeFunc func(buffer *bytes.Buffer) T) *StorageValue[T] {
18 | return &StorageValue[T]{
19 | prefix,
20 | name,
21 | decodeFunc,
22 | }
23 | }
24 |
25 | func (sv StorageValue[T]) Get() T {
26 | prefixHash := hashing.Twox128(sv.prefix)
27 | nameHash := hashing.Twox128(sv.name)
28 |
29 | return storage.GetDecode(append(prefixHash, nameHash...), sv.decodeFunc)
30 | }
31 |
32 | func (sv StorageValue[T]) Exists() bool {
33 | prefixHash := hashing.Twox128(sv.prefix)
34 | nameHash := hashing.Twox128(sv.name)
35 |
36 | exists := storage.Exists(append(prefixHash, nameHash...))
37 |
38 | return exists != 0
39 | }
40 |
41 | func (sv StorageValue[T]) Put(value T) {
42 | prefixHash := hashing.Twox128(sv.prefix)
43 | nameHash := hashing.Twox128(sv.name)
44 |
45 | storage.Set(append(prefixHash, nameHash...), value.Bytes())
46 | }
47 |
48 | func (sv StorageValue[T]) Take() []byte {
49 | prefixHash := hashing.Twox128(sv.prefix)
50 | nameHash := hashing.Twox128(sv.name)
51 |
52 | return storage.TakeBytes(append(prefixHash, nameHash...))
53 | }
54 |
55 | func (sv StorageValue[T]) TakeExact() T {
56 | prefixHash := hashing.Twox128(sv.prefix)
57 | nameHash := hashing.Twox128(sv.name)
58 |
59 | return storage.TakeDecode(append(prefixHash, nameHash...), sv.decodeFunc)
60 | }
61 |
--------------------------------------------------------------------------------
/frame/system/event.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/primitives/types"
6 | )
7 |
8 | // DepositEvent deposits an event into block's event record.
9 | func DepositEvent(event types.Event) {
10 | depositEventIndexed([]types.H256{}, event)
11 | }
12 |
13 | // depositEventIndexed Deposits an event into this block's event record adding this event
14 | // to the corresponding topic indexes.
15 | //
16 | // This will update storage entries that correspond to the specified topics.
17 | // It is expected that light-clients could subscribe to this topics.
18 | //
19 | // NOTE: Events not registered at the genesis block and quietly omitted.
20 | func depositEventIndexed(topics []types.H256, event types.Event) {
21 | blockNumber := StorageGetBlockNumber()
22 | if blockNumber == 0 {
23 | return
24 | }
25 |
26 | eventRecord := types.EventRecord{
27 | Phase: StorageExecutionPhase(),
28 | Event: event,
29 | Topics: topics,
30 | }
31 |
32 | oldEventCount := storageEventCount()
33 | newEventCount := oldEventCount + 1 // checked_add
34 | if newEventCount < oldEventCount {
35 | return
36 | }
37 |
38 | storageSetEventCount(newEventCount)
39 |
40 | storageAppendEvent(eventRecord)
41 |
42 | topicValue := sc.NewVaryingData(blockNumber, oldEventCount)
43 | for _, topic := range topics {
44 | storageAppendTopic(topic, topicValue)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/frame/system/events.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants/system"
8 | "github.com/LimeChain/gosemble/primitives/log"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | )
11 |
12 | // System module events.
13 | const (
14 | EventExtrinsicSuccess sc.U8 = iota
15 | EventExtrinsicFailed
16 | EventCodeUpdated
17 | EventNewAccount
18 | EventKilledAccount
19 | EventRemarked
20 | )
21 |
22 | func NewEventExtrinsicSuccess(dispatchInfo types.DispatchInfo) types.Event {
23 | return types.NewEvent(system.ModuleIndex, EventExtrinsicSuccess, dispatchInfo)
24 | }
25 |
26 | func NewEventExtrinsicFailed(dispatchError types.DispatchError, dispatchInfo types.DispatchInfo) types.Event {
27 | return types.NewEvent(system.ModuleIndex, EventExtrinsicFailed, dispatchError, dispatchInfo)
28 | }
29 |
30 | func NewEventCodeUpdated() types.Event {
31 | return types.NewEvent(system.ModuleIndex, EventCodeUpdated)
32 | }
33 |
34 | func NewEventNewAccount(account types.PublicKey) types.Event {
35 | return types.NewEvent(system.ModuleIndex, EventNewAccount, account)
36 | }
37 |
38 | func NewEventKilledAccount(account types.PublicKey) types.Event {
39 | return types.NewEvent(system.ModuleIndex, EventKilledAccount, account)
40 | }
41 |
42 | func NewEventRemarked(sender types.PublicKey, hash types.H256) types.Event {
43 | return types.NewEvent(system.ModuleIndex, EventRemarked, sender, hash)
44 | }
45 |
46 | func DecodeEvent(buffer *bytes.Buffer) types.Event {
47 | moduleIndex := sc.DecodeU8(buffer)
48 | if moduleIndex != system.ModuleIndex {
49 | log.Critical("invalid system.Event")
50 | }
51 |
52 | b := sc.DecodeU8(buffer)
53 |
54 | switch b {
55 | case EventExtrinsicSuccess:
56 | dispatchInfo := types.DecodeDispatchInfo(buffer)
57 | return NewEventExtrinsicSuccess(dispatchInfo)
58 | case EventExtrinsicFailed:
59 | dispatchErr := types.DecodeDispatchError(buffer)
60 | dispatchInfo := types.DecodeDispatchInfo(buffer)
61 | return NewEventExtrinsicFailed(dispatchErr, dispatchInfo)
62 | case EventCodeUpdated:
63 | return NewEventCodeUpdated()
64 | case EventNewAccount:
65 | account := types.DecodePublicKey(buffer)
66 | return NewEventNewAccount(account)
67 | case EventKilledAccount:
68 | account := types.DecodePublicKey(buffer)
69 | return NewEventKilledAccount(account)
70 | case EventRemarked:
71 | account := types.DecodePublicKey(buffer)
72 | hash := types.DecodeH256(buffer)
73 | return NewEventRemarked(account, hash)
74 | default:
75 | log.Critical("invalid system.Event type")
76 | }
77 |
78 | panic("unreachable")
79 | }
80 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_genesis.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/frame/system"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | type CheckGenesis struct{}
10 |
11 | func (_ CheckGenesis) AdditionalSigned() (ok primitives.H256, err primitives.TransactionValidityError) {
12 | ok = primitives.H256(system.StorageGetBlockHash(sc.U32(0)))
13 | return ok, err
14 | }
15 |
16 | func (_ CheckGenesis) Validate(_who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
17 | ok = primitives.DefaultValidTransaction()
18 | return ok, err
19 | }
20 |
21 | func (g CheckGenesis) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
22 | _, err = g.Validate(who, call, info, length)
23 | return ok, err
24 | }
25 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_mortality.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/frame/system"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | func (e CheckMortality) AdditionalSigned() (ok primitives.H256, err primitives.TransactionValidityError) {
10 | current := sc.U64(system.StorageGetBlockNumber()) // TODO: impl saturated_into::()
11 | n := sc.U32(primitives.Era(e).Birth(current)) // TODO: impl saturated_into::()
12 |
13 | if !system.StorageExistsBlockHash(n) {
14 | err = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionAncientBirthBlock())
15 | return ok, err
16 | } else {
17 | ok = primitives.H256(system.StorageGetBlockHash(n))
18 | }
19 |
20 | return ok, err
21 | }
22 |
23 | // TODO: to be able to provide a custom implementation of the Validate function
24 | type CheckMortality primitives.Era
25 |
26 | func (e CheckMortality) Validate(_who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
27 | currentU64 := sc.U64(system.StorageGetBlockNumber()) // TODO: per module implementation
28 |
29 | validTill := primitives.Era(e).Death(currentU64)
30 |
31 | ok = primitives.DefaultValidTransaction()
32 | ok.Longevity = validTill.SaturatingSub(currentU64)
33 |
34 | return ok, err
35 | }
36 |
37 | func (e CheckMortality) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
38 | _, err = e.Validate(who, call, info, length)
39 | return ok, err
40 | }
41 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_non_zero_sender.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "reflect"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | primitives "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | var ZeroAddress = primitives.NewAddress32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
11 |
12 | type CheckNonZeroAddress primitives.Address32
13 |
14 | func (a CheckNonZeroAddress) AdditionalSigned() (ok sc.Empty, err primitives.TransactionValidityError) {
15 | ok = sc.Empty{}
16 | return ok, err
17 | }
18 |
19 | func (who CheckNonZeroAddress) Validate(_who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
20 | // TODO:
21 | // Not sure when this is possible.
22 | // Checks signed transactions but will fail
23 | // before this check if the address is all zeros.
24 | if !reflect.DeepEqual(who, ZeroAddress) {
25 | ok = primitives.DefaultValidTransaction()
26 | return ok, err
27 | }
28 |
29 | err = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadSigner())
30 |
31 | return ok, err
32 | }
33 |
34 | func (a CheckNonZeroAddress) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
35 | _, err = a.Validate(who, call, info, length)
36 | return ok, err
37 | }
38 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_nonce.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "math"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/frame/system"
8 | primitives "github.com/LimeChain/gosemble/primitives/types"
9 | )
10 |
11 | type CheckNonce sc.U32
12 |
13 | func (n CheckNonce) AdditionalSigned() (ok sc.Empty, err primitives.TransactionValidityError) {
14 | ok = sc.Empty{}
15 | return ok, err
16 | }
17 |
18 | func (n CheckNonce) Validate(who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
19 | // TODO: check if we can use just who
20 | account := system.StorageGetAccount((*who).FixedSequence)
21 |
22 | if sc.U32(n) < account.Nonce {
23 | err = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale())
24 | return ok, err
25 | }
26 |
27 | encoded := (*who).Bytes()
28 | encoded = append(encoded, sc.ToCompact(sc.U32(n)).Bytes()...)
29 | provides := sc.Sequence[primitives.TransactionTag]{sc.BytesToSequenceU8(encoded)}
30 |
31 | var requires sc.Sequence[primitives.TransactionTag]
32 | if account.Nonce < sc.U32(n) {
33 | encoded := (*who).Bytes()
34 | encoded = append(encoded, sc.ToCompact(sc.U32(n)-1).Bytes()...)
35 | requires = sc.Sequence[primitives.TransactionTag]{sc.BytesToSequenceU8(encoded)}
36 | } else {
37 | requires = sc.Sequence[primitives.TransactionTag]{}
38 | }
39 |
40 | ok = primitives.ValidTransaction{
41 | Priority: 0,
42 | Requires: requires,
43 | Provides: provides,
44 | Longevity: primitives.TransactionLongevity(math.MaxUint64),
45 | Propagate: true,
46 | }
47 |
48 | return ok, err
49 | }
50 |
51 | func (n CheckNonce) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
52 | account := system.StorageGetAccount(who.FixedSequence)
53 |
54 | if sc.U32(n) != account.Nonce {
55 | if sc.U32(n) < account.Nonce {
56 | err = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale())
57 | } else {
58 | err = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture())
59 | }
60 | return ok, err
61 | }
62 |
63 | account.Nonce += 1
64 | system.StorageSetAccount(who.FixedSequence, account)
65 |
66 | ok = primitives.Pre{}
67 | return ok, err
68 | }
69 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_spec_version.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | type CheckSpecVersion struct{}
10 |
11 | func (_ CheckSpecVersion) AdditionalSigned() (ok sc.U32, err primitives.TransactionValidityError) {
12 | return constants.RuntimeVersion.SpecVersion, err
13 | }
14 |
15 | func (_ CheckSpecVersion) Validate(_who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
16 | ok = primitives.DefaultValidTransaction()
17 | return ok, err
18 | }
19 |
20 | func (v CheckSpecVersion) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
21 | _, err = v.Validate(who, call, info, length)
22 | return ok, err
23 | }
24 |
--------------------------------------------------------------------------------
/frame/system/extensions/check_tx_version.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants"
6 | primitives "github.com/LimeChain/gosemble/primitives/types"
7 | )
8 |
9 | type CheckTxVersion struct{}
10 |
11 | func (_ CheckTxVersion) AdditionalSigned() (ok sc.U32, err primitives.TransactionValidityError) {
12 | return constants.RuntimeVersion.TransactionVersion, err
13 | }
14 |
15 | func (_ CheckTxVersion) Validate(_who *primitives.Address32, _call *primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (ok primitives.ValidTransaction, err primitives.TransactionValidityError) {
16 | ok = primitives.DefaultValidTransaction()
17 | return ok, err
18 | }
19 |
20 | func (v CheckTxVersion) PreDispatch(who *primitives.Address32, call *primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (ok primitives.Pre, err primitives.TransactionValidityError) {
21 | _, err = v.Validate(who, call, info, length)
22 | return ok, err
23 | }
24 |
--------------------------------------------------------------------------------
/frame/system/hooks.go:
--------------------------------------------------------------------------------
1 | package system
2 |
3 | import (
4 | "github.com/LimeChain/gosemble/primitives/types"
5 | )
6 |
7 | func onCreatedAccount(who types.Address32) {
8 | // hook on creating new account, currently not used in Substrate
9 | //T::OnNewAccount::on_new_account(&who);
10 | DepositEvent(NewEventNewAccount(who.FixedSequence))
11 | }
12 |
13 | func onKilledAccount(who types.Address32) {
14 | DepositEvent(NewEventKilledAccount(who.FixedSequence))
15 | }
16 |
--------------------------------------------------------------------------------
/frame/tagged_transaction_queue/tagged_transaction_queue.go:
--------------------------------------------------------------------------------
1 | package tagged_transaction_queue
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/execution/types"
7 | "github.com/LimeChain/gosemble/frame/executive"
8 | primitives "github.com/LimeChain/gosemble/primitives/types"
9 | "github.com/LimeChain/gosemble/utils"
10 | )
11 |
12 | type TaggedTransactionQueue interface {
13 | ValidateTransaction(dataPtr int32, dataLen int32) int64
14 | }
15 |
16 | // ValidateTransaction validates an extrinsic at a given block.
17 | // It takes two arguments:
18 | // - dataPtr: Pointer to the data in the Wasm memory.
19 | // - dataLen: Length of the data.
20 | // which represent the SCALE-encoded tx source, extrinsic and block hash.
21 | // Returns a pointer-size of the SCALE-encoded result whether the extrinsic is valid.
22 | // [Specification](https://spec.polkadot.network/#sect-rte-validate-transaction)
23 | func ValidateTransaction(dataPtr int32, dataLen int32) int64 {
24 | data := utils.ToWasmMemorySlice(dataPtr, dataLen)
25 | buffer := bytes.NewBuffer(data)
26 |
27 | txSource := primitives.DecodeTransactionSource(buffer)
28 | tx := types.DecodeUncheckedExtrinsic(buffer)
29 | blockHash := primitives.DecodeBlake2bHash(buffer)
30 |
31 | ok, err := executive.ValidateTransaction(txSource, tx, blockHash)
32 |
33 | var res primitives.TransactionValidityResult
34 | if err != nil {
35 | res = primitives.NewTransactionValidityResult(err)
36 | } else {
37 | res = primitives.NewTransactionValidityResult(ok)
38 | }
39 |
40 | return utils.BytesToOffsetAndSize(res.Bytes())
41 | }
42 |
--------------------------------------------------------------------------------
/frame/testable/dispatchables/test_call.go:
--------------------------------------------------------------------------------
1 | package dispatchables
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 |
8 | "github.com/LimeChain/gosemble/constants/testable"
9 | "github.com/LimeChain/gosemble/frame/support"
10 | "github.com/LimeChain/gosemble/primitives/storage"
11 | "github.com/LimeChain/gosemble/primitives/types"
12 | primitives "github.com/LimeChain/gosemble/primitives/types"
13 | )
14 |
15 | type TestCall struct {
16 | primitives.Callable
17 | }
18 |
19 | func NewTestCall(args sc.VaryingData) TestCall {
20 | call := TestCall{
21 | Callable: primitives.Callable{
22 | ModuleId: testable.ModuleIndex,
23 | FunctionId: testable.FunctionTestIndex,
24 | },
25 | }
26 |
27 | if len(args) != 0 {
28 | call.Arguments = args
29 | }
30 |
31 | return call
32 | }
33 |
34 | func (c TestCall) DecodeArgs(buffer *bytes.Buffer) primitives.Call {
35 | c.Arguments = sc.NewVaryingData(sc.DecodeSequence[sc.U8](buffer))
36 | return c
37 | }
38 |
39 | func (c TestCall) Encode(buffer *bytes.Buffer) {
40 | c.Callable.Encode(buffer)
41 | }
42 |
43 | func (c TestCall) Bytes() []byte {
44 | return c.Callable.Bytes()
45 | }
46 |
47 | func (c TestCall) ModuleIndex() sc.U8 {
48 | return c.Callable.ModuleIndex()
49 | }
50 |
51 | func (c TestCall) FunctionIndex() sc.U8 {
52 | return c.Callable.FunctionIndex()
53 | }
54 |
55 | func (c TestCall) Args() sc.VaryingData {
56 | return c.Callable.Args()
57 | }
58 |
59 | func (_ TestCall) BaseWeight(args ...any) types.Weight {
60 | return types.WeightFromParts(1_000_000, 0)
61 | }
62 |
63 | func (_ TestCall) IsInherent() bool {
64 | return false
65 | }
66 |
67 | func (_ TestCall) WeightInfo(baseWeight types.Weight) types.Weight {
68 | return types.WeightFromParts(baseWeight.RefTime, 0)
69 | }
70 |
71 | func (_ TestCall) ClassifyDispatch(baseWeight types.Weight) types.DispatchClass {
72 | return types.NewDispatchClassNormal()
73 | }
74 |
75 | func (_ TestCall) PaysFee(baseWeight types.Weight) types.Pays {
76 | return types.NewPaysYes()
77 | }
78 |
79 | func (_ TestCall) Dispatch(origin types.RuntimeOrigin, _ sc.VaryingData) types.DispatchResultWithPostInfo[types.PostDispatchInfo] {
80 | storage.Set([]byte("testvalue"), []byte{1})
81 |
82 | support.WithStorageLayer(func() (ok types.PostDispatchInfo, err types.DispatchError) {
83 | storage.Set([]byte("testvalue"), []byte{2})
84 | return ok, types.NewDispatchErrorOther("revert")
85 | })
86 |
87 | return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{Ok: types.PostDispatchInfo{}}
88 | }
89 |
--------------------------------------------------------------------------------
/frame/testable/module/module.go:
--------------------------------------------------------------------------------
1 | package module
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/constants/testable"
6 | "github.com/LimeChain/gosemble/frame/testable/dispatchables"
7 | primitives "github.com/LimeChain/gosemble/primitives/types"
8 | )
9 |
10 | type TestableModule struct {
11 | functions map[sc.U8]primitives.Call
12 | }
13 |
14 | func NewTestingModule() TestableModule {
15 | functions := make(map[sc.U8]primitives.Call)
16 | functions[testable.FunctionTestIndex] = dispatchables.NewTestCall(nil)
17 |
18 | return TestableModule{
19 | functions: functions,
20 | }
21 | }
22 |
23 | func (tm TestableModule) Functions() map[sc.U8]primitives.Call {
24 | return tm.functions
25 | }
26 |
27 | func (tm TestableModule) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) {
28 | return sc.Empty{}, nil
29 | }
30 |
31 | func (tm TestableModule) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) {
32 | return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator())
33 | }
34 |
35 | func (tm TestableModule) Metadata() (sc.Sequence[primitives.MetadataType], primitives.MetadataModule) {
36 | // TODO: types
37 | return sc.Sequence[primitives.MetadataType]{}, primitives.MetadataModule{
38 | Name: "Testable",
39 | Storage: sc.Option[primitives.MetadataModuleStorage]{},
40 | Call: sc.NewOption[sc.Compact](nil),
41 | Event: sc.NewOption[sc.Compact](nil),
42 | Constants: sc.Sequence[primitives.MetadataModuleConstant]{},
43 | Error: sc.NewOption[sc.Compact](nil),
44 | Index: testable.ModuleIndex,
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/frame/testable/testable.go:
--------------------------------------------------------------------------------
1 | package testable
2 |
--------------------------------------------------------------------------------
/frame/timestamp/hooks.go:
--------------------------------------------------------------------------------
1 | package timestamp
2 |
3 | import (
4 | "github.com/LimeChain/gosemble/constants"
5 | "github.com/LimeChain/gosemble/primitives/hashing"
6 | "github.com/LimeChain/gosemble/primitives/log"
7 | "github.com/LimeChain/gosemble/primitives/storage"
8 | )
9 |
10 | func OnFinalize() {
11 | timestampHash := hashing.Twox128(constants.KeyTimestamp)
12 | didUpdateHash := hashing.Twox128(constants.KeyDidUpdate)
13 |
14 | didUpdate := storage.Get(append(timestampHash, didUpdateHash...))
15 |
16 | if didUpdate.HasValue {
17 | storage.Clear(append(timestampHash, didUpdateHash...))
18 | } else {
19 | log.Critical("Timestamp must be updated once in the block")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/frame/timestamp/timestamp.go:
--------------------------------------------------------------------------------
1 | package timestamp
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants"
8 | timestampConstants "github.com/LimeChain/gosemble/constants/timestamp"
9 | "github.com/LimeChain/gosemble/execution/types"
10 | timestamp "github.com/LimeChain/gosemble/frame/timestamp/dispatchables"
11 | "github.com/LimeChain/gosemble/primitives/hashing"
12 | "github.com/LimeChain/gosemble/primitives/log"
13 | "github.com/LimeChain/gosemble/primitives/storage"
14 | primitives "github.com/LimeChain/gosemble/primitives/types"
15 | )
16 |
17 | func CreateInherent(inherent primitives.InherentData) []byte {
18 | inherentData := inherent.Data[timestampConstants.InherentIdentifier]
19 |
20 | if inherentData == nil {
21 | log.Critical("Timestamp inherent must be provided.")
22 | }
23 |
24 | buffer := &bytes.Buffer{}
25 | buffer.Write(sc.SequenceU8ToBytes(inherentData))
26 | ts := sc.DecodeU64(buffer)
27 | // TODO: err if not able to parse it.
28 | buffer.Reset()
29 |
30 | timestampHash := hashing.Twox128(constants.KeyTimestamp)
31 | nowHash := hashing.Twox128(constants.KeyNow)
32 |
33 | nextTimestamp := storage.GetDecode(append(timestampHash, nowHash...), sc.DecodeU64) + timestampConstants.MinimumPeriod
34 |
35 | if ts > nextTimestamp {
36 | nextTimestamp = ts
37 | }
38 |
39 | function := timestamp.NewSetCall(sc.NewVaryingData(sc.ToCompact(uint64(nextTimestamp))))
40 |
41 | extrinsic := types.UncheckedExtrinsic{
42 | Version: types.ExtrinsicFormatVersion,
43 | Function: function,
44 | }
45 |
46 | return extrinsic.Bytes()
47 | }
48 |
49 | func CheckInherent(args sc.VaryingData, inherent primitives.InherentData) error {
50 | compactTs := args[0].(sc.Compact)
51 | t := sc.U64(compactTs.ToBigInt().Uint64())
52 |
53 | inherentData := inherent.Data[timestampConstants.InherentIdentifier]
54 |
55 | if inherentData == nil {
56 | log.Critical("Timestamp inherent must be provided.")
57 | }
58 |
59 | buffer := &bytes.Buffer{}
60 | buffer.Write(sc.SequenceU8ToBytes(inherentData))
61 | ts := sc.DecodeU64(buffer)
62 | // TODO: err if not able to parse it.
63 | buffer.Reset()
64 |
65 | timestampHash := hashing.Twox128(constants.KeyTimestamp)
66 | nowHash := hashing.Twox128(constants.KeyNow)
67 | systemNow := storage.GetDecode(append(timestampHash, nowHash...), sc.DecodeU64)
68 |
69 | minimum := systemNow + timestampConstants.MinimumPeriod
70 | if t > ts+timestampConstants.MaxTimestampDriftMillis {
71 | return primitives.NewTimestampErrorTooFarInFuture()
72 | } else if t < minimum {
73 | return primitives.NewTimestampErrorTooEarly()
74 | }
75 |
76 | return nil
77 | }
78 |
--------------------------------------------------------------------------------
/frame/transaction_payment/events.go:
--------------------------------------------------------------------------------
1 | package transaction_payment
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants/transaction_payment"
8 | "github.com/LimeChain/gosemble/primitives/log"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | )
11 |
12 | // TransactionPayment module events.
13 | const (
14 | EventTransactionFeePaid sc.U8 = iota
15 | )
16 |
17 | func NewEventTransactionFeePaid(account types.PublicKey, actualFee types.Balance, tip types.Balance) types.Event {
18 | return types.NewEvent(transaction_payment.ModuleIndex, EventTransactionFeePaid, account, actualFee, tip)
19 | }
20 |
21 | func DecodeEvent(buffer *bytes.Buffer) types.Event {
22 | module := sc.DecodeU8(buffer)
23 | if module != transaction_payment.ModuleIndex {
24 | log.Critical("invalid transaction_payment.Event module")
25 | }
26 |
27 | b := sc.DecodeU8(buffer)
28 |
29 | switch b {
30 | case EventTransactionFeePaid:
31 | account := types.DecodePublicKey(buffer)
32 | actualFee := sc.DecodeU128(buffer)
33 | tip := sc.DecodeU128(buffer)
34 | return NewEventTransactionFeePaid(account, actualFee, tip)
35 | default:
36 | log.Critical("invalid transaction_payment.Event type")
37 | }
38 |
39 | panic("unreachable")
40 | }
41 |
--------------------------------------------------------------------------------
/primitives/crypto/crypto.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package crypto
4 |
5 | import (
6 | "github.com/LimeChain/gosemble/env"
7 | "github.com/LimeChain/gosemble/utils"
8 | )
9 |
10 | func ExtCryptoEd25519GenerateVersion1(keyTypeId []byte, seed []byte) []byte {
11 | r := env.ExtCryptoEd25519GenerateVersion1(utils.Offset32(keyTypeId), utils.BytesToOffsetAndSize(seed))
12 | return utils.ToWasmMemorySlice(r, 32)
13 | }
14 |
15 | func ExtCryptoEd25519VerifyVersion1(signature []byte, message []byte, pubKey []byte) bool {
16 | return env.ExtCryptoEd25519VerifyVersion1(
17 | argsSigMsgPubKeyAsWasmMemory(signature, message, pubKey),
18 | ) == 1
19 | }
20 |
21 | func ExtCryptoSr25519GenerateVersion1(keyTypeId []byte, seed []byte) []byte {
22 | r := env.ExtCryptoSr25519GenerateVersion1(utils.Offset32(keyTypeId), utils.BytesToOffsetAndSize(seed))
23 | return utils.ToWasmMemorySlice(r, 32)
24 | }
25 |
26 | func ExtCryptoSr25519VerifyVersion2(signature []byte, message []byte, pubKey []byte) bool {
27 | return env.ExtCryptoSr25519VerifyVersion2(
28 | argsSigMsgPubKeyAsWasmMemory(signature, message, pubKey),
29 | ) == 1
30 | }
31 |
32 | func ExtCryptoStartBatchVerify() {
33 | env.ExtCryptoStartBatchVerifyVersion1()
34 | }
35 |
36 | func ExtCryptoFinishBatchVerify() int32 {
37 | return env.ExtCryptoFinishBatchVerifyVersion1()
38 | }
39 |
40 | func argsSigMsgPubKeyAsWasmMemory(signature []byte, message []byte, pubKey []byte) (sigOffset int32, msgOffsetSize int64, pubKeyOffset int32) {
41 | sigOffsetSize := utils.BytesToOffsetAndSize(signature)
42 | sigOffset, _ = utils.Int64ToOffsetAndSize(sigOffsetSize) // signature: 64-byte
43 |
44 | msgOffsetSize = utils.BytesToOffsetAndSize(message)
45 |
46 | pubKeyOffsetSize := utils.BytesToOffsetAndSize(pubKey)
47 | pubKeyOffset, _ = utils.Int64ToOffsetAndSize(pubKeyOffsetSize) // public key: 256-bit
48 |
49 | return sigOffset, msgOffsetSize, pubKeyOffset
50 | }
51 |
--------------------------------------------------------------------------------
/primitives/crypto/crypto_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package crypto
4 |
5 | import (
6 | "crypto/ed25519"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | func ExtCryptoEd25519GenerateVersion1(keyTypeId []byte, seed []byte) []byte {
12 | panic("not implemented")
13 | }
14 |
15 | func ExtCryptoEd25519VerifyVersion1(signature []byte, message []byte, pubKey []byte) sc.Bool {
16 | return sc.Bool(ed25519.Verify(pubKey, message, signature))
17 | }
18 |
19 | func ExtCryptoSr25519GenerateVersion1(keyTypeId []byte, seed []byte) []byte {
20 | panic("not implemented")
21 | }
22 |
23 | func ExtCryptoSr25519VerifyVersion2(signature []byte, message []byte, pubKey []byte) sc.Bool {
24 | panic("not implemented")
25 | }
26 |
27 | func ExtCryptoStartBatchVerify() {
28 | panic("not implemented")
29 | }
30 |
31 | func ExtCryptoFinishBatchVerify() int32 {
32 | panic("not implemented")
33 | }
34 |
--------------------------------------------------------------------------------
/primitives/hashing/hashing.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package hashing
4 |
5 | import (
6 | "github.com/LimeChain/gosemble/env"
7 | "github.com/LimeChain/gosemble/utils"
8 | )
9 |
10 | func Twox128(value []byte) []byte {
11 | keyOffsetSize := utils.BytesToOffsetAndSize(value)
12 | r := env.ExtHashingTwox128Version1(keyOffsetSize)
13 | return utils.ToWasmMemorySlice(r, 16)
14 | }
15 |
16 | func Twox64(value []byte) []byte {
17 | keyOffsetSize := utils.BytesToOffsetAndSize(value)
18 | r := env.ExtHashingTwox64Version1(keyOffsetSize)
19 | return utils.ToWasmMemorySlice(r, 8)
20 | }
21 |
22 | func Blake128(value []byte) []byte {
23 | keyOffsetSize := utils.BytesToOffsetAndSize(value)
24 | r := env.ExtHashingBlake2128Version1(keyOffsetSize)
25 | return utils.ToWasmMemorySlice(r, 16)
26 | }
27 |
28 | func Blake256(value []byte) []byte {
29 | keyOffsetSize := utils.BytesToOffsetAndSize(value)
30 | r := env.ExtHashingBlake2256Version1(keyOffsetSize)
31 | return utils.ToWasmMemorySlice(r, 32)
32 | }
33 |
--------------------------------------------------------------------------------
/primitives/hashing/hashing_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package hashing
4 |
5 | import (
6 | "github.com/ChainSafe/gossamer/lib/common"
7 | )
8 |
9 | func Twox128(value []byte) []byte {
10 | h, _ := common.Twox128Hash(value)
11 | return h[:]
12 | }
13 |
14 | func Twox64(value []byte) []byte {
15 | h, _ := common.Twox64(value)
16 | return h[:]
17 | }
18 |
19 | func Blake128(value []byte) []byte {
20 | h, _ := common.Blake2b128(value)
21 | return h[:]
22 | }
23 |
24 | func Blake256(value []byte) []byte {
25 | h, _ := common.Blake2bHash(value)
26 | return h[:]
27 | }
28 |
--------------------------------------------------------------------------------
/primitives/log/log.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package log
4 |
5 | import (
6 | "github.com/LimeChain/gosemble/env"
7 | "github.com/LimeChain/gosemble/utils"
8 | )
9 |
10 | const (
11 | CriticalLevel = iota
12 | WarnLevel
13 | InfoLevel
14 | DebugLevel
15 | TraceLevel
16 | )
17 |
18 | const target = "runtime"
19 |
20 | func Critical(message string) {
21 | log(CriticalLevel, []byte(target), []byte(message))
22 | panic(message)
23 | }
24 |
25 | func Warn(message string) {
26 | log(WarnLevel, []byte(target), []byte(message))
27 | }
28 |
29 | func Info(message string) {
30 | log(InfoLevel, []byte(target), []byte(message))
31 | }
32 |
33 | func Debug(message string) {
34 | log(DebugLevel, []byte(target), []byte(message))
35 | }
36 |
37 | func Trace(message string) {
38 | log(TraceLevel, []byte(target), []byte(message))
39 | }
40 |
41 | func log(level int32, target []byte, message []byte) {
42 | targetOffsetSize := utils.BytesToOffsetAndSize(target)
43 | messageOffsetSize := utils.BytesToOffsetAndSize(message)
44 | env.ExtLoggingLogVersion1(level, targetOffsetSize, messageOffsetSize)
45 | }
46 |
--------------------------------------------------------------------------------
/primitives/log/log_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package log
4 |
5 | import "fmt"
6 |
7 | const (
8 | CriticalLevel = iota
9 | WarnLevel
10 | InfoLevel
11 | DebugLevel
12 | TraceLevel
13 | )
14 | const target = "runtime"
15 |
16 | func Critical(message string) {
17 | log(CriticalLevel, []byte(target), []byte(message))
18 | panic(message)
19 | }
20 |
21 | func Warn(message string) {
22 | log(WarnLevel, []byte(target), []byte(message))
23 | }
24 |
25 | func Info(message string) {
26 | log(InfoLevel, []byte(target), []byte(message))
27 | }
28 |
29 | func Debug(message string) {
30 | log(DebugLevel, []byte(target), []byte(message))
31 | }
32 |
33 | func Trace(message string) {
34 | log(TraceLevel, []byte(target), []byte(message))
35 | }
36 |
37 | func log(level int32, target []byte, message []byte) {
38 | var levelStr string
39 | switch level {
40 | case CriticalLevel:
41 | levelStr = "CRITICAL"
42 | case WarnLevel:
43 | levelStr = "WARN"
44 | case InfoLevel:
45 | levelStr = "INFO"
46 | case DebugLevel:
47 | levelStr = "DEBUG"
48 | case TraceLevel:
49 | levelStr = "TRACE"
50 | }
51 |
52 | fmt.Println(levelStr, " target="+string(target), " message="+string(message))
53 | }
54 |
--------------------------------------------------------------------------------
/primitives/storage/storage_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package storage
4 |
5 | import (
6 | "bytes"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | func Append(key []byte, value []byte) {
12 | panic("not implemented")
13 | }
14 |
15 | func ChangesRoot(parent_hash int64) int64 {
16 | panic("not implemented")
17 | }
18 |
19 | func Clear(key []byte) {
20 | panic("not implemented")
21 | }
22 |
23 | func ClearPrefix(key []byte, limit []byte) {
24 | panic("not implemented")
25 | }
26 |
27 | func Exists(key []byte) int32 {
28 | panic("not implemented")
29 | }
30 |
31 | func Get(key []byte) sc.Option[sc.Sequence[sc.U8]] {
32 | panic("not implemented")
33 | }
34 |
35 | func GetDecode[T sc.Encodable](key []byte, decodeFunc func(buffer *bytes.Buffer) T) T {
36 | panic("not implemented")
37 | }
38 |
39 | func GetDecodeOnEmpty[T sc.Encodable](key []byte, decodeFunc func(buffer *bytes.Buffer) T, onEmpty T) T {
40 | panic("not implemented")
41 | }
42 |
43 | func NextKey(key int64) int64 {
44 | panic("not implemented")
45 | }
46 |
47 | func Read(key []byte, valueOut []byte, offset int32) sc.Option[sc.U32] {
48 | panic("not implemented")
49 | }
50 |
51 | func Root(key int32) []byte {
52 | panic("not implemented")
53 | }
54 |
55 | func Set(key []byte, value []byte) {
56 | panic("not implemented")
57 | }
58 |
59 | func TakeBytes(key []byte) []byte {
60 | panic("not implemented")
61 | }
62 |
63 | func TakeDecode[T sc.Encodable](key []byte, decodeFunc func(buffer *bytes.Buffer) T) T {
64 | panic("not implemented")
65 | }
66 |
67 | func StartTransaction() {
68 | panic("not implemented")
69 | }
70 |
71 | func RollbackTransaction() {
72 | panic("not implemented")
73 | }
74 |
75 | func CommitTransaction() {
76 | panic("not implemented")
77 | }
78 |
--------------------------------------------------------------------------------
/primitives/trie/trie.go:
--------------------------------------------------------------------------------
1 | //go:build !nonwasmenv
2 |
3 | package trie
4 |
5 | import (
6 | "github.com/LimeChain/gosemble/env"
7 | "github.com/LimeChain/gosemble/utils"
8 | )
9 |
10 | func Blake2256OrderedRoot(key []byte, version int32) []byte {
11 | keyOffsetSize := utils.BytesToOffsetAndSize(key)
12 | r := env.ExtTrieBlake2256OrderedRootVersion2(keyOffsetSize, version)
13 | return utils.ToWasmMemorySlice(r, 32)
14 | }
15 |
--------------------------------------------------------------------------------
/primitives/trie/trie_nonwasm.go:
--------------------------------------------------------------------------------
1 | //go:build nonwasmenv
2 |
3 | package trie
4 |
5 | import (
6 | "fmt"
7 | "math/big"
8 |
9 | "github.com/ChainSafe/gossamer/lib/trie"
10 | "github.com/ChainSafe/gossamer/pkg/scale"
11 | )
12 |
13 | func Blake2256OrderedRoot(inherentExt []byte, version int32) []byte {
14 | var exts [][]byte
15 | err := scale.Unmarshal(inherentExt, &exts)
16 | if err != nil {
17 | panic(err)
18 | }
19 |
20 | t := trie.NewEmptyTrie()
21 |
22 | for i, value := range exts {
23 | key, err := scale.Marshal(big.NewInt(int64(i)))
24 | if err != nil {
25 | panic(fmt.Sprintf("failed scale encoding value index %d: %s", i, err))
26 | }
27 |
28 | err = t.Put(key, value)
29 | if err != nil {
30 | panic(fmt.Sprintf("failed putting key 0x%x and value 0x%x into trie: %s",
31 | key, value, err))
32 | }
33 | }
34 |
35 | hash, err := t.Hash()
36 | if err != nil {
37 | panic(err)
38 | }
39 |
40 | return hash.ToBytes()
41 | }
42 |
--------------------------------------------------------------------------------
/primitives/types/account_data.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | )
9 |
10 | type Balance = sc.U128
11 |
12 | type AccountData struct {
13 | Free Balance
14 | Reserved Balance
15 | MiscFrozen Balance
16 | FeeFrozen Balance
17 | }
18 |
19 | func (ad AccountData) Encode(buffer *bytes.Buffer) {
20 | ad.Free.Encode(buffer)
21 | ad.Reserved.Encode(buffer)
22 | ad.MiscFrozen.Encode(buffer)
23 | ad.FeeFrozen.Encode(buffer)
24 | }
25 |
26 | func (ad AccountData) Bytes() []byte {
27 | return sc.EncodedBytes(ad)
28 | }
29 |
30 | func DecodeAccountData(buffer *bytes.Buffer) AccountData {
31 | return AccountData{
32 | Free: sc.DecodeU128(buffer),
33 | Reserved: sc.DecodeU128(buffer),
34 | MiscFrozen: sc.DecodeU128(buffer),
35 | FeeFrozen: sc.DecodeU128(buffer),
36 | }
37 | }
38 |
39 | func (ad AccountData) Total() *big.Int {
40 | return new(big.Int).Add(ad.Free.ToBigInt(), ad.Reserved.ToBigInt())
41 | }
42 |
--------------------------------------------------------------------------------
/primitives/types/account_info.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | )
9 |
10 | type RefCount = sc.U32
11 |
12 | type AccountInfo struct {
13 | Nonce AccountIndex
14 | Consumers RefCount
15 | Providers RefCount
16 | Sufficients RefCount
17 | Data AccountData
18 | }
19 |
20 | func (ai AccountInfo) Encode(buffer *bytes.Buffer) {
21 | ai.Nonce.Encode(buffer)
22 | ai.Consumers.Encode(buffer)
23 | ai.Providers.Encode(buffer)
24 | ai.Sufficients.Encode(buffer)
25 | ai.Data.Encode(buffer)
26 | }
27 |
28 | func (ai AccountInfo) Bytes() []byte {
29 | return sc.EncodedBytes(ai)
30 | }
31 |
32 | func DecodeAccountInfo(buffer *bytes.Buffer) AccountInfo {
33 | return AccountInfo{
34 | Nonce: sc.DecodeU32(buffer),
35 | Consumers: sc.DecodeU32(buffer),
36 | Providers: sc.DecodeU32(buffer),
37 | Sufficients: sc.DecodeU32(buffer),
38 | Data: DecodeAccountData(buffer),
39 | }
40 | }
41 |
42 | func (ai AccountInfo) Frozen(reasons Reasons) *big.Int {
43 | switch reasons {
44 | case ReasonsAll:
45 | if ai.Data.MiscFrozen.ToBigInt().Cmp(ai.Data.FeeFrozen.ToBigInt()) > 0 {
46 | return ai.Data.MiscFrozen.ToBigInt()
47 | }
48 | return ai.Data.FeeFrozen.ToBigInt()
49 | case ReasonsMisc:
50 | return big.NewInt(0).Set(ai.Data.MiscFrozen.ToBigInt())
51 | case ReasonsFee:
52 | return big.NewInt(0).Set(ai.Data.MiscFrozen.ToBigInt())
53 | }
54 |
55 | return big.NewInt(0)
56 | }
57 |
--------------------------------------------------------------------------------
/primitives/types/apply_extrinsic_result.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | // ApplyExtrinsicResult The result of applying of an extrinsic.
11 | //
12 | // This type is typically used in the context of `BlockBuilder` to signal that the extrinsic
13 | // in question cannot be included.
14 | //
15 | // A block containing extrinsics that have a negative inclusion outcome is invalid. A negative
16 | // result can only occur during the block production, where such extrinsics are detected and
17 | // removed from the block that is being created and the transaction pool.
18 | //
19 | // To rehash: every extrinsic in a valid block must return a positive `ApplyExtrinsicResult`.
20 | //
21 | // Examples of reasons preventing inclusion in a block:
22 | // - More block weight is required to process the extrinsic than is left in the block being built.
23 | // This doesn't necessarily mean that the extrinsic is invalid, since it can still be included in
24 | // the next block if it has enough spare weight available.
25 | // - The sender doesn't have enough funds to pay the transaction inclusion fee. Including such a
26 | // transaction in the block doesn't make sense.
27 | // - The extrinsic supplied a bad signature. This transaction won't become valid ever.
28 | type ApplyExtrinsicResult sc.VaryingData // = sc.Result[DispatchOutcome, TransactionValidityError]
29 |
30 | func NewApplyExtrinsicResult(value sc.Encodable) ApplyExtrinsicResult {
31 | // DispatchOutcome = 0 Outcome of dispatching the extrinsic.
32 | // TransactionValidityError = 1 Possible errors while checking the validity of a transaction.
33 | switch value.(type) {
34 | case DispatchOutcome, TransactionValidityError:
35 | return ApplyExtrinsicResult(sc.NewVaryingData(value))
36 | default:
37 | log.Critical("invalid ApplyExtrinsicResult type")
38 | }
39 |
40 | panic("unreachable")
41 | }
42 |
43 | func (r ApplyExtrinsicResult) Encode(buffer *bytes.Buffer) {
44 | switch r[0].(type) {
45 | case DispatchOutcome:
46 | sc.U8(0).Encode(buffer)
47 | case TransactionValidityError:
48 | sc.U8(1).Encode(buffer)
49 | default:
50 | log.Critical("invalid ApplyExtrinsicResult type")
51 | }
52 |
53 | r[0].Encode(buffer)
54 | }
55 |
56 | func DecodeApplyExtrinsicResult(buffer *bytes.Buffer) ApplyExtrinsicResult {
57 | b := sc.DecodeU8(buffer)
58 |
59 | switch b {
60 | case 0:
61 | value := DecodeDispatchOutcome(buffer)
62 | return NewApplyExtrinsicResult(value)
63 | case 1:
64 | value := DecodeTransactionValidityError(buffer)
65 | return NewApplyExtrinsicResult(value)
66 | default:
67 | log.Critical("invalid ApplyExtrinsicResult type")
68 | }
69 |
70 | panic("unreachable")
71 | }
72 |
73 | func (r ApplyExtrinsicResult) Bytes() []byte {
74 | return sc.EncodedBytes(r)
75 | }
76 |
--------------------------------------------------------------------------------
/primitives/types/apply_extrinsic_result_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func Test_EncodeApplyExtrinsicResult(t *testing.T) {
11 | var testExamples = []struct {
12 | label string
13 | input ApplyExtrinsicResult
14 | expectation []byte
15 | }{
16 | {
17 | label: "Encode ApplyExtrinsicResult(NewDispatchOutcome(None))",
18 | input: NewApplyExtrinsicResult(NewDispatchOutcome(nil)),
19 | expectation: []byte{0x00, 0x00},
20 | },
21 | {
22 | label: "Encode ApplyExtrinsicResult(NewDispatchOutcome(NewDispatchErrorBadOrigin))",
23 | input: NewApplyExtrinsicResult(NewDispatchOutcome(NewDispatchErrorBadOrigin())),
24 | expectation: []byte{0x00, 0x01, 0x02},
25 | },
26 | {
27 | label: "Encode ApplyExtrinsicResult(NewTransactionValidityError(NewInvalidTransactionCall))",
28 | input: NewApplyExtrinsicResult(NewTransactionValidityError(NewInvalidTransactionCall())),
29 | expectation: []byte{0x01, 0x00, 0x00},
30 | },
31 | }
32 |
33 | for _, testExample := range testExamples {
34 | t.Run(testExample.label, func(t *testing.T) {
35 | buffer := &bytes.Buffer{}
36 |
37 | testExample.input.Encode(buffer)
38 |
39 | assert.Equal(t, testExample.expectation, buffer.Bytes())
40 | })
41 | }
42 | }
43 |
44 | func Test_DecodeApplyExtrinsicResult(t *testing.T) {
45 | var testExamples = []struct {
46 | label string
47 | input []byte
48 | expectation ApplyExtrinsicResult
49 | }{
50 | {
51 | label: "Decode ApplyExtrinsicResult(NewDispatchOutcome(None))",
52 | expectation: NewApplyExtrinsicResult(NewDispatchOutcome(nil)),
53 | input: []byte{0x00, 0x00},
54 | },
55 | {
56 | label: "Decode ApplyExtrinsicResult(NewDispatchOutcome(NewDispatchErrorBadOrigin))",
57 | expectation: NewApplyExtrinsicResult(NewDispatchOutcome(NewDispatchErrorBadOrigin())),
58 | input: []byte{0x00, 0x01, 0x02},
59 | },
60 | {
61 | label: "Decode ApplyExtrinsicResult(NewTransactionValidityError(NewInvalidTransactionCall)",
62 | expectation: NewApplyExtrinsicResult(NewTransactionValidityError(NewInvalidTransactionCall())),
63 | input: []byte{0x01, 0x00, 0x00},
64 | },
65 | }
66 |
67 | for _, testExample := range testExamples {
68 | t.Run(testExample.label, func(t *testing.T) {
69 | buffer := &bytes.Buffer{}
70 | buffer.Write(testExample.input)
71 |
72 | result := DecodeApplyExtrinsicResult(buffer)
73 |
74 | assert.Equal(t, testExample.expectation, result)
75 | })
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/primitives/types/arithmetic_error.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | const (
11 | ArithmeticErrorUnderflow sc.U8 = iota
12 | ArithmeticErrorOverflow
13 | ArithmeticErrorDivisionByZero
14 | )
15 |
16 | type ArithmeticError = sc.VaryingData
17 |
18 | func NewArithmeticErrorUnderflow() ArithmeticError {
19 | return sc.NewVaryingData(ArithmeticErrorUnderflow)
20 | }
21 |
22 | func NewArithmeticErrorOverflow() ArithmeticError {
23 | return sc.NewVaryingData(ArithmeticErrorOverflow)
24 | }
25 |
26 | func NewArithmeticErrorDivisionByZero() ArithmeticError {
27 | return sc.NewVaryingData(ArithmeticErrorDivisionByZero)
28 | }
29 |
30 | func DecodeArithmeticError(buffer *bytes.Buffer) ArithmeticError {
31 | b := sc.DecodeU8(buffer)
32 |
33 | switch b {
34 | case ArithmeticErrorUnderflow:
35 | return NewArithmeticErrorUnderflow()
36 | case ArithmeticErrorOverflow:
37 | return NewArithmeticErrorOverflow()
38 | case ArithmeticErrorDivisionByZero:
39 | return NewArithmeticErrorDivisionByZero()
40 | default:
41 | log.Critical("invalid ArithmeticError type")
42 | }
43 |
44 | panic("unreachable")
45 | }
46 |
--------------------------------------------------------------------------------
/primitives/types/authority.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | sc "github.com/LimeChain/goscale"
6 | )
7 |
8 | type Authority struct {
9 | Id PublicKey
10 | Weight sc.U64
11 | }
12 |
13 | func (a Authority) Encode(buffer *bytes.Buffer) {
14 | a.Id.Encode(buffer)
15 | a.Weight.Encode(buffer)
16 | }
17 |
18 | func DecodeAuthority(buffer *bytes.Buffer) Authority {
19 | return Authority{
20 | Id: DecodePublicKey(buffer),
21 | Weight: sc.DecodeU64(buffer),
22 | }
23 | }
24 |
25 | func (a Authority) Bytes() []byte {
26 | return sc.EncodedBytes(a)
27 | }
28 |
--------------------------------------------------------------------------------
/primitives/types/balance_status.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/primitives/log"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | const (
12 | BalanceStatusFree sc.U8 = iota
13 | BalanceStatusReserved
14 | )
15 |
16 | type BalanceStatus = sc.U8
17 |
18 | func DecodeBalanceStatus(buffer *bytes.Buffer) sc.U8 {
19 | value := sc.DecodeU8(buffer)
20 | switch value {
21 | case BalanceStatusFree, BalanceStatusReserved:
22 | return value
23 | default:
24 | log.Critical("invalid balance status type")
25 | }
26 |
27 | panic("unreachable")
28 | }
29 |
--------------------------------------------------------------------------------
/primitives/types/call.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type Call interface {
10 | sc.Encodable
11 |
12 | ModuleIndex() sc.U8
13 | FunctionIndex() sc.U8
14 | Args() sc.VaryingData
15 | Dispatch(origin RuntimeOrigin, args sc.VaryingData) DispatchResultWithPostInfo[PostDispatchInfo]
16 | IsInherent() bool
17 | BaseWeight(...any) Weight
18 | ClassifyDispatch(baseWeight Weight) DispatchClass
19 | PaysFee(baseWeight Weight) Pays
20 | WeightInfo(baseWeight Weight) Weight
21 | DecodeArgs(buffer *bytes.Buffer) Call
22 | }
23 |
24 | type Callable struct {
25 | ModuleId sc.U8
26 | FunctionId sc.U8
27 | Arguments sc.VaryingData
28 | }
29 |
30 | func (c Callable) Encode(buffer *bytes.Buffer) {
31 | c.ModuleId.Encode(buffer)
32 | c.FunctionId.Encode(buffer)
33 | c.Arguments.Encode(buffer)
34 | }
35 |
36 | func (c Callable) Bytes() []byte {
37 | return sc.EncodedBytes(c)
38 | }
39 |
40 | func (c Callable) ModuleIndex() sc.U8 {
41 | return c.ModuleId
42 | }
43 |
44 | func (c Callable) FunctionIndex() sc.U8 {
45 | return c.FunctionId
46 | }
47 |
48 | func (c Callable) Args() sc.VaryingData {
49 | return c.Arguments
50 | }
51 |
--------------------------------------------------------------------------------
/primitives/types/call_index_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | // TODO:
4 | //var call = Call{
5 | // CallIndex: CallIndex{
6 | // ModuleIndex: 0,
7 | // FunctionIndex: 0,
8 | // },
9 | // Args: []goscale.Encodable{},
10 | //}
11 | //
12 | //func Test_NewCall(t *testing.T) {
13 | // var testExamples = []struct {
14 | // label string
15 | // input Call
16 | // expectation Call
17 | // }{
18 | // {
19 | // label: "Encode(Call(System.remark(0xab, 0xcd)))",
20 | // input: call,
21 | // expectation: Call{
22 | // CallIndex: CallIndex{
23 | // ModuleIndex: 0,
24 | // FunctionIndex: 0,
25 | // },
26 | // Args: []goscale.Encodable{},
27 | // },
28 | // },
29 | // }
30 | //
31 | // for _, testExample := range testExamples {
32 | // t.Run(testExample.label, func(t *testing.T) {
33 | // assert.Equal(t, testExample.input.CallIndex.ModuleIndex, testExample.expectation.CallIndex.ModuleIndex)
34 | // assert.Equal(t, testExample.input.CallIndex.FunctionIndex, testExample.expectation.CallIndex.FunctionIndex)
35 | // assert.Equal(t, testExample.input.Args, testExample.expectation.Args)
36 | // })
37 | // }
38 | //}
39 | //
40 | //func Test_EncodeCall(t *testing.T) {
41 | // var testExamples = []struct {
42 | // label string
43 | // input Call
44 | // expectation []byte
45 | // }{
46 | // {
47 | // label: "Encode(Call(System.remark(0xab, 0xcd)))",
48 | // input: call,
49 | // expectation: []byte{0x0, 0x0},
50 | // },
51 | // }
52 | //
53 | // for _, testExample := range testExamples {
54 | // t.Run(testExample.label, func(t *testing.T) {
55 | // buffer := &bytes.Buffer{}
56 | //
57 | // testExample.input.Encode(buffer)
58 | //
59 | // assert.Equal(t, testExample.expectation, buffer.Bytes())
60 | // })
61 | // }
62 | //}
63 | //
64 | //func Test_DecodeCall(t *testing.T) {
65 | // var testExamples = []struct {
66 | // label string
67 | // input []byte
68 | // expectation Call
69 | // }{
70 | // {
71 | // label: "Decode(0x0, 0x0, 0x8, 0xab, 0xcd)",
72 | // input: []byte{0x0, 0x0},
73 | // expectation: call,
74 | // },
75 | // }
76 | //
77 | // for _, testExample := range testExamples {
78 | // t.Run(testExample.label, func(t *testing.T) {
79 | // buffer := &bytes.Buffer{}
80 | // buffer.Write(testExample.input)
81 | //
82 | // result := DecodeCall(buffer)
83 | //
84 | // assert.Equal(t, testExample.expectation, result)
85 | // })
86 | // }
87 | //}
88 |
--------------------------------------------------------------------------------
/primitives/types/checked_extrinsic.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type AccountIdExtra struct {
10 | Address32
11 | SignedExtra
12 | }
13 |
14 | func (ae AccountIdExtra) Encode(buffer *bytes.Buffer) {
15 | ae.Address32.Encode(buffer)
16 | ae.SignedExtra.Encode(buffer)
17 | }
18 |
19 | func DecodeAccountIdExtra(buffer *bytes.Buffer) AccountIdExtra {
20 | ae := AccountIdExtra{}
21 | ae.Address32 = DecodeAddress32(buffer)
22 | ae.SignedExtra = DecodeExtra(buffer)
23 | return ae
24 | }
25 |
26 | func (ae AccountIdExtra) Bytes() []byte {
27 | return sc.EncodedBytes(ae)
28 | }
29 |
--------------------------------------------------------------------------------
/primitives/types/constant_multiplier.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "math/big"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type ConstantMultiplier struct {
10 | Multiplier Balance
11 | }
12 |
13 | func NewConstantMultiplier(multiplier Balance) ConstantMultiplier {
14 | return ConstantMultiplier{
15 | Multiplier: multiplier,
16 | }
17 | }
18 |
19 | func (cm ConstantMultiplier) WeightToFee(weight Weight) Balance {
20 | bnRefTime := new(big.Int).SetUint64(uint64(weight.RefTime))
21 |
22 | res := new(big.Int).Mul(bnRefTime, cm.Multiplier.ToBigInt())
23 | return sc.NewU128FromBigInt(res)
24 | }
25 |
--------------------------------------------------------------------------------
/primitives/types/dec_ref_status.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | type DecRefStatus = sc.U8
6 |
7 | const (
8 | DecRefStatusReaped sc.U8 = iota
9 | DecRefStatusExists
10 | )
11 |
--------------------------------------------------------------------------------
/primitives/types/digest.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | const (
10 | DigestTypeConsensusMessage = 4
11 | DigestTypeSeal = 5
12 | DigestTypePreRuntime = 6
13 | DigestTypeRuntimeEnvironmentUpgraded = 8
14 | )
15 |
16 | type Digest = sc.Dictionary[sc.U8, sc.FixedSequence[DigestItem]]
17 |
18 | func DecodeDigest(buffer *bytes.Buffer) Digest {
19 | compactSize := sc.DecodeCompact(buffer)
20 | size := int(compactSize.ToBigInt().Int64())
21 |
22 | decoder := sc.Decoder{Reader: buffer}
23 |
24 | result := Digest{}
25 | for i := 0; i < size; i++ {
26 | digestType := decoder.DecodeByte()
27 |
28 | switch digestType {
29 | case DigestTypeConsensusMessage:
30 | consensusDigest := DecodeDigestItem(buffer)
31 | result[DigestTypeConsensusMessage] = append(result[DigestTypeConsensusMessage], consensusDigest)
32 | case DigestTypeSeal:
33 | seal := DecodeDigestItem(buffer)
34 | result[DigestTypeSeal] = append(result[DigestTypeSeal], seal)
35 | case DigestTypePreRuntime:
36 | preRuntimeDigest := DecodeDigestItem(buffer)
37 | result[DigestTypePreRuntime] = append(result[DigestTypePreRuntime], preRuntimeDigest)
38 | case DigestTypeRuntimeEnvironmentUpgraded:
39 | sc.DecodeU8(buffer)
40 | // TODO:
41 | }
42 | }
43 |
44 | return result
45 | }
46 |
--------------------------------------------------------------------------------
/primitives/types/digest_item.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type DigestItem struct {
10 | Engine sc.FixedSequence[sc.U8]
11 | Payload sc.Sequence[sc.U8]
12 | }
13 |
14 | func (di DigestItem) Encode(buffer *bytes.Buffer) {
15 | di.Engine.Encode(buffer)
16 | di.Payload.Encode(buffer)
17 | }
18 |
19 | func (di DigestItem) Bytes() []byte {
20 | buffer := &bytes.Buffer{}
21 | di.Encode(buffer)
22 |
23 | return buffer.Bytes()
24 | }
25 |
26 | func DecodeDigestItem(buffer *bytes.Buffer) DigestItem {
27 | return DigestItem{
28 | Engine: sc.DecodeFixedSequence[sc.U8](4, buffer),
29 | Payload: sc.DecodeSequence[sc.U8](buffer),
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/primitives/types/dispatch_errors_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func Test_EncodeDispatchError(t *testing.T) {
11 | var testExamples = []struct {
12 | label string
13 | input DispatchError
14 | expectation []byte
15 | }{
16 | {label: "Encode(DispatchError('unknown error'))", input: NewDispatchErrorOther("unknown error"), expectation: []byte{0x00, 0x34, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72}},
17 | {label: "Encode(DispatchErrorCannotLookup)", input: NewDispatchErrorCannotLookup(), expectation: []byte{0x01}},
18 | {label: "Encode(DispatchErrorBadOrigin)", input: NewDispatchErrorBadOrigin(), expectation: []byte{0x02}},
19 | {label: "Encode(DispatchErrorCustomModule)", input: NewDispatchErrorModule(CustomModuleError{}), expectation: []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00}},
20 | }
21 |
22 | for _, testExample := range testExamples {
23 | t.Run(testExample.label, func(t *testing.T) {
24 | buffer := &bytes.Buffer{}
25 |
26 | testExample.input.Encode(buffer)
27 |
28 | assert.Equal(t, testExample.expectation, buffer.Bytes())
29 | })
30 | }
31 | }
32 |
33 | func Test_DecodeDispatchError(t *testing.T) {
34 | var testExamples = []struct {
35 | label string
36 | input []byte
37 | expectation DispatchError
38 | }{
39 |
40 | {label: "DecodeDispatchError(0x00, 0x34, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72)", input: []byte{0x00, 0x34, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72}, expectation: NewDispatchErrorOther("unknown error")},
41 | {label: "DecodeDispatchError(0x01)", input: []byte{0x01}, expectation: NewDispatchErrorCannotLookup()},
42 | {label: "DecodeDispatchError(0x02)", input: []byte{0x02}, expectation: NewDispatchErrorBadOrigin()},
43 | {label: "DecodeDispatchError(0x03, 0x00, 0x00, 0x00)", input: []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, expectation: NewDispatchErrorModule(CustomModuleError{})},
44 | }
45 |
46 | for _, testExample := range testExamples {
47 | t.Run(testExample.label, func(t *testing.T) {
48 | buffer := &bytes.Buffer{}
49 | buffer.Write(testExample.input)
50 |
51 | result := DecodeDispatchError(buffer)
52 |
53 | assert.Equal(t, testExample.expectation, result)
54 | })
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/primitives/types/dispatch_info.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // DispatchInfo A bundle of static information collected from the `#[pallet::weight]` attributes.
10 | type DispatchInfo struct {
11 | // Weight of this transaction.
12 | Weight Weight
13 |
14 | // Class of this transaction.
15 | Class DispatchClass
16 |
17 | // Does this transaction pay fees.
18 | PaysFee Pays
19 | }
20 |
21 | func (di DispatchInfo) Encode(buffer *bytes.Buffer) {
22 | di.Weight.Encode(buffer)
23 | di.Class.Encode(buffer)
24 | di.PaysFee.Encode(buffer)
25 | }
26 |
27 | func DecodeDispatchInfo(buffer *bytes.Buffer) DispatchInfo {
28 | di := DispatchInfo{}
29 | di.Weight = DecodeWeight(buffer)
30 | di.Class = DecodeDispatchClass(buffer)
31 | di.PaysFee = DecodePays(buffer)
32 | return di
33 | }
34 |
35 | func (di DispatchInfo) Bytes() []byte {
36 | return sc.EncodedBytes(di)
37 | }
38 |
39 | // ExtractActualWeight Extract the actual weight from a dispatch result if any or fall back to the default weight.
40 | func ExtractActualWeight(result *DispatchResultWithPostInfo[PostDispatchInfo], info *DispatchInfo) Weight {
41 | var pdi PostDispatchInfo
42 | if result.HasError {
43 | err := result.Err
44 | pdi = err.PostInfo
45 | } else {
46 | pdi = result.Ok
47 | }
48 | return pdi.CalcActualWeight(info)
49 | }
50 |
51 | // ExtractActualPaysFee Extract the actual pays_fee from a dispatch result if any or fall back to the default weight.
52 | func ExtractActualPaysFee(result *DispatchResultWithPostInfo[PostDispatchInfo], info *DispatchInfo) Pays {
53 | var pdi PostDispatchInfo
54 | if result.HasError {
55 | err := result.Err
56 | pdi = err.PostInfo
57 | } else {
58 | pdi = result.Ok
59 | }
60 | return pdi.Pays(info)
61 | }
62 |
63 | func GetDispatchInfo(call Call) DispatchInfo {
64 | function := call
65 | baseWeight := function.BaseWeight(call.Args())
66 |
67 | return DispatchInfo{
68 | Weight: function.WeightInfo(baseWeight),
69 | Class: function.ClassifyDispatch(baseWeight),
70 | PaysFee: function.PaysFee(baseWeight),
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/primitives/types/dispatch_outcome.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "reflect"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | "github.com/LimeChain/gosemble/primitives/log"
9 | )
10 |
11 | // DispatchOutcome This type specifies the outcome of dispatching a call to a module.
12 | //
13 | // In case of failure an error specific to the module is returned.
14 | //
15 | // Failure of the module call dispatching doesn't invalidate the extrinsic and it is still included
16 | // in the block, therefore all state changes performed by the dispatched call are still persisted.
17 | //
18 | // For example, if the dispatching of an extrinsic involves inclusion fee payment then these
19 | // changes are going to be preserved even if the call dispatched failed.
20 | type DispatchOutcome sc.VaryingData // = sc.Result[sc.Empty, DispatchError]
21 |
22 | func NewDispatchOutcome(value sc.Encodable) DispatchOutcome {
23 | // None = 0 - Extrinsic is valid and was submitted successfully.
24 | // DispatchError = 1 - Possible errors while dispatching the extrinsic.
25 | switch value.(type) {
26 | case DispatchError:
27 | return DispatchOutcome(sc.NewVaryingData(value))
28 | case sc.Empty, nil:
29 | return DispatchOutcome(sc.NewVaryingData(sc.Empty{}))
30 | default:
31 | log.Critical("invalid DispatchOutcome type")
32 | }
33 |
34 | panic("unreachable")
35 | }
36 |
37 | func (o DispatchOutcome) Encode(buffer *bytes.Buffer) {
38 | value := o[0]
39 |
40 | switch reflect.TypeOf(value) {
41 | case reflect.TypeOf(*new(sc.Empty)):
42 | sc.U8(0).Encode(buffer)
43 | case reflect.TypeOf(*new(DispatchError)):
44 | sc.U8(1).Encode(buffer)
45 | value.Encode(buffer)
46 | default:
47 | log.Critical("invalid DispatchOutcome type")
48 | }
49 | }
50 |
51 | func DecodeDispatchOutcome(buffer *bytes.Buffer) DispatchOutcome {
52 | b := sc.DecodeU8(buffer)
53 |
54 | switch b {
55 | case 0:
56 | return NewDispatchOutcome(sc.Empty{})
57 | case 1:
58 | value := DecodeDispatchError(buffer)
59 | return NewDispatchOutcome(value)
60 | default:
61 | log.Critical("invalid DispatchOutcome type")
62 | }
63 |
64 | panic("unreachable")
65 | }
66 |
67 | func (o DispatchOutcome) Bytes() []byte {
68 | return sc.EncodedBytes(o)
69 | }
70 |
--------------------------------------------------------------------------------
/primitives/types/dispatch_outcome_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | func Test_EncodeDispatchOutcome(t *testing.T) {
11 | var testExamples = []struct {
12 | label string
13 | input DispatchOutcome
14 | expectation []byte
15 | }{
16 | {label: "Encode DispatchOutcome(None)", input: NewDispatchOutcome(nil), expectation: []byte{0x00}},
17 | {label: "Encode DispatchOutcome(DispatchErrorBadOrigin)", input: NewDispatchOutcome(NewDispatchErrorBadOrigin()), expectation: []byte{0x01, 0x02}},
18 | }
19 |
20 | for _, testExample := range testExamples {
21 | t.Run(testExample.label, func(t *testing.T) {
22 | buffer := &bytes.Buffer{}
23 |
24 | testExample.input.Encode(buffer)
25 |
26 | assert.Equal(t, testExample.expectation, buffer.Bytes())
27 | })
28 | }
29 | }
30 |
31 | func Test_DecodeDispatchOutcome(t *testing.T) {
32 | var testExamples = []struct {
33 | label string
34 | input []byte
35 | expectation DispatchOutcome
36 | }{
37 | {label: "0x00", input: []byte{0x00}, expectation: NewDispatchOutcome(nil)},
38 | {label: "0x01, 0x02", input: []byte{0x01, 0x02}, expectation: NewDispatchOutcome(NewDispatchErrorBadOrigin())},
39 | }
40 |
41 | for _, testExample := range testExamples {
42 | t.Run(testExample.label, func(t *testing.T) {
43 | buffer := &bytes.Buffer{}
44 | buffer.Write(testExample.input)
45 |
46 | result := DecodeDispatchOutcome(buffer)
47 |
48 | assert.Equal(t, testExample.expectation, result)
49 | })
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/primitives/types/dispatch_result.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/primitives/log"
6 | )
7 |
8 | type DispatchResult sc.VaryingData
9 |
10 | func NewDispatchResult(value sc.Encodable) DispatchResult {
11 | switch value.(type) {
12 | case DispatchError, DispatchErrorWithPostInfo[PostDispatchInfo]:
13 | return DispatchResult(sc.NewVaryingData(value))
14 | case sc.Empty, nil:
15 | return DispatchResult(sc.NewVaryingData(sc.Empty{}))
16 | default:
17 | log.Critical("invalid DispatchResult type")
18 | }
19 |
20 | panic("unreachable")
21 | }
22 |
23 | type DispatchResultWithPostInfo[T sc.Encodable] struct {
24 | HasError sc.Bool
25 | Ok T
26 | Err DispatchErrorWithPostInfo[T]
27 | }
28 |
--------------------------------------------------------------------------------
/primitives/types/event.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type Event = sc.VaryingData
10 |
11 | func NewEvent(module sc.U8, event sc.U8, values ...sc.Encodable) Event {
12 | args := []sc.Encodable{module, event}
13 | args = append(args, values...)
14 |
15 | return sc.NewVaryingData(args...)
16 | }
17 |
18 | type EventRecord struct {
19 | Phase ExtrinsicPhase
20 | Event Event
21 | Topics sc.Sequence[H256]
22 | }
23 |
24 | func (er EventRecord) Encode(buffer *bytes.Buffer) {
25 | er.Phase.Encode(buffer)
26 | er.Event.Encode(buffer)
27 | er.Topics.Encode(buffer)
28 | }
29 |
30 | func (er EventRecord) Bytes() []byte {
31 | return sc.EncodedBytes(er)
32 | }
33 |
--------------------------------------------------------------------------------
/primitives/types/existence_requirement.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | type ExistenceRequirement sc.U8
6 |
7 | const (
8 | ExistenceRequirementKeepAlive ExistenceRequirement = iota
9 | ExistenceRequirementAllowDeath
10 | )
11 |
--------------------------------------------------------------------------------
/primitives/types/extra.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // SignedExtra implements SignedExtension
10 | // Extra data, E, is a tuple containing additional metadata about the extrinsic and the system it is meant to be executed in.
11 | type SignedExtra struct {
12 | Era Era
13 |
14 | // a compact integer containing the nonce of the sender.
15 | // The nonce must be incremented by one for each extrinsic created,
16 | // otherwise the Polkadot network will reject the extrinsic.
17 | Nonce sc.U32 // encode as Compact
18 |
19 | // a compact integer containing the transactor pay including tip.
20 | Fee sc.U128 // encode as Compact
21 | }
22 |
23 | func (e SignedExtra) Encode(buffer *bytes.Buffer) {
24 | e.Era.Encode(buffer)
25 | sc.ToCompact(e.Nonce).Encode(buffer)
26 | sc.Compact(e.Fee).Encode(buffer)
27 | }
28 |
29 | func DecodeExtra(buffer *bytes.Buffer) SignedExtra {
30 | e := SignedExtra{}
31 | e.Era = DecodeEra(buffer)
32 | e.Nonce = sc.U32(sc.U128(sc.DecodeCompact(buffer)).ToBigInt().Uint64())
33 | e.Fee = sc.U128(sc.DecodeCompact(buffer))
34 | return e
35 | }
36 |
37 | func (e SignedExtra) Bytes() []byte {
38 | return sc.EncodedBytes(e)
39 | }
40 |
--------------------------------------------------------------------------------
/primitives/types/extrinsic_signature.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // ExtrinsicSignature The signature is a varying data type indicating the used signature type,
10 | // followed by the signature created by the extrinsic author (the sender).
11 | type ExtrinsicSignature struct {
12 | // is the 32-byte address of the sender of the extrinsic
13 | // as described in https://docs.substrate.io/reference/address-formats/
14 | Signer MultiAddress
15 | Signature MultiSignature
16 | Extra SignedExtra
17 | }
18 |
19 | func (s ExtrinsicSignature) Encode(buffer *bytes.Buffer) {
20 | s.Signer.Encode(buffer)
21 | s.Signature.Encode(buffer)
22 | s.Extra.Encode(buffer)
23 | }
24 |
25 | func DecodeExtrinsicSignature(buffer *bytes.Buffer) ExtrinsicSignature {
26 | s := ExtrinsicSignature{}
27 | s.Signer = DecodeMultiAddress(buffer)
28 | s.Signature = DecodeMultiSignature(buffer)
29 | s.Extra = DecodeExtra(buffer)
30 | return s
31 | }
32 |
33 | func (s ExtrinsicSignature) Bytes() []byte {
34 | return sc.EncodedBytes(s)
35 | }
36 |
--------------------------------------------------------------------------------
/primitives/types/extrinsic_signature_payload.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/hashing"
8 | )
9 |
10 | // SignedPayload A payload that has been signed for an unchecked extrinsics.
11 | //
12 | // Note that the payload that we sign to produce unchecked extrinsic signature
13 | // is going to be different than the `SignaturePayload` - so the thing the extrinsic
14 | // actually contains.
15 | //
16 | // TODO: make it generic
17 | // generic::SignedPayload;
18 | type SignedPayload struct {
19 | Call Call
20 | Extra SignedExtra
21 | AdditionalSigned
22 | }
23 |
24 | type AdditionalSigned struct {
25 | SpecVersion sc.U32
26 | // FormatVersion sc.U32
27 |
28 | // Hh(G): a 32-byte array containing the genesis hash.
29 | GenesisHash H256 // size 32
30 |
31 | // Hh(B): a 32-byte array containing the hash of the block which starts the mortality period, as described in
32 | BlockHash H256 // size 32
33 |
34 | TransactionVersion sc.U32
35 | }
36 |
37 | func (sp SignedPayload) Encode(buffer *bytes.Buffer) {
38 | sp.Call.Encode(buffer)
39 | sp.Extra.Encode(buffer)
40 | sp.SpecVersion.Encode(buffer)
41 | sp.TransactionVersion.Encode(buffer)
42 | // sp.FormatVersion.Encode(buffer)
43 | sp.GenesisHash.Encode(buffer)
44 | sp.BlockHash.Encode(buffer)
45 | }
46 |
47 | func (sp SignedPayload) Bytes() []byte {
48 | return sc.EncodedBytes(sp)
49 | }
50 |
51 | func (sp SignedPayload) UsingEncoded() sc.Sequence[sc.U8] {
52 | enc := sp.Bytes()
53 |
54 | if len(enc) > 256 {
55 | return sc.BytesToSequenceU8(hashing.Blake256(enc))
56 | } else {
57 | return sc.BytesToSequenceU8(enc)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/primitives/types/fee_details.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | )
9 |
10 | type FeeDetails struct {
11 | InclusionFee sc.Option[InclusionFee]
12 |
13 | Tip Balance // not serializable
14 | }
15 |
16 | func (fd FeeDetails) Encode(buffer *bytes.Buffer) {
17 | fd.InclusionFee.Encode(buffer)
18 | }
19 |
20 | func (fd FeeDetails) Bytes() []byte {
21 | return sc.EncodedBytes(fd)
22 | }
23 |
24 | func DecodeFeeDetails(buffer *bytes.Buffer) FeeDetails {
25 | return FeeDetails{
26 | InclusionFee: sc.DecodeOptionWith(buffer, DecodeInclusionFee),
27 | }
28 | }
29 |
30 | func (fd FeeDetails) FinalFee() Balance {
31 | sum := fd.Tip
32 | if fd.InclusionFee.HasValue {
33 | inclusionFee := fd.InclusionFee.Value.InclusionFee().ToBigInt()
34 | total := new(big.Int).Add(inclusionFee, fd.Tip.ToBigInt())
35 |
36 | sum = sc.NewU128FromBigInt(total)
37 | }
38 |
39 | return sum
40 | }
41 |
--------------------------------------------------------------------------------
/primitives/types/hash.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | type H256 struct {
11 | sc.FixedSequence[sc.U8] // size 32
12 | }
13 |
14 | func NewH256(values ...sc.U8) H256 {
15 | if len(values) != 32 {
16 | log.Critical("H256 should be of size 32")
17 | }
18 | return H256{sc.NewFixedSequence(32, values...)}
19 | }
20 |
21 | func (h H256) Encode(buffer *bytes.Buffer) {
22 | h.FixedSequence.Encode(buffer)
23 | }
24 |
25 | func DecodeH256(buffer *bytes.Buffer) H256 {
26 | h := H256{}
27 | h.FixedSequence = sc.DecodeFixedSequence[sc.U8](32, buffer)
28 | return h
29 | }
30 |
31 | func (h H256) Bytes() []byte {
32 | return sc.EncodedBytes(h)
33 | }
34 |
35 | type H512 struct {
36 | sc.FixedSequence[sc.U8] // size 64
37 | }
38 |
39 | func NewH512(values ...sc.U8) H512 {
40 | if len(values) != 64 {
41 | log.Critical("H512 should be of size 64")
42 | }
43 | return H512{sc.NewFixedSequence(64, values...)}
44 | }
45 |
46 | func (h H512) Encode(buffer *bytes.Buffer) {
47 | h.FixedSequence.Encode(buffer)
48 | }
49 |
50 | func DecodeH512(buffer *bytes.Buffer) H512 {
51 | h := H512{}
52 | h.FixedSequence = sc.DecodeFixedSequence[sc.U8](64, buffer)
53 | return h
54 | }
55 |
56 | func (h H512) Bytes() []byte {
57 | return sc.EncodedBytes(h)
58 | }
59 |
60 | type Blake2bHash struct {
61 | sc.FixedSequence[sc.U8] // size 32
62 | }
63 |
64 | func NewBlake2bHash(values ...sc.U8) Blake2bHash {
65 | if len(values) != 32 {
66 | log.Critical("Blake2bHash should be of size 32")
67 | }
68 | return Blake2bHash{sc.NewFixedSequence(32, values...)}
69 | }
70 |
71 | func (h Blake2bHash) Encode(buffer *bytes.Buffer) {
72 | h.FixedSequence.Encode(buffer)
73 | }
74 |
75 | func DecodeBlake2bHash(buffer *bytes.Buffer) Blake2bHash {
76 | h := Blake2bHash{}
77 | h.FixedSequence = sc.DecodeFixedSequence[sc.U8](32, buffer)
78 | return h
79 | }
80 |
81 | func (h Blake2bHash) Bytes() []byte {
82 | return sc.EncodedBytes(h)
83 | }
84 |
--------------------------------------------------------------------------------
/primitives/types/header.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type BlockNumber = sc.U32
10 |
11 | type Header struct {
12 | ParentHash Blake2bHash
13 | Number BlockNumber
14 | StateRoot H256
15 | ExtrinsicsRoot H256
16 | Digest Digest
17 | }
18 |
19 | func (h Header) Encode(buffer *bytes.Buffer) {
20 | h.ParentHash.Encode(buffer)
21 | sc.ToCompact(uint64(h.Number)).Encode(buffer)
22 | h.StateRoot.Encode(buffer)
23 | h.ExtrinsicsRoot.Encode(buffer)
24 | h.Digest.Encode(buffer)
25 | }
26 |
27 | func (h Header) Bytes() []byte {
28 | buffer := &bytes.Buffer{}
29 | h.Encode(buffer)
30 |
31 | return buffer.Bytes()
32 | }
33 |
34 | func DecodeHeader(buffer *bytes.Buffer) Header {
35 | parentHash := DecodeBlake2bHash(buffer)
36 | blockNumber := sc.DecodeCompact(buffer)
37 | stateRoot := DecodeH256(buffer)
38 | extrinsicRoot := DecodeH256(buffer)
39 | digest := DecodeDigest(buffer)
40 |
41 | return Header{
42 | ParentHash: parentHash,
43 | Number: sc.U32(blockNumber.ToBigInt().Int64()),
44 | StateRoot: stateRoot,
45 | ExtrinsicsRoot: extrinsicRoot,
46 | Digest: digest,
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/primitives/types/identity_fee.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | // IdentityFee implements WeightToFee and maps one unit of weight
6 | // to one unit of fee.
7 | type IdentityFee struct {
8 | }
9 |
10 | func (i IdentityFee) WeightToFee(weight Weight) Balance {
11 | return sc.NewU128FromUint64(uint64(weight.RefTime))
12 | }
13 |
--------------------------------------------------------------------------------
/primitives/types/inc_ref_status.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | type IncRefStatus = sc.U8
6 |
7 | const (
8 | IncRefStatusCreated IncRefStatus = iota
9 | IncRefStatusExisted
10 | )
11 |
--------------------------------------------------------------------------------
/primitives/types/inclusion_fee.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | )
9 |
10 | type InclusionFee struct {
11 | BaseFee Balance
12 | LenFee Balance
13 | AdjustedWeightFee Balance
14 | }
15 |
16 | func NewInclusionFee(baseFee, lenFee, adjustedWeightFee Balance) InclusionFee {
17 | return InclusionFee{
18 | baseFee,
19 | lenFee,
20 | adjustedWeightFee,
21 | }
22 | }
23 |
24 | func (i InclusionFee) Encode(buffer *bytes.Buffer) {
25 | i.BaseFee.Encode(buffer)
26 | i.LenFee.Encode(buffer)
27 | i.AdjustedWeightFee.Encode(buffer)
28 | }
29 |
30 | func (i InclusionFee) Bytes() []byte {
31 | return sc.EncodedBytes(i)
32 | }
33 |
34 | func DecodeInclusionFee(buffer *bytes.Buffer) InclusionFee {
35 | return InclusionFee{
36 | BaseFee: sc.DecodeU128(buffer),
37 | LenFee: sc.DecodeU128(buffer),
38 | AdjustedWeightFee: sc.DecodeU128(buffer),
39 | }
40 | }
41 |
42 | func (i InclusionFee) InclusionFee() Balance {
43 | sum := new(big.Int).Add(i.BaseFee.ToBigInt(), i.LenFee.ToBigInt())
44 |
45 | sum = sum.Add(sum, i.AdjustedWeightFee.ToBigInt())
46 |
47 | return sc.NewU128FromBigInt(sum)
48 | }
49 |
--------------------------------------------------------------------------------
/primitives/types/inherent_data.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "sort"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | type InherentData struct {
12 | Data map[[8]byte]sc.Sequence[sc.U8]
13 | }
14 |
15 | func NewInherentData() *InherentData {
16 | return &InherentData{
17 | Data: make(map[[8]byte]sc.Sequence[sc.U8]),
18 | }
19 | }
20 |
21 | func (id *InherentData) Encode(buffer *bytes.Buffer) {
22 | sc.ToCompact(uint64(len(id.Data))).Encode(buffer)
23 |
24 | keys := make([][8]byte, 0)
25 | for k := range id.Data {
26 | keys = append(keys, k)
27 | }
28 |
29 | sort.Slice(keys, func(i, j int) bool { return string(keys[i][:]) < string(keys[j][:]) })
30 |
31 | for _, k := range keys {
32 | value := id.Data[k]
33 |
34 | buffer.Write(k[:])
35 | buffer.Write(value.Bytes())
36 | }
37 | }
38 |
39 | func (id *InherentData) Bytes() []byte {
40 | return sc.EncodedBytes(id)
41 | }
42 |
43 | func (id *InherentData) Put(key [8]byte, value sc.Encodable) error {
44 | if id.Data[key] != nil {
45 | return NewInherentErrorInherentDataExists(sc.BytesToSequenceU8(key[:]))
46 | }
47 |
48 | id.Data[key] = sc.BytesToSequenceU8(value.Bytes())
49 |
50 | return nil
51 | }
52 |
53 | func (id *InherentData) Clear() {
54 | id.Data = make(map[[8]byte]sc.Sequence[sc.U8])
55 | }
56 |
57 | func DecodeInherentData(buffer *bytes.Buffer) (*InherentData, error) {
58 | result := NewInherentData()
59 | length := sc.DecodeCompact(buffer).ToBigInt().Int64()
60 |
61 | for i := 0; i < int(length); i++ {
62 | key := [8]byte{}
63 | len, err := buffer.Read(key[:])
64 | if err != nil {
65 | return nil, err
66 | }
67 | if len != 8 {
68 | return nil, errors.New("invalid length")
69 | }
70 | value := sc.DecodeSequence[sc.U8](buffer)
71 |
72 | result.Data[key] = value
73 | if err != nil {
74 | return nil, err
75 | }
76 | }
77 |
78 | return result, nil
79 | }
80 |
--------------------------------------------------------------------------------
/primitives/types/inherent_data_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | var (
12 | key0 = [8]byte{
13 | 't', 'e', 's', 't', 'i', 'n', 'h', '0',
14 | }
15 | key1 = [8]byte{
16 | 't', 'e', 's', 't', 'i', 'n', 'h', '1',
17 | }
18 |
19 | value0 = sc.Sequence[sc.I32]{1, 2, 3}
20 | value1 = sc.U32(7)
21 |
22 | expectedEncoded = []byte{8, 116, 101, 115, 116, 105, 110, 104, 48, 52, 12, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 116, 101, 115, 116, 105, 110, 104, 49, 16, 7, 0, 0, 0}
23 | )
24 |
25 | func Test_InherentData_Encode(t *testing.T) {
26 | inherent := NewInherentData()
27 | assert.Nil(t, inherent.Put(key0, value0))
28 | assert.Nil(t, inherent.Put(key1, value1))
29 |
30 | encoded := inherent.Bytes()
31 |
32 | assert.Equal(t, expectedEncoded, encoded)
33 | }
34 |
35 | func Test_InherentData_Decode(t *testing.T) {
36 | buffer := &bytes.Buffer{}
37 | buffer.Write(expectedEncoded)
38 |
39 | res, err := DecodeInherentData(buffer)
40 | assert.Nil(t, err)
41 |
42 | buffer.Reset()
43 | buffer.Write(sc.SequenceU8ToBytes(res.Data[key0]))
44 |
45 | decodedValue0 := sc.DecodeSequence[sc.I32](buffer)
46 | assert.Equal(t, value0, decodedValue0)
47 |
48 | buffer.Reset()
49 | buffer.Write(sc.SequenceU8ToBytes(res.Data[key1]))
50 |
51 | decodedValue1 := sc.DecodeU32(buffer)
52 | assert.Equal(t, value1, decodedValue1)
53 | }
54 |
--------------------------------------------------------------------------------
/primitives/types/is_fatal_error.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import "github.com/LimeChain/goscale"
4 |
5 | type IsFatalError interface {
6 | goscale.Encodable
7 | IsFatal() goscale.Bool
8 | }
9 |
--------------------------------------------------------------------------------
/primitives/types/last_runtime_upgrade_info.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type LastRuntimeUpgradeInfo struct {
10 | SpecVersion sc.Compact
11 | SpecName sc.Str
12 | }
13 |
14 | func (lrui LastRuntimeUpgradeInfo) Encode(buffer *bytes.Buffer) {
15 | lrui.SpecVersion.Encode(buffer)
16 | lrui.SpecName.Encode(buffer)
17 | }
18 |
19 | func (lrui LastRuntimeUpgradeInfo) Bytes() []byte {
20 | buf := &bytes.Buffer{}
21 | lrui.Encode(buf)
22 |
23 | return buf.Bytes()
24 | }
25 |
26 | func DecodeLastRuntimeUpgradeInfo(buffer *bytes.Buffer) (value LastRuntimeUpgradeInfo) {
27 | if buffer.Len() <= 1 {
28 | return value
29 | }
30 |
31 | value.SpecVersion = sc.DecodeCompact(buffer)
32 | value.SpecName = sc.DecodeStr(buffer)
33 |
34 | return value
35 | }
36 |
--------------------------------------------------------------------------------
/primitives/types/lookup.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | // AccountIdLookup A lookup implementation returning the `AccountId` from a `MultiAddress`.
6 | type AccountIdLookup struct { // TODO: make it generic [AccountId, AccountIndex]
7 | // TODO: PhantomData[(AccountId, AccountIndex)]
8 | }
9 |
10 | func DefaultAccountIdLookup() AccountIdLookup {
11 | return AccountIdLookup{}
12 | }
13 |
14 | // TODO: MultiAddress[AccountId, AccountIndex]
15 | func (l AccountIdLookup) Lookup(a MultiAddress) (Address32, TransactionValidityError) {
16 | address := LookupAddress(a)
17 | if address.HasValue {
18 | return address.Value, nil
19 | }
20 |
21 | return Address32{}, NewTransactionValidityError(NewUnknownTransactionCannotLookup())
22 | }
23 |
24 | // LookupAddress Lookup an address to get an Id, if there's one there.
25 | func LookupAddress(a MultiAddress) sc.Option[Address32] { // TODO: MultiAddress[AccountId, AccountIndex]
26 | if a.IsAccountId() {
27 | return sc.NewOption[Address32](a.AsAccountId().Address32)
28 | }
29 |
30 | if a.IsAddress32() {
31 | return sc.NewOption[Address32](a.AsAddress32())
32 | }
33 |
34 | if a.IsAccountIndex() {
35 | return sc.NewOption[Address32](LookupIndex(a.AsAccountIndex()))
36 | }
37 |
38 | return sc.NewOption[Address32](nil)
39 | }
40 |
41 | // LookupIndex Lookup an T::AccountIndex to get an Id, if there's one there.
42 | func LookupIndex(index AccountIndex) sc.Option[Address32] {
43 | // TODO:
44 | return sc.NewOption[Address32](nil)
45 | }
46 |
--------------------------------------------------------------------------------
/primitives/types/metadata_extrinsic.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type MetadataExtrinsic struct {
10 | Type sc.Compact
11 | Version sc.U8
12 | SignedExtensions sc.Sequence[MetadataSignedExtension]
13 | }
14 |
15 | func (me MetadataExtrinsic) Encode(buffer *bytes.Buffer) {
16 | me.Type.Encode(buffer)
17 | me.Version.Encode(buffer)
18 | me.SignedExtensions.Encode(buffer)
19 | }
20 |
21 | func DecodeMetadataExtrinsic(buffer *bytes.Buffer) MetadataExtrinsic {
22 | return MetadataExtrinsic{
23 | Type: sc.DecodeCompact(buffer),
24 | Version: sc.DecodeU8(buffer),
25 | SignedExtensions: sc.DecodeSequenceWith(buffer, DecodeMetadataSignedExtension),
26 | }
27 | }
28 |
29 | func (me MetadataExtrinsic) Bytes() []byte {
30 | return sc.EncodedBytes(me)
31 | }
32 |
33 | type MetadataSignedExtension struct {
34 | Identifier sc.Str
35 | Type sc.Compact
36 | AdditionalSigned sc.Compact
37 | }
38 |
39 | func NewMetadataSignedExtension(identifier sc.Str, typeIndex, additionalSigned int) MetadataSignedExtension {
40 | return MetadataSignedExtension{
41 | Identifier: identifier,
42 | Type: sc.ToCompact(typeIndex),
43 | AdditionalSigned: sc.ToCompact(additionalSigned),
44 | }
45 | }
46 |
47 | func (mse MetadataSignedExtension) Encode(buffer *bytes.Buffer) {
48 | mse.Identifier.Encode(buffer)
49 | mse.Type.Encode(buffer)
50 | mse.AdditionalSigned.Encode(buffer)
51 | }
52 |
53 | func DecodeMetadataSignedExtension(buffer *bytes.Buffer) MetadataSignedExtension {
54 | return MetadataSignedExtension{
55 | Identifier: sc.DecodeStr(buffer),
56 | Type: sc.DecodeCompact(buffer),
57 | AdditionalSigned: sc.DecodeCompact(buffer),
58 | }
59 | }
60 |
61 | func (mse MetadataSignedExtension) Bytes() []byte {
62 | return sc.EncodedBytes(mse)
63 | }
64 |
--------------------------------------------------------------------------------
/primitives/types/module.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | type Module interface {
6 | Functions() map[sc.U8]Call
7 | PreDispatch(call Call) (sc.Empty, TransactionValidityError)
8 | ValidateUnsigned(source TransactionSource, call Call) (ValidTransaction, TransactionValidityError)
9 | Metadata() (sc.Sequence[MetadataType], MetadataModule)
10 | }
11 |
--------------------------------------------------------------------------------
/primitives/types/pays.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | const (
11 | // PaysYes Transactor will pay related fees.
12 | PaysYes sc.U8 = iota
13 |
14 | // PaysNo Transactor will NOT pay related fees.
15 | PaysNo
16 | )
17 |
18 | type Pays = sc.VaryingData
19 |
20 | func NewPaysYes() Pays {
21 | return sc.NewVaryingData(PaysYes)
22 | }
23 |
24 | func NewPaysNo() Pays {
25 | return sc.NewVaryingData(PaysNo)
26 | }
27 |
28 | func DecodePays(buffer *bytes.Buffer) Pays {
29 | b := sc.DecodeU8(buffer)
30 |
31 | switch b {
32 | case PaysYes:
33 | return NewPaysYes()
34 | case PaysNo:
35 | return NewPaysNo()
36 | default:
37 | log.Critical("invalid Pays type")
38 | }
39 |
40 | panic("unreachable")
41 | }
42 |
--------------------------------------------------------------------------------
/primitives/types/perthings.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | type Perbill struct {
11 | Percentage sc.U32
12 | }
13 |
14 | func (p Perbill) Encode(buffer *bytes.Buffer) {
15 | p.Percentage.Encode(buffer)
16 | }
17 |
18 | func DecodePerbill(buffer *bytes.Buffer) Perbill {
19 | p := Perbill{}
20 | p.Percentage = sc.DecodeU32(buffer)
21 | return p
22 | }
23 |
24 | func (p Perbill) Bytes() []byte {
25 | return sc.EncodedBytes(p)
26 | }
27 |
28 | func (p Perbill) Mul(v sc.Encodable) sc.Encodable {
29 | switch v := v.(type) {
30 | case sc.U32:
31 | return ((v / 100) * p.Percentage)
32 | case Weight:
33 | return Weight{
34 | RefTime: (v.RefTime / 100) * sc.U64(p.Percentage),
35 | ProofSize: (v.ProofSize / 100) * sc.U64(p.Percentage),
36 | }
37 | default:
38 | log.Critical("unsupported type")
39 | }
40 |
41 | panic("unreachable")
42 | }
43 |
--------------------------------------------------------------------------------
/primitives/types/phase.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | const (
11 | // PhaseApplyExtrinsic Applying an extrinsic.
12 | PhaseApplyExtrinsic sc.U8 = iota
13 |
14 | // PhaseFinalization Finalizing the block.
15 | PhaseFinalization
16 |
17 | // PhaseInitialization Initializing the block.
18 | PhaseInitialization
19 | )
20 |
21 | type ExtrinsicPhase = sc.VaryingData
22 |
23 | func NewExtrinsicPhaseApply(index sc.U32) ExtrinsicPhase {
24 | return sc.NewVaryingData(PhaseApplyExtrinsic, index)
25 | }
26 |
27 | func NewExtrinsicPhaseFinalization() ExtrinsicPhase {
28 | return sc.NewVaryingData(PhaseFinalization)
29 | }
30 |
31 | func NewExtrinsicPhaseInitialization() ExtrinsicPhase {
32 | return sc.NewVaryingData(PhaseInitialization)
33 | }
34 |
35 | func DecodeExtrinsicPhase(buffer *bytes.Buffer) ExtrinsicPhase {
36 | b := sc.DecodeU8(buffer)
37 |
38 | switch b {
39 | case PhaseApplyExtrinsic:
40 | index := sc.DecodeU32(buffer)
41 | return NewExtrinsicPhaseApply(index)
42 | case PhaseFinalization:
43 | return NewExtrinsicPhaseFinalization()
44 | case PhaseInitialization:
45 | return NewExtrinsicPhaseInitialization()
46 | default:
47 | log.Critical("invalid Phase type")
48 | }
49 |
50 | panic("unreachable")
51 | }
52 |
--------------------------------------------------------------------------------
/primitives/types/post_dispatch_info.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // PostDispatchInfo Weight information that is only available post dispatch.
10 | // NOTE: This can only be used to reduce the weight or fee, not increase it.
11 | type PostDispatchInfo struct {
12 | // Actual weight consumed by a call or `None` which stands for the worst case static weight.
13 | ActualWeight sc.Option[Weight]
14 |
15 | // Whether this transaction should pay fees when all is said and done.
16 | PaysFee sc.U8
17 | }
18 |
19 | func (pdi PostDispatchInfo) Encode(buffer *bytes.Buffer) {
20 | pdi.ActualWeight.Encode(buffer)
21 | pdi.PaysFee.Encode(buffer)
22 | }
23 |
24 | func DecodePostDispatchInfo(buffer *bytes.Buffer) PostDispatchInfo {
25 | pdi := PostDispatchInfo{}
26 | pdi.ActualWeight = sc.DecodeOptionWith(buffer, DecodeWeight)
27 | pdi.PaysFee = sc.DecodeU8(buffer)
28 | return pdi
29 | }
30 |
31 | func (pdi PostDispatchInfo) Bytes() []byte {
32 | return sc.EncodedBytes(pdi)
33 | }
34 |
35 | // CalcUnspent Calculate how much (if any) weight was not used by the `Dispatchable`.
36 | func (pdi PostDispatchInfo) CalcUnspent(info *DispatchInfo) Weight {
37 | return info.Weight.Sub(pdi.CalcActualWeight(info))
38 | }
39 |
40 | // CalcActualWeight Calculate how much weight was actually spent by the `Dispatchable`.
41 | func (pdi PostDispatchInfo) CalcActualWeight(info *DispatchInfo) Weight {
42 | if pdi.ActualWeight.HasValue {
43 | actualWeight := pdi.ActualWeight.Value
44 | return actualWeight.Min(info.Weight)
45 | } else {
46 | return info.Weight
47 | }
48 | }
49 |
50 | // Pays Determine if user should actually pay fees at the end of the dispatch.
51 | func (pdi PostDispatchInfo) Pays(info *DispatchInfo) Pays {
52 | // If they originally were not paying fees, or the post dispatch info
53 | // says they should not pay fees, then they don't pay fees.
54 | // This is because the pre dispatch information must contain the
55 | // worst case for weight and fees paid.
56 |
57 | if info.PaysFee[0] == PaysNo || pdi.PaysFee == PaysNo {
58 | return NewPaysNo()
59 | } else {
60 | // Otherwise they pay.
61 | return NewPaysYes()
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/primitives/types/pre.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // Pre is the type that encodes information that can be passed from pre_dispatch to post-dispatch.
10 | type Pre struct {
11 | Tip Balance
12 | Who Address32
13 | Imbalance sc.Option[Balance]
14 | }
15 |
16 | func (p Pre) Encode(buffer *bytes.Buffer) {
17 | p.Tip.Encode(buffer)
18 | p.Who.Encode(buffer)
19 | p.Imbalance.Encode(buffer)
20 | }
21 |
22 | func (p Pre) Bytes() []byte {
23 | return sc.EncodedBytes(p)
24 | }
25 |
--------------------------------------------------------------------------------
/primitives/types/public_key.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | // TODO: Extend for different types (ecdsa, ed25519, sr25519)
10 | type PublicKey = sc.FixedSequence[sc.U8]
11 |
12 | func DecodePublicKey(buffer *bytes.Buffer) PublicKey {
13 | return sc.DecodeFixedSequence[sc.U8](32, buffer)
14 | }
15 |
--------------------------------------------------------------------------------
/primitives/types/reasons.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import sc "github.com/LimeChain/goscale"
4 |
5 | type Reasons sc.U8
6 |
7 | const (
8 | ReasonsFee Reasons = iota
9 | ReasonsMisc
10 | ReasonsAll
11 | )
12 |
--------------------------------------------------------------------------------
/primitives/types/runtime_dispatch_info.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type RuntimeDispatchInfo struct {
10 | Weight Weight
11 | Class DispatchClass
12 | PartialFee Balance
13 | }
14 |
15 | func (rdi RuntimeDispatchInfo) Encode(buffer *bytes.Buffer) {
16 | rdi.Weight.Encode(buffer)
17 | rdi.Class.Encode(buffer)
18 | rdi.PartialFee.Encode(buffer)
19 | }
20 |
21 | func (rdi RuntimeDispatchInfo) Bytes() []byte {
22 | return sc.EncodedBytes(rdi)
23 | }
24 |
25 | func DecodeRuntimeDispatchInfo(buffer *bytes.Buffer) RuntimeDispatchInfo {
26 | rdi := RuntimeDispatchInfo{}
27 | rdi.Weight = DecodeWeight(buffer)
28 | rdi.Class = DecodeDispatchClass(buffer)
29 | rdi.PartialFee = sc.DecodeU128(buffer)
30 | return rdi
31 | }
32 |
--------------------------------------------------------------------------------
/primitives/types/runtime_origin.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | "github.com/LimeChain/gosemble/primitives/log"
6 | )
7 |
8 | const (
9 | RawOriginRoot sc.U8 = iota
10 | RawOriginSigned
11 | RawOriginNone
12 | )
13 |
14 | type RawOrigin struct {
15 | sc.VaryingData // [T AccountId]
16 | }
17 |
18 | func NewRawOriginRoot() RawOrigin {
19 | return RawOrigin{sc.NewVaryingData(RawOriginRoot)}
20 | }
21 |
22 | func NewRawOriginSigned(account Address32) RawOrigin {
23 | return RawOrigin{sc.NewVaryingData(RawOriginSigned, account)}
24 | }
25 |
26 | func NewRawOriginNone() RawOrigin {
27 | return RawOrigin{sc.NewVaryingData(RawOriginNone)}
28 | }
29 |
30 | func RawOriginFrom(a sc.Option[Address32]) RawOrigin {
31 | if a.HasValue {
32 | return NewRawOriginSigned(a.Value)
33 | } else {
34 | return NewRawOriginNone()
35 | }
36 | }
37 |
38 | func (o RawOrigin) IsRootOrigin() sc.Bool {
39 | return o.VaryingData[0] == RawOriginRoot
40 | }
41 |
42 | func (o RawOrigin) IsSignedOrigin() sc.Bool {
43 | return o.VaryingData[0] == RawOriginSigned
44 | }
45 |
46 | func (o RawOrigin) IsNoneOrigin() sc.Bool {
47 | return o.VaryingData[0] == RawOriginNone
48 | }
49 |
50 | func (o RawOrigin) AsSigned() Address32 {
51 | if !o.IsSignedOrigin() {
52 | log.Critical("not a signed origin")
53 | }
54 |
55 | return o.VaryingData[1].(Address32)
56 | }
57 |
58 | type RuntimeOrigin = RawOrigin
59 |
--------------------------------------------------------------------------------
/primitives/types/runtime_version.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | )
8 |
9 | type ApiItem struct {
10 | Name sc.FixedSequence[sc.U8] // size 8
11 | Version sc.U32
12 | }
13 |
14 | func (ai ApiItem) Encode(buffer *bytes.Buffer) {
15 | ai.Name.Encode(buffer)
16 | ai.Version.Encode(buffer)
17 | }
18 |
19 | func (ai ApiItem) Bytes() []byte {
20 | buffer := &bytes.Buffer{}
21 | ai.Encode(buffer)
22 |
23 | return buffer.Bytes()
24 | }
25 |
26 | func DecodeApiItem(buffer *bytes.Buffer) ApiItem {
27 | return ApiItem{
28 | Name: sc.DecodeFixedSequence[sc.U8](8, buffer),
29 | Version: sc.DecodeU32(buffer),
30 | }
31 | }
32 |
33 | type RuntimeVersion struct {
34 | SpecName sc.Str
35 | ImplName sc.Str
36 | AuthoringVersion sc.U32
37 | SpecVersion sc.U32
38 | ImplVersion sc.U32
39 | Apis sc.Sequence[ApiItem]
40 | TransactionVersion sc.U32
41 | StateVersion sc.U8
42 | }
43 |
44 | func (rv RuntimeVersion) Encode(buffer *bytes.Buffer) {
45 | rv.SpecName.Encode(buffer)
46 | rv.ImplName.Encode(buffer)
47 | rv.AuthoringVersion.Encode(buffer)
48 | rv.SpecVersion.Encode(buffer)
49 | rv.ImplVersion.Encode(buffer)
50 | rv.Apis.Encode(buffer)
51 | rv.TransactionVersion.Encode(buffer)
52 | rv.StateVersion.Encode(buffer)
53 | }
54 |
55 | func DecodeRuntimeVersion(buffer *bytes.Buffer) RuntimeVersion {
56 | var rv RuntimeVersion
57 |
58 | rv.SpecName = sc.DecodeStr(buffer)
59 | rv.ImplName = sc.DecodeStr(buffer)
60 | rv.AuthoringVersion = sc.DecodeU32(buffer)
61 | rv.SpecVersion = sc.DecodeU32(buffer)
62 | rv.ImplVersion = sc.DecodeU32(buffer)
63 |
64 | apisLength := sc.DecodeCompact(buffer).ToBigInt().Int64()
65 | if apisLength != 0 {
66 | var apis []ApiItem
67 | for i := 0; i < int(apisLength); i++ {
68 | apis = append(apis, DecodeApiItem(buffer))
69 | }
70 | rv.Apis = apis
71 | }
72 |
73 | rv.TransactionVersion = sc.DecodeU32(buffer)
74 | rv.StateVersion = sc.DecodeU8(buffer)
75 |
76 | return rv
77 | }
78 |
79 | func (rv RuntimeVersion) Bytes() []byte {
80 | return sc.EncodedBytes(rv)
81 | }
82 |
--------------------------------------------------------------------------------
/primitives/types/session_key.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | sc "github.com/LimeChain/goscale"
6 | )
7 |
8 | type SessionKey struct {
9 | Key sc.Sequence[sc.U8]
10 | TypeId sc.FixedSequence[sc.U8]
11 | }
12 |
13 | func NewSessionKey(key []byte, typeId [4]byte) SessionKey {
14 | return SessionKey{
15 | Key: sc.BytesToSequenceU8(key),
16 | TypeId: sc.BytesToFixedSequenceU8(typeId[:]),
17 | }
18 | }
19 |
20 | func (sk SessionKey) Encode(buffer *bytes.Buffer) {
21 | sk.Key.Encode(buffer)
22 | sk.TypeId.Encode(buffer)
23 | }
24 |
25 | func DecodeSessionKey(buffer *bytes.Buffer) SessionKey {
26 | return SessionKey{
27 | Key: sc.DecodeSequence[sc.U8](buffer),
28 | TypeId: sc.DecodeFixedSequence[sc.U8](4, buffer),
29 | }
30 | }
31 |
32 | func (sk SessionKey) Bytes() []byte {
33 | return sc.EncodedBytes(sk)
34 | }
35 |
--------------------------------------------------------------------------------
/primitives/types/signature.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/crypto"
8 | )
9 |
10 | type Ed25519 struct {
11 | H512 // size 64
12 | }
13 |
14 | func NewEd25519(values ...sc.U8) Ed25519 {
15 | return Ed25519{NewH512(values...)}
16 | }
17 |
18 | func (s Ed25519) Verify(msg sc.Sequence[sc.U8], signer Address32) sc.Bool {
19 | sig := sc.FixedSequenceU8ToBytes(s.H512.FixedSequence)
20 | message := sc.SequenceU8ToBytes(msg)
21 | key := sc.FixedSequenceU8ToBytes(signer.FixedSequence)
22 | return sc.Bool(crypto.ExtCryptoEd25519VerifyVersion1(sig, message, key))
23 | }
24 |
25 | func (s Ed25519) Encode(buffer *bytes.Buffer) {
26 | s.H512.Encode(buffer)
27 | }
28 |
29 | func DecodeEd25519(buffer *bytes.Buffer) Ed25519 {
30 | s := Ed25519{}
31 | s.H512 = DecodeH512(buffer)
32 | return s
33 | }
34 |
35 | func (s Ed25519) Bytes() []byte {
36 | return sc.EncodedBytes(s)
37 | }
38 |
39 | type Sr25519 struct {
40 | H512 // size 64
41 | }
42 |
43 | func NewSr25519(values ...sc.U8) Sr25519 {
44 | return Sr25519{NewH512(values...)}
45 | }
46 |
47 | func (s Sr25519) Verify(msg sc.Sequence[sc.U8], signer Address32) sc.Bool {
48 | sig := sc.FixedSequenceU8ToBytes(s.H512.FixedSequence)
49 | message := sc.SequenceU8ToBytes(msg)
50 | key := sc.FixedSequenceU8ToBytes(signer.FixedSequence)
51 | return sc.Bool(crypto.ExtCryptoSr25519VerifyVersion2(sig, message, key))
52 | }
53 |
54 | func (s Sr25519) Encode(buffer *bytes.Buffer) {
55 | s.H512.Encode(buffer)
56 | }
57 |
58 | func DecodeSr25519(buffer *bytes.Buffer) Sr25519 {
59 | s := Sr25519{}
60 | s.H512 = DecodeH512(buffer)
61 | return s
62 | }
63 |
64 | func (s Sr25519) Bytes() []byte {
65 | return sc.EncodedBytes(s)
66 | }
67 |
68 | type Ecdsa struct {
69 | sc.FixedSequence[sc.U8] // size 65
70 | }
71 |
72 | func NewEcdsa(values ...sc.U8) Ecdsa {
73 | return Ecdsa{sc.NewFixedSequence(65, values...)}
74 | }
75 |
76 | func (s Ecdsa) Verify(msg sc.Sequence[sc.U8], signer Address32) sc.Bool {
77 | // TODO:
78 | return true
79 | }
80 |
81 | func (s Ecdsa) Encode(buffer *bytes.Buffer) {
82 | s.FixedSequence.Encode(buffer)
83 | }
84 |
85 | func DecodeEcdsa(buffer *bytes.Buffer) Ecdsa {
86 | s := Ecdsa{}
87 | s.FixedSequence = sc.DecodeFixedSequence[sc.U8](65, buffer)
88 | return s
89 | }
90 |
91 | func (s Ecdsa) Bytes() []byte {
92 | return sc.EncodedBytes(s)
93 | }
94 |
--------------------------------------------------------------------------------
/primitives/types/timestamp_error.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | )
6 |
7 | const (
8 | TimestampErrorTooEarly sc.U8 = iota
9 | TimestampErrorTooFarInFuture
10 | )
11 |
12 | const (
13 | errInvalidTimestampType = "invalid TimestampError type"
14 | )
15 |
16 | type TimestampError struct {
17 | sc.VaryingData
18 | }
19 |
20 | func NewTimestampErrorTooEarly() TimestampError {
21 | return TimestampError{sc.NewVaryingData(TimestampErrorTooEarly)}
22 | }
23 |
24 | func NewTimestampErrorTooFarInFuture() TimestampError {
25 | return TimestampError{sc.NewVaryingData(TimestampErrorTooFarInFuture)}
26 | }
27 |
28 | func (te TimestampError) IsFatal() sc.Bool {
29 | switch te.VaryingData[0] {
30 | case TimestampErrorTooEarly, TimestampErrorTooFarInFuture:
31 | return true
32 | default:
33 | return false
34 | }
35 | }
36 |
37 | func (te TimestampError) Error() string {
38 | switch te.VaryingData[0] {
39 | case TimestampErrorTooEarly:
40 | return "The time since the last timestamp is lower than the minimum period."
41 | case TimestampErrorTooFarInFuture:
42 | return "The timestamp of the block is too far in the future."
43 | }
44 |
45 | panic("unreachable")
46 | }
47 |
--------------------------------------------------------------------------------
/primitives/types/token_error.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/primitives/log"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | const (
12 | TokenErrorNoFunds sc.U8 = iota
13 | TokenErrorWouldDie
14 | TokenErrorBelowMinimum
15 | TokenErrorCannotCreate
16 | TokenErrorUnknownAsset
17 | TokenErrorFrozen
18 | TokenErrorUnsupported
19 | )
20 |
21 | type TokenError = sc.VaryingData
22 |
23 | func NewTokenErrorNoFounds() TokenError {
24 | return sc.NewVaryingData(TokenErrorNoFunds)
25 | }
26 |
27 | func NewTokenErrorWouldDie() TokenError {
28 | return sc.NewVaryingData(TokenErrorWouldDie)
29 | }
30 |
31 | func NewTokenErrorBelowMinimum() TokenError {
32 | return sc.NewVaryingData(TokenErrorBelowMinimum)
33 | }
34 |
35 | func NewTokenErrorCannotCreate() TokenError {
36 | return sc.NewVaryingData(TokenErrorCannotCreate)
37 | }
38 |
39 | func NewTokenErrorUnknownAsset() TokenError {
40 | return sc.NewVaryingData(TokenErrorUnknownAsset)
41 | }
42 |
43 | func NewTokenErrorFrozen() TokenError {
44 | return sc.NewVaryingData(TokenErrorFrozen)
45 | }
46 |
47 | func NewTokenErrorUnsupported() TokenError {
48 | return sc.NewVaryingData(TokenErrorUnsupported)
49 | }
50 |
51 | func DecodeTokenError(buffer *bytes.Buffer) TokenError {
52 | b := sc.DecodeU8(buffer)
53 |
54 | switch b {
55 | case TokenErrorNoFunds:
56 | return NewTokenErrorNoFounds()
57 | case TokenErrorWouldDie:
58 | return NewTokenErrorWouldDie()
59 | case TokenErrorBelowMinimum:
60 | return NewTokenErrorBelowMinimum()
61 | case TokenErrorCannotCreate:
62 | return NewTokenErrorCannotCreate()
63 | case TokenErrorUnknownAsset:
64 | return NewTokenErrorUnknownAsset()
65 | case TokenErrorFrozen:
66 | return NewTokenErrorFrozen()
67 | case TokenErrorUnsupported:
68 | return NewTokenErrorUnsupported()
69 | default:
70 | log.Critical("invalid TokenError type")
71 | }
72 |
73 | panic("unreachable")
74 | }
75 |
--------------------------------------------------------------------------------
/primitives/types/transaction_errors_test.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/stretchr/testify/assert"
8 | )
9 |
10 | // TODO: add more test cases
11 |
12 | func Test_EncodeTransactionValidityError(t *testing.T) {
13 | var testExamples = []struct {
14 | label string
15 | input TransactionValidityError
16 | expectation []byte
17 | }{
18 | {
19 | label: "Encode(TransactionValidityError(InvalidTransaction(PaymentError)))",
20 | input: NewTransactionValidityError(NewInvalidTransactionPayment()),
21 | expectation: []byte{0x00, 0x01},
22 | },
23 | {
24 | label: "Encode(TransactionValidityError(UnknownTransaction(0)))",
25 | input: NewTransactionValidityError(NewUnknownTransactionCannotLookup()),
26 | expectation: []byte{0x01, 0x00},
27 | },
28 | }
29 |
30 | for _, testExample := range testExamples {
31 | t.Run(testExample.label, func(t *testing.T) {
32 | buffer := &bytes.Buffer{}
33 |
34 | testExample.input.Encode(buffer)
35 |
36 | assert.Equal(t, testExample.expectation, buffer.Bytes())
37 | })
38 | }
39 | }
40 |
41 | func Test_DecodeTransactionValidityError(t *testing.T) {
42 | var testExamples = []struct {
43 | label string
44 | input []byte
45 | expectation TransactionValidityError
46 | }{
47 | {
48 | label: "Encode(TransactionValidityError(InvalidTransaction(PaymentError)))",
49 | input: []byte{0x00, 0x01},
50 | expectation: NewTransactionValidityError(NewInvalidTransactionPayment()),
51 | },
52 | {
53 | label: "Encode(TransactionValidityError(UnknownTransaction(0)))",
54 | input: []byte{0x01, 0x00},
55 | expectation: NewTransactionValidityError(NewUnknownTransactionCannotLookup()),
56 | },
57 | }
58 |
59 | for _, testExample := range testExamples {
60 | t.Run(testExample.label, func(t *testing.T) {
61 | buffer := &bytes.Buffer{}
62 | buffer.Write(testExample.input)
63 |
64 | result := DecodeTransactionValidityError(buffer)
65 |
66 | assert.Equal(t, testExample.expectation, result)
67 | })
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/primitives/types/transaction_source.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/primitives/log"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | // The source of the transaction.
12 | //
13 | // Depending on the source we might apply different validation schemes.
14 | // For instance, we can disallow specific kinds of transactions if they were not produced
15 | // by our local node (for instance off-chain workers).
16 | const (
17 | // Transaction is already included in block.
18 | //
19 | // This means that we can't really tell where the transaction is coming from,
20 | // since it's already in the received block. Note that the custom validation logic
21 | // using either `Local` or `External` should most likely just allow `InBlock`
22 | // transactions as well.
23 | TransactionSourceInBlock sc.U8 = iota
24 |
25 | // Transaction is coming from a local source.
26 | //
27 | // This means that the transaction was produced internally by the node
28 | // (for instance an Off-Chain Worker, or an Off-Chain Call), as opposed
29 | // to being received over the network.
30 | TransactionSourceLocal
31 |
32 | // Transaction has been received externally.
33 | //
34 | // This means the transaction has been received from (usually) "untrusted" source,
35 | // for instance received over the network or RPC.
36 | TransactionSourceExternal
37 | )
38 |
39 | type TransactionSource = sc.VaryingData
40 |
41 | func NewTransactionSourceInBlock() TransactionSource {
42 | return sc.NewVaryingData(TransactionSourceInBlock)
43 | }
44 |
45 | func NewTransactionSourceLocal() TransactionSource {
46 | return sc.NewVaryingData(TransactionSourceLocal)
47 | }
48 |
49 | func NewTransactionSourceExternal() TransactionSource {
50 | return sc.NewVaryingData(TransactionSourceExternal)
51 | }
52 |
53 | func DecodeTransactionSource(buffer *bytes.Buffer) TransactionSource {
54 | b := sc.DecodeU8(buffer)
55 |
56 | switch b {
57 | case TransactionSourceInBlock:
58 | return NewTransactionSourceInBlock()
59 | case TransactionSourceLocal:
60 | return NewTransactionSourceLocal()
61 | case TransactionSourceExternal:
62 | return NewTransactionSourceExternal()
63 | default:
64 | log.Critical("invalid TransactionSource type")
65 | }
66 |
67 | panic("unreachable")
68 | }
69 |
--------------------------------------------------------------------------------
/primitives/types/transaction_validity_result.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/primitives/log"
8 | )
9 |
10 | // TransactionValidityResult Information on a transaction's validity and, if valid, on how it relates to other transactions.
11 | type TransactionValidityResult sc.VaryingData
12 |
13 | func NewTransactionValidityResult(value sc.Encodable) TransactionValidityResult {
14 | switch value.(type) {
15 | case ValidTransaction, TransactionValidityError:
16 | return TransactionValidityResult(sc.NewVaryingData(value))
17 | default:
18 | log.Critical("invalid TransactionValidityResult type")
19 | }
20 |
21 | panic("unreachable")
22 | }
23 |
24 | func (r TransactionValidityResult) Encode(buffer *bytes.Buffer) {
25 | switch r[0].(type) {
26 | case ValidTransaction:
27 | sc.U8(0).Encode(buffer)
28 | case TransactionValidityError:
29 | sc.U8(1).Encode(buffer)
30 | default:
31 | log.Critical("invalid TransactionValidityResult type")
32 | }
33 |
34 | r[0].Encode(buffer)
35 | }
36 |
37 | func DecodeTransactionValidityResult(buffer *bytes.Buffer) TransactionValidityResult {
38 | b := sc.DecodeU8(buffer)
39 |
40 | switch b {
41 | case 0:
42 | return NewTransactionValidityResult(DecodeValidTransaction(buffer))
43 | case 1:
44 | return NewTransactionValidityResult(DecodeTransactionValidityError(buffer))
45 | default:
46 | log.Critical("invalid TransactionValidityResult type")
47 | }
48 |
49 | panic("unreachable")
50 | }
51 |
52 | func (r TransactionValidityResult) Bytes() []byte {
53 | return sc.EncodedBytes(r)
54 | }
55 |
56 | func (r TransactionValidityResult) IsValidTransaction() sc.Bool {
57 | switch r[0].(type) {
58 | case ValidTransaction:
59 | return true
60 | default:
61 | return false
62 | }
63 | }
64 |
65 | func (r TransactionValidityResult) AsValidTransaction() ValidTransaction {
66 | if r.IsValidTransaction() {
67 | return r[0].(ValidTransaction)
68 | } else {
69 | log.Critical("not a ValidTransaction type")
70 | }
71 |
72 | panic("unreachable")
73 | }
74 |
--------------------------------------------------------------------------------
/primitives/types/transactional_error.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/LimeChain/gosemble/primitives/log"
7 |
8 | sc "github.com/LimeChain/goscale"
9 | )
10 |
11 | const (
12 | // Too many transactional layers have been spawned.
13 | TransactionalErrorLimitReached sc.U8 = iota
14 | // A transactional layer was expected, but does not exist.
15 | TransactionalErrorNoLayer
16 | )
17 |
18 | type TransactionalError = sc.VaryingData
19 |
20 | func NewTransactionalErrorLimitReached() TransactionalError {
21 | return sc.NewVaryingData(TransactionalErrorLimitReached)
22 | }
23 |
24 | func NewTransactionalErrorNoLayer() TransactionalError {
25 | return sc.NewVaryingData(TransactionalErrorNoLayer)
26 | }
27 |
28 | func DecodeTransactionalError(buffer *bytes.Buffer) TransactionalError {
29 | b := sc.DecodeU8(buffer)
30 |
31 | switch b {
32 | case TransactionalErrorLimitReached:
33 | return NewTransactionalErrorLimitReached()
34 | case TransactionalErrorNoLayer:
35 | return NewTransactionalErrorNoLayer()
36 | default:
37 | log.Critical("invalid TransactionalError type")
38 | }
39 |
40 | panic("unreachable")
41 | }
42 |
--------------------------------------------------------------------------------
/primitives/types/transactional_outcome.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | sc "github.com/LimeChain/goscale"
5 | )
6 |
7 | const (
8 | // Commit the transaction.
9 | TransactionOutcomeCommit sc.U8 = iota
10 | // Rollback the transaction.
11 | TransactionOutcomeRollback
12 | )
13 |
14 | // TransactionOutcome Describes on what should happen with a storage transaction.
15 | type TransactionOutcome = sc.VaryingData
16 |
17 | func NewTransactionOutcomeCommit(res sc.Encodable) TransactionOutcome {
18 | return sc.NewVaryingData(TransactionOutcomeCommit, res)
19 | }
20 |
21 | func NewTransactionOutcomeRollback(res sc.Encodable) TransactionOutcome {
22 | return sc.NewVaryingData(TransactionOutcomeRollback, res)
23 | }
24 |
--------------------------------------------------------------------------------
/primitives/types/versioned_authority_list.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import (
4 | "bytes"
5 | sc "github.com/LimeChain/goscale"
6 | )
7 |
8 | type VersionedAuthorityList struct {
9 | Version sc.U8
10 | AuthorityList sc.Sequence[Authority]
11 | }
12 |
13 | func (val VersionedAuthorityList) Encode(buffer *bytes.Buffer) {
14 | val.Version.Encode(buffer)
15 | val.AuthorityList.Encode(buffer)
16 | }
17 |
18 | func DecodeVersionedAuthorityList(buffer *bytes.Buffer) VersionedAuthorityList {
19 | return VersionedAuthorityList{
20 | Version: sc.DecodeU8(buffer),
21 | AuthorityList: sc.DecodeSequenceWith(buffer, DecodeAuthority),
22 | }
23 | }
24 |
25 | func (val VersionedAuthorityList) Bytes() []byte {
26 | return sc.EncodedBytes(val)
27 | }
28 |
--------------------------------------------------------------------------------
/primitives/types/weight_to_fee.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | type WeightToFee interface {
4 | WeightToFee(weight Weight) Balance
5 | }
6 |
--------------------------------------------------------------------------------
/primitives/types/withdraw_reasons.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | const (
4 | WithdrawReasonsTransactionPayment = 1 << iota
5 | WithdrawReasonsTransfer
6 | WithdrawReasonsReserve
7 | WithdrawReasonsFee
8 | WithdrawReasonsTip
9 | )
10 |
--------------------------------------------------------------------------------
/runtime/account_nonce_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "math/big"
5 | "testing"
6 |
7 | "github.com/centrifuge/go-substrate-rpc-client/v4/signature"
8 |
9 | sc "github.com/LimeChain/goscale"
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func Test_AccountNonceApi_account_nonce_Empty(t *testing.T) {
14 | pubKey := signature.TestKeyringPairAlice.PublicKey
15 |
16 | rt, _ := newTestRuntime(t)
17 |
18 | result, err := rt.Exec("AccountNonceApi_account_nonce", pubKey)
19 | assert.NoError(t, err)
20 |
21 | assert.Equal(t, sc.U32(0).Bytes(), result)
22 | }
23 |
24 | func Test_AccountNonceApi_account_nonce(t *testing.T) {
25 | pubKey := signature.TestKeyringPairAlice.PublicKey
26 | rt, storage := newTestRuntime(t)
27 |
28 | nonce := 1
29 |
30 | setStorageAccountInfo(t, storage, pubKey, big.NewInt(5), 1)
31 |
32 | result, err := rt.Exec("AccountNonceApi_account_nonce", pubKey)
33 | assert.NoError(t, err)
34 |
35 | assert.Equal(t, sc.U32(nonce).Bytes(), result)
36 | }
37 |
--------------------------------------------------------------------------------
/runtime/aura_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/ChainSafe/gossamer/lib/common"
8 | "github.com/ChainSafe/gossamer/pkg/scale"
9 | "github.com/stretchr/testify/assert"
10 | )
11 |
12 | func Test_Aura_Authorities_Empty(t *testing.T) {
13 | rt, _ := newTestRuntime(t)
14 |
15 | result, err := rt.Exec("AuraApi_authorities", []byte{})
16 | assert.NoError(t, err)
17 |
18 | assert.Equal(t, []byte{0}, result)
19 | }
20 |
21 | func Test_Aura_Authorities(t *testing.T) {
22 | pubKey1 := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee")
23 | pubKey2 := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ef")
24 |
25 | buffer := &bytes.Buffer{}
26 | buffer.Write(pubKey1)
27 |
28 | bytesPubKey1, err := common.Read32Bytes(buffer)
29 | assert.NoError(t, err)
30 |
31 | buffer.Write(pubKey2)
32 | bytesPubKey2, err := common.Read32Bytes(buffer)
33 | assert.NoError(t, err)
34 |
35 | authorities := [][32]byte{
36 | bytesPubKey1,
37 | bytesPubKey2,
38 | }
39 |
40 | bytesAuthorities, err := scale.Marshal(authorities)
41 | assert.NoError(t, err)
42 |
43 | rt, storage := newTestRuntime(t)
44 |
45 | err = (*storage).Put(append(keyAuraHash, keyAuthoritiesHash...), bytesAuthorities)
46 | assert.NoError(t, err)
47 |
48 | result, err := rt.Exec("AuraApi_authorities", []byte{})
49 | assert.NoError(t, err)
50 |
51 | assert.Equal(t, bytesAuthorities, result)
52 |
53 | var resultAuthorities [][32]byte
54 | err = scale.Unmarshal(result, &resultAuthorities)
55 | assert.NoError(t, err)
56 |
57 | assert.Equal(t, authorities, resultAuthorities)
58 | }
59 |
--------------------------------------------------------------------------------
/runtime/balances_force_free_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 | "testing"
7 |
8 | gossamertypes "github.com/ChainSafe/gossamer/dot/types"
9 | "github.com/ChainSafe/gossamer/pkg/scale"
10 | primitives "github.com/LimeChain/gosemble/primitives/types"
11 | cscale "github.com/centrifuge/go-substrate-rpc-client/v4/scale"
12 | "github.com/centrifuge/go-substrate-rpc-client/v4/signature"
13 | ctypes "github.com/centrifuge/go-substrate-rpc-client/v4/types"
14 | "github.com/stretchr/testify/assert"
15 | )
16 |
17 | func Test_Balances_ForceFree_BadOrigin(t *testing.T) {
18 | rt, storage := newTestRuntime(t)
19 | runtimeVersion, err := rt.Version()
20 | assert.NoError(t, err)
21 |
22 | metadata := runtimeMetadata(t, rt)
23 |
24 | alice, err := ctypes.NewMultiAddressFromAccountID(signature.TestKeyringPairAlice.PublicKey)
25 |
26 | call, err := ctypes.NewCall(metadata, "Balances.force_unreserve", alice, ctypes.NewU128(*big.NewInt(10000000000)))
27 | assert.NoError(t, err)
28 |
29 | // Create the extrinsic
30 | ext := ctypes.NewExtrinsic(call)
31 | o := ctypes.SignatureOptions{
32 | BlockHash: ctypes.Hash(parentHash),
33 | Era: ctypes.ExtrinsicEra{IsImmortalEra: true},
34 | GenesisHash: ctypes.Hash(parentHash),
35 | Nonce: ctypes.NewUCompactFromUInt(0),
36 | SpecVersion: ctypes.U32(runtimeVersion.SpecVersion),
37 | Tip: ctypes.NewUCompactFromUInt(0),
38 | TransactionVersion: ctypes.U32(runtimeVersion.TransactionVersion),
39 | }
40 |
41 | // Set Account Info
42 | balance, ok := big.NewInt(0).SetString("500000000000000", 10)
43 | assert.True(t, ok)
44 |
45 | setStorageAccountInfo(t, storage, signature.TestKeyringPairAlice.PublicKey, balance, 0)
46 |
47 | // Sign the transaction using Alice's default account
48 | err = ext.Sign(signature.TestKeyringPairAlice, o)
49 | assert.NoError(t, err)
50 |
51 | extEnc := bytes.Buffer{}
52 | encoder := cscale.NewEncoder(&extEnc)
53 | err = ext.Encode(*encoder)
54 | assert.NoError(t, err)
55 |
56 | header := gossamertypes.NewHeader(parentHash, stateRoot, extrinsicsRoot, blockNumber, gossamertypes.NewDigest())
57 | encodedHeader, err := scale.Marshal(*header)
58 | assert.NoError(t, err)
59 |
60 | _, err = rt.Exec("Core_initialize_block", encodedHeader)
61 | assert.NoError(t, err)
62 |
63 | res, err := rt.Exec("BlockBuilder_apply_extrinsic", extEnc.Bytes())
64 | assert.NoError(t, err)
65 |
66 | expectedResult :=
67 | primitives.NewApplyExtrinsicResult(
68 | primitives.NewDispatchOutcome(
69 | primitives.NewDispatchErrorBadOrigin()))
70 |
71 | assert.Equal(t, expectedResult.Bytes(), res)
72 | }
73 |
--------------------------------------------------------------------------------
/runtime/balances_force_transfer_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 | "testing"
7 |
8 | gossamertypes "github.com/ChainSafe/gossamer/dot/types"
9 | "github.com/ChainSafe/gossamer/pkg/scale"
10 | primitives "github.com/LimeChain/gosemble/primitives/types"
11 | cscale "github.com/centrifuge/go-substrate-rpc-client/v4/scale"
12 | "github.com/centrifuge/go-substrate-rpc-client/v4/signature"
13 | ctypes "github.com/centrifuge/go-substrate-rpc-client/v4/types"
14 | "github.com/stretchr/testify/assert"
15 | )
16 |
17 | func Test_Balances_ForceTransfer_BadOrigin(t *testing.T) {
18 | rt, storage := newTestRuntime(t)
19 | runtimeVersion, err := rt.Version()
20 | assert.NoError(t, err)
21 |
22 | metadata := runtimeMetadata(t, rt)
23 |
24 | alice, err := ctypes.NewMultiAddressFromAccountID(signature.TestKeyringPairAlice.PublicKey)
25 |
26 | bob, err := ctypes.NewMultiAddressFromHexAccountID(
27 | "0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22")
28 | assert.NoError(t, err)
29 |
30 | call, err := ctypes.NewCall(metadata, "Balances.force_transfer", alice, bob, ctypes.NewUCompactFromUInt(10000000000))
31 | assert.NoError(t, err)
32 |
33 | // Create the extrinsic
34 | ext := ctypes.NewExtrinsic(call)
35 | o := ctypes.SignatureOptions{
36 | BlockHash: ctypes.Hash(parentHash),
37 | Era: ctypes.ExtrinsicEra{IsImmortalEra: true},
38 | GenesisHash: ctypes.Hash(parentHash),
39 | Nonce: ctypes.NewUCompactFromUInt(0),
40 | SpecVersion: ctypes.U32(runtimeVersion.SpecVersion),
41 | Tip: ctypes.NewUCompactFromUInt(0),
42 | TransactionVersion: ctypes.U32(runtimeVersion.TransactionVersion),
43 | }
44 |
45 | // Set Account Info
46 | balance, ok := big.NewInt(0).SetString("500000000000000", 10)
47 | assert.True(t, ok)
48 |
49 | setStorageAccountInfo(t, storage, signature.TestKeyringPairAlice.PublicKey, balance, 0)
50 |
51 | // Sign the transaction using Alice's default account
52 | err = ext.Sign(signature.TestKeyringPairAlice, o)
53 | assert.NoError(t, err)
54 |
55 | extEnc := bytes.Buffer{}
56 | encoder := cscale.NewEncoder(&extEnc)
57 | err = ext.Encode(*encoder)
58 | assert.NoError(t, err)
59 |
60 | header := gossamertypes.NewHeader(parentHash, stateRoot, extrinsicsRoot, blockNumber, gossamertypes.NewDigest())
61 | encodedHeader, err := scale.Marshal(*header)
62 | assert.NoError(t, err)
63 |
64 | _, err = rt.Exec("Core_initialize_block", encodedHeader)
65 | assert.NoError(t, err)
66 |
67 | res, err := rt.Exec("BlockBuilder_apply_extrinsic", extEnc.Bytes())
68 | assert.NoError(t, err)
69 |
70 | expectedResult :=
71 | primitives.NewApplyExtrinsicResult(
72 | primitives.NewDispatchOutcome(
73 | primitives.NewDispatchErrorBadOrigin()))
74 |
75 | assert.Equal(t, expectedResult.Bytes(), res)
76 | }
77 |
--------------------------------------------------------------------------------
/runtime/balances_set_balance_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "math/big"
6 | "testing"
7 |
8 | gossamertypes "github.com/ChainSafe/gossamer/dot/types"
9 | "github.com/ChainSafe/gossamer/pkg/scale"
10 | primitives "github.com/LimeChain/gosemble/primitives/types"
11 | cscale "github.com/centrifuge/go-substrate-rpc-client/v4/scale"
12 | "github.com/centrifuge/go-substrate-rpc-client/v4/signature"
13 | ctypes "github.com/centrifuge/go-substrate-rpc-client/v4/types"
14 | "github.com/stretchr/testify/assert"
15 | )
16 |
17 | func Test_Balances_SetBalance_BadOrigin(t *testing.T) {
18 | rt, storage := newTestRuntime(t)
19 | runtimeVersion, err := rt.Version()
20 | assert.NoError(t, err)
21 |
22 | metadata := runtimeMetadata(t, rt)
23 |
24 | bob, err := ctypes.NewMultiAddressFromHexAccountID(
25 | "0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22")
26 | assert.NoError(t, err)
27 |
28 | call, err := ctypes.NewCall(metadata, "Balances.set_balance", bob, ctypes.NewUCompactFromUInt(10000000000), ctypes.NewUCompactFromUInt(10000000000))
29 | assert.NoError(t, err)
30 |
31 | // Create the extrinsic
32 | ext := ctypes.NewExtrinsic(call)
33 | o := ctypes.SignatureOptions{
34 | BlockHash: ctypes.Hash(parentHash),
35 | Era: ctypes.ExtrinsicEra{IsImmortalEra: true},
36 | GenesisHash: ctypes.Hash(parentHash),
37 | Nonce: ctypes.NewUCompactFromUInt(0),
38 | SpecVersion: ctypes.U32(runtimeVersion.SpecVersion),
39 | Tip: ctypes.NewUCompactFromUInt(0),
40 | TransactionVersion: ctypes.U32(runtimeVersion.TransactionVersion),
41 | }
42 |
43 | // Set Account Info
44 | balance, ok := big.NewInt(0).SetString("500000000000000", 10)
45 | assert.True(t, ok)
46 |
47 | setStorageAccountInfo(t, storage, signature.TestKeyringPairAlice.PublicKey, balance, 0)
48 |
49 | // Sign the transaction using Alice's default account
50 | err = ext.Sign(signature.TestKeyringPairAlice, o)
51 | assert.NoError(t, err)
52 |
53 | extEnc := bytes.Buffer{}
54 | encoder := cscale.NewEncoder(&extEnc)
55 | err = ext.Encode(*encoder)
56 | assert.NoError(t, err)
57 |
58 | header := gossamertypes.NewHeader(parentHash, stateRoot, extrinsicsRoot, blockNumber, gossamertypes.NewDigest())
59 | encodedHeader, err := scale.Marshal(*header)
60 | assert.NoError(t, err)
61 |
62 | _, err = rt.Exec("Core_initialize_block", encodedHeader)
63 | assert.NoError(t, err)
64 |
65 | res, err := rt.Exec("BlockBuilder_apply_extrinsic", extEnc.Bytes())
66 | assert.NoError(t, err)
67 |
68 | expectedResult :=
69 | primitives.NewApplyExtrinsicResult(
70 | primitives.NewDispatchOutcome(
71 | primitives.NewDispatchErrorBadOrigin()))
72 |
73 | assert.Equal(t, expectedResult.Bytes(), res)
74 | }
75 |
--------------------------------------------------------------------------------
/runtime/block_builder_check_inherents_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | "time"
7 |
8 | gossamertypes "github.com/ChainSafe/gossamer/dot/types"
9 | "github.com/ChainSafe/gossamer/pkg/scale"
10 | "github.com/LimeChain/gosemble/primitives/types"
11 | "github.com/stretchr/testify/assert"
12 | )
13 |
14 | func Test_CheckInherents(t *testing.T) {
15 | expectedCheckInherentsResult := types.NewCheckInherentsResult()
16 |
17 | idata := gossamertypes.NewInherentData()
18 | time := time.Now().UnixMilli()
19 | err := idata.SetInherent(gossamertypes.Timstap0, uint64(time))
20 |
21 | assert.NoError(t, err)
22 |
23 | ienc, err := idata.Encode()
24 | assert.NoError(t, err)
25 |
26 | rt, _ := newTestRuntime(t)
27 |
28 | inherentExt, err := rt.Exec("BlockBuilder_inherent_extrinsics", ienc)
29 | assert.NoError(t, err)
30 | assert.NotNil(t, inherentExt)
31 |
32 | header := gossamertypes.NewHeader(parentHash, stateRoot, extrinsicsRoot, blockNumber, gossamertypes.NewDigest())
33 |
34 | var exts [][]byte
35 | err = scale.Unmarshal(inherentExt, &exts)
36 | assert.NoError(t, err)
37 |
38 | block := gossamertypes.Block{
39 | Header: *header,
40 | Body: gossamertypes.BytesArrayToExtrinsics(exts),
41 | }
42 |
43 | encodedBlock, err := scale.Marshal(block)
44 | assert.NoError(t, err)
45 |
46 | inputData := append(encodedBlock, ienc...)
47 | bytesCheckInherentsResult, err := rt.Exec("BlockBuilder_check_inherents", inputData)
48 | assert.NoError(t, err)
49 |
50 | buffer := &bytes.Buffer{}
51 | buffer.Write(bytesCheckInherentsResult)
52 | checkInherentsResult := types.DecodeCheckInherentsResult(buffer)
53 |
54 | assert.Equal(t, expectedCheckInherentsResult, checkInherentsResult)
55 | }
56 |
--------------------------------------------------------------------------------
/runtime/block_builder_inherent_extrinsics_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | "time"
7 |
8 | gossamertypes "github.com/ChainSafe/gossamer/dot/types"
9 | sc "github.com/LimeChain/goscale"
10 | "github.com/LimeChain/gosemble/execution/types"
11 | timestamp "github.com/LimeChain/gosemble/frame/timestamp/dispatchables"
12 | "github.com/stretchr/testify/assert"
13 | )
14 |
15 | func Test_BlockBuilder_Inherent_Extrinsics(t *testing.T) {
16 | idata := gossamertypes.NewInherentData()
17 | time := time.Now().UnixMilli()
18 | err := idata.SetInherent(gossamertypes.Timstap0, uint64(time))
19 |
20 | assert.NoError(t, err)
21 |
22 | call := timestamp.NewSetCall(sc.NewVaryingData(sc.ToCompact(time)))
23 |
24 | expectedExtrinsic := types.NewUnsignedUncheckedExtrinsic(call)
25 |
26 | ienc, err := idata.Encode()
27 | assert.NoError(t, err)
28 |
29 | rt, _ := newTestRuntime(t)
30 |
31 | inherentExt, err := rt.Exec("BlockBuilder_inherent_extrinsics", ienc)
32 | assert.NoError(t, err)
33 |
34 | assert.NotNil(t, inherentExt)
35 |
36 | buffer := &bytes.Buffer{}
37 | buffer.Write([]byte{inherentExt[0]})
38 |
39 | totalInherents := sc.DecodeCompact(buffer)
40 | assert.Equal(t, int64(1), totalInherents.ToBigInt().Int64())
41 | buffer.Reset()
42 |
43 | buffer.Write(inherentExt[1:])
44 | extrinsic := types.DecodeUncheckedExtrinsic(buffer)
45 |
46 | assert.Equal(t, expectedExtrinsic, extrinsic)
47 | }
48 |
--------------------------------------------------------------------------------
/runtime/core_version_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | runtimetypes "github.com/ChainSafe/gossamer/lib/runtime"
8 | "github.com/ChainSafe/gossamer/pkg/scale"
9 | "github.com/stretchr/testify/assert"
10 | )
11 |
12 | func Test_CoreVersion(t *testing.T) {
13 | rt, _ := newTestRuntime(t)
14 |
15 | res, err := rt.Exec("Core_version", []byte{})
16 | assert.NoError(t, err)
17 |
18 | buffer := bytes.Buffer{}
19 | buffer.Write(res)
20 | dec := scale.NewDecoder(&buffer)
21 | runtimeVersion := runtimetypes.Version{}
22 | err = dec.Decode(&runtimeVersion)
23 | assert.NoError(t, err)
24 | assert.Equal(t, "node-template", string(runtimeVersion.SpecName))
25 | assert.Equal(t, "node-template", string(runtimeVersion.ImplName))
26 | assert.Equal(t, uint32(1), runtimeVersion.AuthoringVersion)
27 | assert.Equal(t, uint32(100), runtimeVersion.SpecVersion)
28 | assert.Equal(t, uint32(1), runtimeVersion.ImplVersion)
29 | assert.Equal(t, uint32(1), runtimeVersion.TransactionVersion)
30 | assert.Equal(t, uint32(1), runtimeVersion.StateVersion)
31 | }
32 |
--------------------------------------------------------------------------------
/runtime/grandpa_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/ChainSafe/gossamer/lib/common"
5 | sc "github.com/LimeChain/goscale"
6 | "github.com/LimeChain/gosemble/constants"
7 | "github.com/LimeChain/gosemble/constants/grandpa"
8 | "github.com/LimeChain/gosemble/primitives/types"
9 | "github.com/stretchr/testify/assert"
10 | "testing"
11 | )
12 |
13 | func Test_Grandpa_Authorities_Empty(t *testing.T) {
14 | rt, _ := newTestRuntime(t)
15 |
16 | result, err := rt.Exec("GrandpaApi_grandpa_authorities", []byte{})
17 | assert.NoError(t, err)
18 |
19 | assert.Equal(t, []byte{0}, result)
20 | }
21 |
22 | func Test_Grandpa_Authorities(t *testing.T) {
23 | rt, storage := newTestRuntime(t)
24 | pubKey1 := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee")
25 | pubKey2 := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ef")
26 | weight := sc.U64(1)
27 |
28 | storageAuthorityList := types.VersionedAuthorityList{
29 | Version: grandpa.AuthorityVersion,
30 | AuthorityList: sc.Sequence[types.Authority]{
31 | {
32 | Id: sc.BytesToFixedSequenceU8(pubKey1),
33 | Weight: weight,
34 | },
35 | {
36 | Id: sc.BytesToFixedSequenceU8(pubKey2),
37 | Weight: weight,
38 | },
39 | },
40 | }
41 |
42 | err := (*storage).Put(constants.KeyGrandpaAuthorities, storageAuthorityList.Bytes())
43 | assert.NoError(t, err)
44 |
45 | result, err := rt.Exec("GrandpaApi_grandpa_authorities", []byte{})
46 | assert.NoError(t, err)
47 |
48 | assert.Equal(t, storageAuthorityList.AuthorityList.Bytes(), result)
49 | }
50 |
--------------------------------------------------------------------------------
/runtime/metadata_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | sc "github.com/LimeChain/goscale"
8 | "github.com/LimeChain/gosemble/primitives/types"
9 | "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec"
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func Test_Metadata_Encoding_Success(t *testing.T) {
14 | runtime, _ := newTestRuntime(t)
15 | gossamerMetadata := runtimeMetadata(t, runtime)
16 |
17 | bMetadata, err := runtime.Metadata()
18 | assert.NoError(t, err)
19 |
20 | buffer := bytes.NewBuffer(bMetadata)
21 |
22 | // Decode Compact Length
23 | _ = sc.DecodeCompact(buffer)
24 |
25 | // Copy bytes for assertion after re-encode.
26 | bMetadataCopy := make([]byte, buffer.Len())
27 | copy(bMetadataCopy, buffer.Bytes())
28 |
29 | metadata, err := types.DecodeMetadata(buffer)
30 | assert.NoError(t, err)
31 |
32 | // Assert encoding of previously decoded
33 | assert.Equal(t, bMetadataCopy, metadata.Bytes())
34 |
35 | // Encode gossamer Metadata
36 | bGossamerMetadata, err := codec.Encode(gossamerMetadata)
37 | assert.NoError(t, err)
38 |
39 | assert.Equal(t, metadata.Bytes(), bGossamerMetadata)
40 | }
41 |
--------------------------------------------------------------------------------
/runtime/session_keys_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "github.com/ChainSafe/gossamer/lib/common"
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/constants/aura"
8 | "github.com/LimeChain/gosemble/constants/grandpa"
9 | "github.com/LimeChain/gosemble/primitives/types"
10 | "github.com/stretchr/testify/assert"
11 | "testing"
12 | )
13 |
14 | func Test_SessionKeys_Generate_Session_Keys(t *testing.T) {
15 | rt, _ := newTestRuntime(t)
16 | // TODO: not working with seed, Gossamer fails
17 | //seed := []byte("//Alice")
18 | option := sc.NewOption[sc.U8](nil)
19 |
20 | assert.Equal(t, 0, rt.Keystore().Aura.Size())
21 | assert.Equal(t, 0, rt.Keystore().Gran.Size())
22 |
23 | result, err := rt.Exec("SessionKeys_generate_session_keys", option.Bytes())
24 | assert.NoError(t, err)
25 |
26 | assert.Equal(t, 1, rt.Keystore().Aura.Size())
27 | assert.Equal(t, 1, rt.Keystore().Gran.Size())
28 |
29 | buffer := bytes.NewBuffer(result)
30 |
31 | seq := sc.DecodeSequence[sc.U8](buffer)
32 | buffer.Reset()
33 | buffer.Write(sc.SequenceU8ToBytes(seq))
34 |
35 | auraKey := types.DecodePublicKey(buffer)
36 | grandpaKey := types.DecodePublicKey(buffer)
37 |
38 | assert.Equal(t, rt.Keystore().Aura.PublicKeys()[0].Encode(), auraKey.Bytes())
39 | assert.Equal(t, rt.Keystore().Gran.PublicKeys()[0].Encode(), grandpaKey.Bytes())
40 | }
41 |
42 | func Test_SessionKeys_Decode_Session_Keys(t *testing.T) {
43 | rt, _ := newTestRuntime(t)
44 |
45 | auraKey := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee")
46 | grandpaKey := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ef")
47 |
48 | sessionKeys := sc.Sequence[types.SessionKey]{
49 | types.NewSessionKey(auraKey, aura.KeyTypeId),
50 | types.NewSessionKey(grandpaKey, grandpa.KeyTypeId),
51 | }
52 | expectedResult := sc.NewOption[sc.Sequence[types.SessionKey]](sessionKeys)
53 |
54 | encodedKeys := sc.BytesToSequenceU8(append(auraKey, grandpaKey...)).Bytes()
55 |
56 | result, err := rt.Exec("SessionKeys_decode_session_keys", encodedKeys)
57 | assert.NoError(t, err)
58 |
59 | assert.Equal(t, expectedResult.Bytes(), result)
60 | }
61 |
--------------------------------------------------------------------------------
/runtime/transactional_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "testing"
5 |
6 | sc "github.com/LimeChain/goscale"
7 | "github.com/LimeChain/gosemble/execution/types"
8 | "github.com/LimeChain/gosemble/frame/testable/dispatchables"
9 |
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | // TODO: in the test case "Commit_Then_Rollback" the host
14 | // panics with "fatal error: exitsyscall: syscall frame is no longer valid"
15 |
16 | func Test_Storage_Layer_Rollback_Then_Commit(t *testing.T) {
17 | rt, storage := newTestRuntime(t)
18 |
19 | call := dispatchables.NewTestCall(sc.NewVaryingData(sc.Sequence[sc.U8]{}))
20 |
21 | extrinsic := types.NewUnsignedUncheckedExtrinsic(call)
22 |
23 | _, err := rt.Exec("BlockBuilder_apply_extrinsic", extrinsic.Bytes())
24 | assert.NoError(t, err)
25 |
26 | assert.Equal(t, []byte{1}, (*storage).Get([]byte("testvalue")))
27 | }
28 |
--------------------------------------------------------------------------------
/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "unsafe"
5 | )
6 |
7 | var alivePointers = map[uintptr]interface{}{}
8 |
9 | func Retain(data []byte) {
10 | ptr := &data[0]
11 | unsafePtr := uintptr(unsafe.Pointer(ptr))
12 | alivePointers[unsafePtr] = data
13 | }
14 |
15 | func Int64ToOffsetAndSize(offsetAndSize int64) (offset int32, size int32) {
16 | return int32(offsetAndSize), int32(offsetAndSize >> 32)
17 | }
18 |
19 | func OffsetAndSizeToInt64(offset int32, size int32) int64 {
20 | return int64(offset) | (int64(size) << 32)
21 | }
22 |
23 | func Offset32(data []byte) int32 {
24 | return int32(SliceToOffset(data))
25 | }
26 |
27 | func SliceToOffset(data []byte) uintptr {
28 | if len(data) == 0 {
29 | return uintptr(unsafe.Pointer(nil))
30 | }
31 |
32 | return uintptr(unsafe.Pointer(&data[0]))
33 | }
34 |
35 | func BytesToOffsetAndSize(data []byte) int64 {
36 | offset := SliceToOffset(data)
37 | size := len(data)
38 | return OffsetAndSizeToInt64(int32(offset), int32(size))
39 | }
40 |
41 | func ToWasmMemorySlice(offset int32, size int32) []byte {
42 | return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(offset))), uintptr(size))
43 | }
44 |
--------------------------------------------------------------------------------