├── .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 | --------------------------------------------------------------------------------