├── .devcontainer └── devcontainer.json ├── .dockerignore ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── ask-a-question.md │ ├── report-a-bug.md │ └── suggest-a-feature.md └── workflows │ └── .autobuild.yml ├── .gitignore ├── .vscode └── tasks.json ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── doc └── rust-setup.md ├── docker-compose.yml ├── docs ├── erc20 │ ├── erc20.hex │ ├── erc20.sol │ └── erc20.wasm ├── interact-using-web.md └── web-ui │ ├── after-balanceOfAliceBob.png │ ├── after-transfer.png │ ├── before-balanceOfAlice.png │ ├── contract-address.png │ ├── deploy-contract.png │ ├── local-node.png │ ├── sendtx-balanceOfAlice.png │ └── sendtx-transfer.png ├── node ├── Cargo.toml ├── build.rs └── src │ ├── chain_spec.rs │ ├── cli.rs │ ├── command.rs │ ├── lib.rs │ ├── main.rs │ ├── rpc.rs │ └── service.rs ├── pallets └── template │ ├── Cargo.toml │ └── src │ ├── lib.rs │ ├── mock.rs │ └── tests.rs ├── runtime ├── Cargo.toml ├── build.rs └── src │ ├── lib.rs │ └── multiaddress.rs └── scripts ├── docker_run.sh └── init.sh /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Substrate Node template", 3 | "context": "..", 4 | "settings": { 5 | "terminal.integrated.shell.linux": "/bin/bash", 6 | "lldb.executable": "/usr/bin/lldb" 7 | }, 8 | "extensions": [ 9 | "rust-lang.rust", 10 | "bungcip.better-toml", 11 | "vadimcn.vscode-lldb" 12 | ], 13 | "forwardPorts": [ 14 | 3000, 15 | 9944 16 | ], 17 | "preCreateCommand": "cargo build --release && cargo check", 18 | "postStartCommand": "./target/release/node-template --dev --ws-external", 19 | "menuActions": [ 20 | {"id": "polkadotjs", 21 | "label": "Open PolkadotJS Apps", 22 | "type": "external-preview", 23 | "args": ["https://polkadot.js.org/apps/?rpc=wss%3A%2F%2F/$HOST/wss"]} 24 | ], 25 | "image": "paritytech/substrate-playground-template-node-template:latest" 26 | } 27 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/target 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*.rs] 3 | indent_style=tab 4 | indent_size=tab 5 | tab_width=4 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=100 10 | insert_final_newline=true 11 | 12 | [*.yml] 13 | indent_style=space 14 | indent_size=2 15 | tab_width=8 16 | end_of_line=lf 17 | 18 | [*.sh] 19 | indent_style=space 20 | indent_size=2 21 | tab_width=8 22 | end_of_line=lf 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ask-a-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Ask a Question 3 | about: Ask a question about this template. 4 | title: "" 5 | labels: question 6 | assignees: "" 7 | --- 8 | 9 | **Question** 10 | 11 | _Please include information such as the following: is your question to clarify an existing resource 12 | or are you asking about something new? what are you trying to accomplish? where have you looked for 13 | answers?_ 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report-a-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a Bug 3 | about: Report a problem with this template. 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | **Description** 10 | 11 | _Tell us what happened. In particular, be specific about any changes you made to this template. 12 | Ideally, provide a link to your project's GitHub repository. Please note that we are not able to 13 | support all conceivable changes to this template project, but the more information you are able to 14 | provide the more equipped we will be to help._ 15 | 16 | **Steps to Reproduce** 17 | 18 | _Replace the example steps below with actual steps to reproduce the bug you're reporting._ 19 | 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | **Expected vs. Actual Behavior** 26 | 27 | _What did you expect to happen after you followed the steps you described in the last section? What 28 | actually happened?_ 29 | 30 | **Environment** 31 | 32 | _Describe the environment in which you encountered this bug. Use the list below as a starting point 33 | and add additional information if you think it's relevant._ 34 | 35 | - Operating system: 36 | - Template version/tag: 37 | - Rust version (run `rustup show`): 38 | 39 | **Logs, Errors or Screenshots** 40 | 41 | _Please provide the text of any logs or errors that you experienced; if 42 | applicable, provide screenshots to help illustrate the problem._ 43 | 44 | **Additional Information** 45 | 46 | _Please add any other details that you think may help us solve your problem._ 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggest-a-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggest a Feature 3 | about: Suggest a new feature or an improvement to an existing feature for this template. 4 | title: "" 5 | labels: enhancement 6 | assignees: "" 7 | --- 8 | 9 | **Motivation** 10 | 11 | _Describe the need or frustration that motivated you to make this suggestion. Please note that the 12 | goal of this project is to provide a general-purpose template project, so please take care when 13 | suggesting features that may be specific to a particular use case._ 14 | 15 | **Suggested Solution** 16 | 17 | _Describe your suggested solution to the need or frustration that you are experiencing._ 18 | 19 | **Alternatives** 20 | 21 | _Describe any alternative solutions or features you considered and why you believe your suggested 22 | solution is preferable._ 23 | 24 | **Additional Information** 25 | 26 | _Provide any additional information that you believe may help us evaluate your suggestion._ 27 | -------------------------------------------------------------------------------- /.github/workflows/.autobuild.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: build 4 | 5 | # Controls when the action will run. 6 | # Triggers the workflow on push or pull request events 7 | on: 8 | push: 9 | branches: 10 | - master 11 | pull_request: 12 | branches: 13 | - master 14 | 15 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 16 | jobs: 17 | # This workflow contains a single job called "build" 18 | runs: 19 | # The type of runner that the job will run on 20 | runs-on: ubuntu-latest 21 | container: 22 | image: secondstate/substrate-ssvm 23 | 24 | # Steps represent a sequence of tasks that will be executed as part of the job 25 | steps: 26 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 27 | - uses: actions/checkout@v2 28 | 29 | # Runs a set of commands using the runners shell 30 | - name: Build substrate-ssvm-node 31 | run: | 32 | ln -sf /root/.rustup $HOME/ 33 | ln -sf /root/.cargo $HOME/ 34 | make init && make build -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | **/target/ 4 | # These are backup files generated by rustfmt 5 | **/*.rs.bk 6 | 7 | .DS_Store 8 | 9 | # The cache for docker container dependency 10 | .cargo 11 | 12 | # The cache for chain data in container 13 | .local -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Run ", 8 | "type": "shell", 9 | "command": "cargo", 10 | "args": ["run", "--release", "--", "--dev"], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | }, 15 | "presentation": { 16 | "reveal": "always", 17 | "panel": "new" 18 | }, 19 | "problemMatcher": [ 20 | { 21 | "owner": "rust", 22 | "fileLocation": ["relative", "${workspaceRoot}"], 23 | "pattern": { 24 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(\\d+):(\\d+)\\s+(warning|error):\\s+(.*)$", 25 | "file": 1, 26 | "line": 2, 27 | "column": 3, 28 | "endLine": 4, 29 | "endColumn": 5, 30 | "severity": 6, 31 | "message": 7 32 | } 33 | } 34 | ] 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [profile.release] 2 | panic = 'unwind' 3 | 4 | [workspace] 5 | members = [ 6 | 'node', 7 | # 'pallets/*', 8 | 'runtime', 9 | ] 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM secondstate/ssvm:latest 2 | ENV PATH="/root/.cargo/bin:${PATH}" 3 | 4 | # Install rust 5 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y 6 | RUN rustup update nightly && rustup update stable 7 | RUN rustup target add wasm32-unknown-unknown --toolchain nightly 8 | 9 | # Install yarn 10 | RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - 11 | RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list 12 | RUN apt update && apt install -y yarn 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: init 2 | init: 3 | ./scripts/init.sh 4 | 5 | .PHONY: check 6 | check: 7 | SKIP_WASM_BUILD=1 cargo check --release 8 | 9 | .PHONY: test 10 | test: 11 | SKIP_WASM_BUILD=1 cargo test --release --all 12 | 13 | .PHONY: run 14 | run: 15 | cargo run --release -- --dev --tmp 16 | 17 | .PHONY: build 18 | build: 19 | cargo build --release 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Substrate SSVM Node ![build](https://github.com/second-state/substrate-ssvm-node/workflows/build/badge.svg) 2 | 3 | The primary objective of this project was to bring the Ethereum flavored WebAssembly (EWASM) runtime to Substrate. It enables developer collaboration between the Ethereum and Polkadot/Substrate ecosystems, and promotes inter-blockchain interoperability at the application level. You can now create a Substrate node (or Polkadot parachain) that supports the deployment and execution of EWASM smart contracts. 4 | 5 | The project has a few components and dependencies. 6 | 7 | 1. The [EWASM Test Guide](https://github.com/second-state/rust-ssvm/blob/master/docs/EWASM_TEST.md) shows how to use the official EWASM test suite to verify the SSVM EWASM engine. 8 | 2. The [ssvm-evmc](https://github.com/second-state/evmc) project provides a Rust EVMC binding for SSVM. ([crates.io](https://crates.io/crates/ssvm-evmc-client/6.3.1-rc4)) 9 | 3. The [rust-ssvm](https://github.com/second-state/rust-ssvm) project provides a Rust interface on SSVM. ([crates.io](https://crates.io/crates/rust-ssvm/0.1.0-rc2)) 10 | 4. The [pallet-ssvm](https://github.com/second-state/pallet-ssvm) project creates a "pallet" (or substrate package) that uses rust-ssvm as the substrate node's EWASM engine. ([crates.io](https://crates.io/crates/pallet-ssvm/0.1.0-rc2)) 11 | 5. The [substrate-ssvm-node](https://github.com/second-state/substrate-ssvm-node) project (this project) provides a full ssvm-node that incorporates the pallet-ssvm. 12 | 13 | ## Getting Started 14 | 15 | ### Environment (Docker) 16 | 17 | We provide a docker image [secondstate/substrate-ssvm](https://hub.docker.com/r/secondstate/substrate-ssvm) for building and running the Substrate SSVM Node. 18 | 19 | ```bash 20 | > docker pull secondstate/substrate-ssvm 21 | ``` 22 | 23 | ### Build and Run Substrate SSVM Node 24 | 25 | ```bash 26 | > git clone https://github.com/second-state/substrate-ssvm-node.git 27 | > docker run -it --rm \ 28 | --name substrate-ssvm \ 29 | -v $(pwd):/root/node \ 30 | -w /root/node \ 31 | -p 9944:9944 \ 32 | secondstate/substrate-ssvm 33 | (docker) cd substrate-ssvm-node 34 | (docker) make init 35 | (docker) make build 36 | (docker) cargo run --release --bin ssvm-node -- --dev --ws-external 37 | ``` 38 | 39 | ### Interact with Substrate SSVM Node 40 | 41 | You can use the [Substrate Web Interface(Polkadot.js)](https://polkadot.js.org/apps) to connect with the node. 42 | 43 | We provide a [demo video](https://drive.google.com/open?id=1sR41n8fdLJD66Skcq8f7hyLRRQzSX9KF) to show that how polkadot.js interacts with our nodes. 44 | 45 | And the detailed steps can be found in this [tutorial](./docs/interact-using-web.md). 46 | -------------------------------------------------------------------------------- /doc/rust-setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | This page will guide you through the steps needed to prepare a computer for development with the 6 | Substrate Node Template. Since Substrate is built with 7 | [the Rust programming language](https://www.rust-lang.org/), the first thing you will need to do is 8 | prepare the computer for Rust development - these steps will vary based on the computer's operating 9 | system. Once Rust is configured, you will use its toolchains to interact with Rust projects; the 10 | commands for Rust's toolchains will be the same for all supported, Unix-based operating systems. 11 | 12 | ## Unix-Based Operating Systems 13 | 14 | Substrate development is easiest on Unix-based operating systems like macOS or Linux. The examples 15 | in the Substrate [Tutorials](https://substrate.dev/tutorials) and [Recipes](https://substrate.dev/recipes/) 16 | use Unix-style terminals to demonstrate how to interact with Substrate from the command line. 17 | 18 | ### macOS 19 | 20 | Open the Terminal application and execute the following commands: 21 | 22 | ```bash 23 | # Install Homebrew if necessary https://brew.sh/ 24 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 25 | 26 | # Make sure Homebrew is up-to-date, install openssl and cmake 27 | brew update 28 | brew install openssl cmake 29 | ``` 30 | 31 | ### Ubuntu/Debian 32 | 33 | Use a terminal shell to execute the following commands: 34 | 35 | ```bash 36 | sudo apt update 37 | # May prompt for location information 38 | sudo apt install -y cmake pkg-config libssl-dev git build-essential clang libclang-dev curl 39 | ``` 40 | 41 | ### Arch Linux 42 | 43 | Run these commands from a terminal: 44 | 45 | ```bash 46 | pacman -Syu --needed --noconfirm cmake gcc openssl-1.0 pkgconf git clang 47 | export OPENSSL_LIB_DIR="/usr/lib/openssl-1.0" 48 | export OPENSSL_INCLUDE_DIR="/usr/include/openssl-1.0" 49 | ``` 50 | 51 | ## Rust Developer Environment 52 | 53 | This project uses [`rustup`](https://rustup.rs/) to help manage the Rust toolchain. First install 54 | and configure `rustup`: 55 | 56 | ```bash 57 | # Install 58 | curl https://sh.rustup.rs -sSf | sh 59 | # Configure 60 | source ~/.cargo/env 61 | ``` 62 | 63 | Finally, configure the Rust toolchain to default to the latest stable version: 64 | 65 | ```bash 66 | rustup default stable 67 | ``` 68 | 69 | ## Build the Project 70 | 71 | Now that the standard Rust environment is configured, use the 72 | [included Makefile](../README.md#makefile) to install the project-specific toolchains and build the 73 | project. 74 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.2" 2 | 3 | services: 4 | dev: 5 | container_name: node-template 6 | image: paritytech/ci-linux:974ba3ac-20201006 7 | working_dir: /var/www/node-template 8 | ports: 9 | - "9944:9944" 10 | environment: 11 | - CARGO_HOME=/var/www/node-template/.cargo 12 | volumes: 13 | - .:/var/www/node-template 14 | - type: bind 15 | source: ./.local 16 | target: /root/.local 17 | command: bash -c "cargo build --release && ./target/release/node-template --dev --ws-external" 18 | -------------------------------------------------------------------------------- /docs/erc20/erc20.hex: -------------------------------------------------------------------------------- 1 | 0061736d0100000001460a6000017e60047e7f7f7f017f60037f7f7f0060017f0060027f7f0060000060057f7e7e7e7e0060067f7e7e7e7e7f0060097f7e7e7e7e7e7e7e7e0060077e7e7e7e7e7e7e0002c7010908657468657265756d0a6765744761734c656674000008657468657265756d0a63616c6c537461746963000108657468657265756d0e72657475726e44617461436f7079000208657468657265756d0c67657443616c6c56616c7565000308657468657265756d06726576657274000408657468657265756d0b73746f726167654c6f6164000408657468657265756d0c73746f7261676553746f7265000408657468657265756d0967657443616c6c6572000308657468657265756d0666696e6973680004030908060207080905030505030100020608017f0141809f050b071102066d656d6f72790200046d61696e00100ab61f088d0300200041186a20014228884280fe03832001421888428080fc0783200142088842808080f80f8320014208864280808080f01f832001421886428080808080e03f83200142288642808080808080c0ff00832001423886848484848484200142388884370300200020024228884280fe03832002421888428080fc0783200242088842808080f80f8320024208864280808080f01f832002421886428080808080e03f83200242288642808080808080c0ff00832002423886848484848484200242388884370310200020034228884280fe03832003421888428080fc0783200342088842808080f80f8320034208864280808080f01f832003421886428080808080e03f83200342288642808080808080c0ff00832003423886848484848484200342388884370308200020044228884280fe03832004421888428080fc0783200442088842808080f80f8320044208864280808080f01f832004421886428080808080e03f83200442288642808080808080c0ff008320044238868484848484842004423888843703000b2b00200204400340200020012d00003a0000200041016a2100200141016a21012002417f6a22020d000b0b0bae0101017f230041e0006b220624002006420037035020064200370348200642808080c8003e02581000200641c8006a20052001a710011a200641286a410041201002200641086a2006290328200641306a290300200641386a290300200641406b2903001009200641106a2903002101200641186a290300210220062903082103200041186a200641206a290300370300200020023703102000200137030820002003370300200641e0006a24000bdd03010c7f230041106b220924002009220e100302402009290300200941086a290300844200510440200941606a220c220a2400200941786a220f2004370300200941706a22102003370300200941686a22112002370300200c2001370300200a220941606a220d220a2400200941786a22122008370300200941706a22132007370300200941686a22142006370300200d2005370300200a41606a2209220a2400200a220b41606a220a2400200a200c2903002207200d2903007c2208370300200b41686a2008200754220cad2011290300220120142903007c7c2202370300200b41706a2010290300220320132903007c2206200c20022001542001200251220d1bad7c2204370300200b41786a2004200654ad2006200354ad200f290300220520122903007c7c7c2206370300200820075a200220015a200d1b200420035a200620055a20052006511b2003200485200520068584501b450d012009200a290300370300200941186a220b200a41186a2903003703002009200a41106a2903003703102009200a41086a29030037030820002009290300370300200041186a200b2903003703002000200941106a2903003703102000200941086a290300370308200e41106a24000f0b41800841171004000b419708411b1004000ba90e020f7f057e23004190046b22082400200822074180046a1003024020072903800420074188046a290300844200510440200841606a220a220d2400200841686a22092001370300200a2000370300200841706a220c20023e0200200d220841606a220d220b2400200841786a2006370300200841706a2005370300200841686a2004370300200d20033703002009290300200a290300200c35020084844200510d01200741e0036a41800c290300220041880c290300220141900c290300220241980c29030022031009200741e8036a2903002104200741f0036a2903002105200741f8036a290300210620072903e0032116200b220841606a220c22092400200941606a220b220e2400200841786a2006370300200841706a2005370300200841686a2004370300200c2016370300200c200b1005200741c0036a200b290300200941686a290300200941706a290300200941786a2903001009200741a0036a20072903c003200741c8036a290300200741d0036a290300200741d8036a290300200d290300200d41086a220f290300200d41106a2210290300200d41186a2211290300100c20074180036a2000200120022003100920074188036a290300210020074190036a290300210120074198036a29030021022007290380032103200741e0026a20072903a003200741a8036a290300200741b0036a290300200741b8036a2903001009200741e8026a2903002104200741f0026a2903002105200741f8026a290300210620072903e0022116200e220841606a220c22092400200941606a220b220e2400200941786a2006370300200941706a2005370300200941686a2004370300200b2016370300200841786a2002370300200841706a2001370300200841686a2000370300200c2003370300200c200b1006200741c0026a41800a290300220041880a290300220141900a290300220241980a29030022031009200741c8026a2903002104200741d0026a2903002105200741d8026a290300210620072903c0022116200741a0026a200a290300200a41086a220b290300200a41106a221235020042001009200741a8026a2903002117200741b0026a2903002118200741b8026a290300211920072903a002211a200e220841406a2209220c2400200841786a2006370300200841706a2005370300200841686a2004370300200841606a2016370300200841586a2019370300200841506a2018370300200841486a20173703002009201a370300200c220841606a220c220e240020074180026a42c0004200420042002009100b20074188026a290300210420074190026a29030021052007290380022106200841786a221320074198026a290300370300200841706a22142005370300200841686a22152004370300200c2006370300200741e0016a20002001200220031009200741e8016a2903002100200741f0016a2903002101200741f8016a290300210220072903e0012103200741c0016a200a290300200b290300201235020042001009200741c8016a2903002104200741d0016a2903002105200741d8016a290300210620072903c0012116200e220841406a220a22092400200841786a2002370300200841706a2001370300200841686a2000370300200841606a2003370300200841586a2006370300200841506a2005370300200841486a2004370300200a20163703002009220841606a2209220b2400200741a0016a42c000420042004200200a100b200741a8016a2903002100200741b0016a290300210120072903a0012102200841786a200741b8016a2903002203370300200841706a2001370300200841686a20003703002009200237030020074180016a2002200020012003100920074188016a290300210020074190016a290300210120074198016a29030021022007290380012103200b220841606a2209220a2400200a41606a220b220e2400200841786a2002370300200841706a2001370300200841686a2000370300200920033703002009200b1005200741e0006a200b290300200a41686a290300200a41706a290300200a41786a2903001009200741406b2007290360200741e8006a290300200741f0006a290300200741f8006a290300200d290300200f29030020102903002011290300100c200741206a200c2903002015290300201429030020132903001009200741286a2903002100200741306a2903002101200741386a29030021022007290320210320072007290340200741c8006a290300200741d0006a290300200741d8006a2903001009200741086a2903002104200741106a2903002105200741186a290300210620072903002116200e220841606a220d220a2400200a41606a22092400200a41786a2006370300200a41706a2005370300200a41686a200437030020092016370300200841786a2002370300200841706a2001370300200841686a2000370300200d2003370300200d2009100620074190046a24000f0b41a01041171004000b41b710411f1004000be807020a7f087e230041b0016b220024002000220141a0016a100320012903a001200141a8016a29030084420051044020014180016a41800e29030041880e29030041900e29030041980e290300100920014188016a290300210a20014190016a290300210b20014198016a290300210c200129038001210d200041606a220322022400200041786a2204200c370300200041706a2205200b370300200041686a2206200a3703002003200d3703002002220041606a220222072400200241ed10410e100a2002290300210a200041686a2208290300210b200041706a2209290300210c200141e0006a421c4200420042001009200141e8006a290300210d200141f0006a290300210e2001290360210f200041786a22002000290300200141f8006a2903008422103703002009200c200e84220c3703002008200b200d84220b3703002002200a200f84220a3703002003290300210d2006290300210e2005290300210f200429030021112007220041606a220322022400200241606a220422052400200241786a2010370300200241706a200c370300200241686a200b3703002004200a370300200041786a2011370300200041706a200f370300200041686a200e3703002003200d370300200320041006200141406b4180102903004188102903004190102903004198102903001009200141c8006a290300210a200141d0006a290300210b200141d8006a290300210c2001290340210d2005220041606a220322022400200041786a2204200c370300200041706a2205200b370300200041686a2206200a3703002003200d3703002002220041606a220222072400200241fb104103100a2002290300210a200041686a2208290300210b200041706a2209290300210c200141206a42064200420042001009200141286a290300210d200141306a290300210e2001290320210f200041786a22002000290300200141386a2903008422103703002009200c200e84220c3703002008200b200d84220b3703002002200a200f84220a3703002003290300210d2006290300210e2005290300210f200429030021112007220041606a220322022400200241606a220422052400200241786a2010370300200241706a200c370300200241686a200b3703002004200a370300200041786a2011370300200041706a200f370300200041686a200e3703002003200d3703002003200410062005220041606a2202240020021007200142002002290300220a422086200a422088200041686a290300220a42208684200041706a350200422086200a4220888410092001290300200141086a290300200141106a35020042e807420042004200100d200141b0016a24000f0b41d61041171004000b2b00200041186a42003703002000420037031020004200370308200042fd8d01370300200041fe103602200b2901017f230041306b22002400100e200041086a100f200028022820002802081008200041306a24000b0bb18f0105004180080b3246756e6374696f6e206973206e6f742070617961626c65536166654d6174683a206164646974696f6e206f766572666c6f770041800c0b01020041800e0b0103004180100b01040041a0100bdb8e0146756e6374696f6e206973206e6f742070617961626c6545524332303a206d696e7420746f20746865207a65726f206164647265737346756e6374696f6e206973206e6f742070617961626c654552433230546f6b656e44656d6f4554440061736d0100000001770f6000017e60047e7f7f7f017f60037f7f7f0060017f0060027f7f006000017f60000060057f7e7e7e7e0060067f7e7e7e7e7f0060097f7e7e7e7e7e7e7e7e0060047f7e7e7e00600a7e7e7e7e7e7e7e7e7e7e0060077e7e7e7e7e7e7e017f60077f7e7e7e7e7e7e00600a7e7e7e7e7e7e7e7e7e7e017f02fa010b08657468657265756d0a6765744761734c656674000008657468657265756d0a63616c6c537461746963000108657468657265756d0e72657475726e44617461436f7079000208657468657265756d0c67657443616c6c56616c7565000308657468657265756d06726576657274000408657468657265756d0b73746f726167654c6f6164000408657468657265756d0c73746f7261676553746f7265000408657468657265756d0967657443616c6c6572000308657468657265756d0f67657443616c6c4461746153697a65000508657468657265756d0c63616c6c44617461436f7079000208657468657265756d0666696e69736800040313120702080909030a0b0c0d0b0c0e0c0c03030605030100020608017f0141d095040b071102066d656d6f72790200046d61696e001c0a8e8601128d0300200041186a20014228884280fe03832001421888428080fc0783200142088842808080f80f8320014208864280808080f01f832001421886428080808080e03f83200142288642808080808080c0ff00832001423886848484848484200142388884370300200020024228884280fe03832002421888428080fc0783200242088842808080f80f8320024208864280808080f01f832002421886428080808080e03f83200242288642808080808080c0ff00832002423886848484848484200242388884370310200020034228884280fe03832003421888428080fc0783200342088842808080f80f8320034208864280808080f01f832003421886428080808080e03f83200342288642808080808080c0ff00832003423886848484848484200342388884370308200020044228884280fe03832004421888428080fc0783200442088842808080f80f8320044208864280808080f01f832004421886428080808080e03f83200442288642808080808080c0ff008320044238868484848484842004423888843703000b2b00200204400340200020012d00003a0000200041016a2100200141016a21012002417f6a22020d000b0b0bae0101017f230041e0006b220624002006420037035020064200370348200642808080c8003e02581000200641c8006a20052001a710011a200641286a410041201002200641086a2006290328200641306a290300200641386a290300200641406b290300100b200641106a2903002101200641186a290300210220062903082103200041186a200641206a290300370300200020023703102000200137030820002003370300200641e0006a24000bdd03010c7f230041106b220924002009220e100302402009290300200941086a290300844200510440200941606a220c220a2400200941786a220f2004370300200941706a22102003370300200941686a22112002370300200c2001370300200a220941606a220d220a2400200941786a22122008370300200941706a22132007370300200941686a22142006370300200d2005370300200a41606a2209220a2400200a220b41606a220a2400200a200c2903002207200d2903007c2208370300200b41686a2008200754220cad2011290300220120142903007c7c2202370300200b41706a2010290300220320132903007c2206200c20022001542001200251220d1bad7c2204370300200b41786a2004200654ad2006200354ad200f290300220520122903007c7c7c2206370300200820075a200220015a200d1b200420035a200620055a20052006511b2003200485200520068584501b450d012009200a290300370300200941186a220b200a41186a2903003703002009200a41106a2903003703102009200a41086a29030037030820002009290300370300200041186a200b2903003703002000200941106a2903003703102000200941086a290300370308200e41106a24000f0b41800841171004000b419708411b1004000b8504010b7f230041106b220924002009220f100302402009290300200941086a290300844200510440200941606a220a220b2400200941786a220c2004370300200941706a220d2003370300200941686a22102002370300200a2001370300200b220941606a220b220e2400200941786a22112008370300200941706a22122007370300200941686a22132006370300200b2005370300200e41606a2209220e2400200b290300200a2903005820132903002201201029030022025820012002511b20122903002203200d29030022045820112903002201200c29030022025820012002511b2003200485200120028584501b450d01200e220c41606a220d2400200d200a2903002203200b29030022047d220137030020092001370300200c41686a200a41086a2903002201200b41086a29030022027d2003200454220dad7d220337030020092003370308200c41706a200a41106a2903002203200b41106a29030022047d2205200d200120025420012002511bad22017d220237030020092002370310200c41786a200a41186a290300200b41186a2903007d2003200454ad7d2005200154ad7d2201370300200941186a220a200137030020002009290300370300200041186a200a2903003703002000200941106a2903003703102000200941086a290300370308200f41106a24000f0b41b20841171004000b41c908411e1004000bea0202077f047e230041d0006b220224002002220141406b10032001290340200141c8006a2903008442005104402002220541606a220222032400200141206a41800e29030041880e29030041900e29030041980e290300100b200141286a2903002108200141306a2903002109200141386a290300210a2001290320210b200341606a220622042400200441606a22072400200341786a200a370300200341706a2009370300200341686a20083703002006200b37030020062007100520012007290300200441686a290300200441706a290300200441786a290300100b200141086a2903002108200141106a29030021092001290300210a200541786a200141186a290300370300200541706a2009370300200541686a20083703002002200a37030020002002290300370300200041186a200241186a2903003703002000200241106a2903003703102000200241086a290300370308200141d0006a24000f0b41a01241171004000bc10502077f057e230041b0016b220524002005220441a0016a100320042903a001200441a8016a290300844200510440200541606a220622092400200541686a2207200237030020062001370300200541706a220520033e0200200941606a220a2208240020044180016a41800a29030041880a29030041900a29030041980a290300100b20044188016a290300210120044190016a290300210220044198016a2903002103200429038001210b200441e0006a2006290300200729030020053502004200100b200441e8006a290300210c200441f0006a290300210d200441f8006a290300210e2004290360210f2008220541406a220622072400200541786a2003370300200541706a2002370300200541686a2001370300200541606a200b370300200541586a200e370300200541506a200d370300200541486a200c3703002006200f3703002007220541606a220722082400200441406b42c0004200420042002006100d200441c8006a2903002101200441d0006a290300210220042903402103200541786a200441d8006a290300220b370300200541706a2002370300200541686a200137030020072003370300200441206a200320012002200b100b200441286a2903002101200441306a2903002102200441386a29030021032004290320210b2008220541606a220722062400200641606a22082400200541786a2003370300200541706a2002370300200541686a20013703002007200b37030020072008100520042008290300200641686a290300200641706a290300200641786a290300100b200441106a2903002101200441086a290300210220042903002103200941786a200441186a290300220b370300200941686a2002370300200a2003370300200941706a2001370300200041186a200b370300200020013703102000200237030820002003370300200441b0016a24000f0b41b71241171004000bf61302107f027e230041d0056b220b2400200b220a41c0056a100302400240200a2903c005200a41c8056a290300844200510440200b41606a220c220e2400200b41686a22102001370300200c2000370300200b41706a221420023e0200200e220b41606a220e220f2400200b41686a2004370300200e2003370300200b41706a20053e0200200f220b41606a220f220d2400200b41786a2009370300200b41706a2008370300200b41686a2007370300200f20063703002010290300200c290300201435020084844200510d01200e41086a2214290300200e290300200e41106a221035020084844200510d02200a41a0056a41800a290300220041880a290300220141900a290300220241980a2903002203100b200a41a8056a2903002104200a41b0056a2903002105200a41b8056a2903002106200a2903a0052107200a4180056a200c290300200c41086a2212290300200c41106a22133502004200100b200a4188056a2903002108200a4190056a2903002109200a4198056a290300211a200a29038005211b200d220b41406a220d22112400200b41786a2006370300200b41706a2005370300200b41686a2004370300200b41606a2007370300200b41586a201a370300200b41506a2009370300200b41486a2008370300200d201b3703002011220b41606a221122152400200a41e0046a42c000420042004200200d100d200a41e8046a2903002104200a41f0046a2903002105200a2903e0042106200b41786a2216200a41f8046a290300370300200b41706a22172005370300200b41686a2218200437030020112006370300200a41c0046a2000200120022003100b200a41c8046a2903002104200a41d0046a2903002105200a41d8046a2903002106200a2903c0042107200a41a0046a200c290300201229030020133502004200100b200a41a8046a2903002108200a41b0046a2903002109200a41b8046a290300211a200a2903a004211b2015220b41406a220c220d2400200b41786a2006370300200b41706a2005370300200b41686a2004370300200b41606a2007370300200b41586a201a370300200b41506a2009370300200b41486a2008370300200c201b370300200d220b41606a220d22122400200a4180046a42c000420042004200200c100d200a4188046a2903002104200a4190046a2903002105200a290380042106200b41786a200a4198046a2903002207370300200b41706a2005370300200b41686a2004370300200d2006370300200a41e0036a2006200420052007100b200a41e8036a2903002104200a41f0036a2903002105200a41f8036a2903002106200a2903e00321072012220b41606a220d220c2400200c41606a221222132400200b41786a2006370300200b41706a2005370300200b41686a2004370300200d2007370300200d20121005200a41c0036a2012290300200c41686a290300200c41706a290300200c41786a290300100b200a41a0036a200a2903c003200a41c8036a290300200a41d0036a290300200a41d8036a290300200f290300200f41086a2212290300200f41106a2215290300200f41186a2219290300100f200a4180036a2011290300201829030020172903002016290300100b200a4188036a2903002104200a4190036a2903002105200a4198036a2903002106200a290380032107200a41e0026a200a2903a003200a41a8036a290300200a41b0036a290300200a41b8036a290300100b200a41e8026a2903002108200a41f0026a2903002109200a41f8026a290300211a200a2903e002211b2013220b41606a220d220c2400200c41606a221122132400200c41786a201a370300200c41706a2009370300200c41686a20083703002011201b370300200b41786a2006370300200b41706a2005370300200b41686a2004370300200d2007370300200d20111006200a41c0026a2000200120022003100b200a41c8026a2903002104200a41d0026a2903002105200a41d8026a2903002106200a2903c0022107200a41a0026a200e290300201429030020103502004200100b200a41a8026a2903002108200a41b0026a2903002109200a41b8026a290300211a200a2903a002211b2013220b41406a220c220d2400200b41786a2006370300200b41706a2005370300200b41686a2004370300200b41606a2007370300200b41586a201a370300200b41506a2009370300200b41486a2008370300200c201b370300200d220b41606a220d22112400200a4180026a42c000420042004200200c100d200a4188026a2903002104200a4190026a2903002105200a290380022106200b41786a2213200a4198026a290300370300200b41706a22162005370300200b41686a22172004370300200d2006370300200a41e0016a2000200120022003100b200a41e8016a2903002100200a41f0016a2903002101200a41f8016a2903002102200a2903e0012103200a41c0016a200e290300201429030020103502004200100b200a41c8016a2903002104200a41d0016a2903002105200a41d8016a2903002106200a2903c00121072011220b41406a220c220e2400200b41786a2002370300200b41706a2001370300200b41686a2000370300200b41606a2003370300200b41586a2006370300200b41506a2005370300200b41486a2004370300200c2007370300200e220b41606a220e22102400200a41a0016a42c000420042004200200c100d200a41a8016a2903002100200a41b0016a2903002101200a2903a0012102200b41786a200a41b8016a2903002203370300200b41706a2001370300200b41686a2000370300200e2002370300200a4180016a2002200020012003100b200a4188016a2903002100200a4190016a2903002101200a4198016a2903002102200a2903800121032010220b41606a220e220c2400200c41606a221022142400200b41786a2002370300200b41706a2001370300200b41686a2000370300200e2003370300200e20101005200a41e0006a2010290300200c41686a290300200c41706a290300200c41786a290300100b200a41406b200a290360200a41e8006a290300200a41f0006a290300200a41f8006a290300200f290300201229030020152903002019290300100e200a41206a200d290300201729030020162903002013290300100b200a41286a2903002100200a41306a2903002101200a41386a2903002102200a2903202103200a200a290340200a41c8006a290300200a41d0006a290300200a41d8006a290300100b200a41086a2903002104200a41106a2903002105200a41186a2903002106200a29030021072014220b41606a220e220c2400200c41606a220f2400200c41786a2006370300200c41706a2005370300200c41686a2004370300200f2007370300200b41786a2002370300200b41706a2001370300200b41686a2000370300200e2003370300200e200f1006200a41d0056a24000f0b41ce1241171004000b41e51241251004000b418a1341231004000bb202010b7f230041306b220724002007220841206a10032007290320200741286a290300844200510440200741606a220b220a2400200741686a220d2001370300200b2000370300200741706a220e20023e0200200a220741606a220a22092400200741786a220f2006370300200741706a22102005370300200741686a22112004370300200a2003370300200941706a220722092400200941606a220c2400200c100720084200200c29030022004220862000422088200941686a290300220042208684200941706a350200422086200042208884100b2008290300200841086a290300200841106a350200200b290300200d290300200e350200200a29030020112903002010290300200f2903001012200741013a000020072d00002107200841306a240020070f0b41ad1341171004000bac08020a7f027e23004190026b22082400200822074180026a100320072903800220074188026a290300844200510440200841606a2209220c2400200841686a220a200237030020092001370300200841706a220d20033e0200200c220841606a220b220c2400200841686a220e2005370300200b2004370300200841706a220f20063e0200200c41606a221022082400200741e0016a41800c29030041880c29030041900c29030041980c290300100b200741e8016a2903002101200741f0016a2903002102200741f8016a290300210320072903e0012104200741c0016a2009290300200a290300200d3502004200100b200741c8016a2903002105200741d0016a2903002106200741d8016a290300211120072903c0012112200841406a2209220a2400200841786a2003370300200841706a2002370300200841686a2001370300200841606a2004370300200841586a2011370300200841506a2006370300200841486a200537030020092012370300200a220841606a220a220d2400200741a0016a42c0004200420042002009100d200741a8016a2903002101200741b0016a290300210220072903a0012103200841786a200741b8016a2903002204370300200841706a2002370300200841686a2001370300200a200337030020074180016a2003200120022004100b20074188016a290300210120074190016a290300210220074198016a29030021032007290380012104200741e0006a200b290300200e290300200f3502004200100b200741e8006a2903002105200741f0006a2903002106200741f8006a290300211120072903602112200d220841406a2209220b2400200841786a2003370300200841706a2002370300200841686a2001370300200841606a2004370300200841586a2011370300200841506a2006370300200841486a200537030020092012370300200b220841606a220b220a2400200741406b42c0004200420042002009100d200741c8006a2903002101200741d0006a290300210220072903402103200841786a200741d8006a2903002204370300200841706a2002370300200841686a2001370300200b2003370300200741206a2003200120022004100b200741286a2903002101200741306a2903002102200741386a290300210320072903202104200a220841606a220b22092400200941606a220a2400200841786a2003370300200841706a2002370300200841686a2001370300200b2004370300200b200a10052007200a290300200941686a290300200941706a290300200941786a290300100b200741106a2903002101200741086a290300210220072903002103200c41786a200741186a2903002204370300200c41686a200237030020102003370300200c41706a2001370300200041186a200437030020002001370310200020023703082000200337030020074190026a24000f0b41c41341171004000b820901097f23004190026b220b2400200b220a4180026a100302400240200a29038002200a4188026a290300844200510440200b220c41606a220b220e2400200c41686a220f2001370300200b2000370300200c41706a221120023e0200200e41606a220c220d2400200e41686a2004370300200c2003370300200e41706a20053e0200200d41606a220e22102400200d41786a2009370300200d41706a2008370300200d41686a2007370300200e2006370300200f290300200b290300201135020084844200510d01200c41086a2211290300200c290300200c41106a220f35020084844200510d02200a41e0016a41800c29030041880c29030041900c29030041980c290300100b200a41e8016a2903002100200a41f0016a2903002101200a41f8016a2903002102200a2903e0012103200a41c0016a200b290300200b41086a290300200b41106a3502004200100b200a41c8016a2903002104200a41d0016a2903002105200a41d8016a2903002106200a2903c00121072010220b41406a220d22102400200b41786a2002370300200b41706a2001370300200b41686a2000370300200b41606a2003370300200b41586a2006370300200b41506a2005370300200b41486a2004370300200d20073703002010220b41606a221022122400200a41a0016a42c000420042004200200d100d200a41a8016a2903002100200a41b0016a2903002101200a2903a0012102200b41786a200a41b8016a2903002203370300200b41706a2001370300200b41686a200037030020102002370300200a4180016a2002200020012003100b200a4188016a2903002100200a4190016a2903002101200a4198016a2903002102200a290380012103200a41e0006a200c2903002011290300200f3502004200100b200a41e8006a2903002104200a41f0006a2903002105200a41f8006a2903002106200a29036021072012220b41406a220c220d2400200b41786a2002370300200b41706a2001370300200b41686a2000370300200b41606a2003370300200b41586a2006370300200b41506a2005370300200b41486a2004370300200c2007370300200d220b41606a220d220f2400200a41406b42c000420042004200200c100d200a41c8006a2903002100200a41d0006a2903002101200a2903402102200b41786a200a41d8006a2903002203370300200b41706a2001370300200b41686a2000370300200d2002370300200a41206a2002200020012003100b200a41286a2903002100200a41306a2903002101200a41386a2903002102200a2903202103200a200e290300200e41086a290300200e41106a290300200e41186a290300100b200a41086a2903002104200a41106a2903002105200a41186a2903002106200a2903002107200f220b41606a220e220c2400200c41606a220d2400200c41786a2006370300200c41706a2005370300200c41686a2004370300200d2007370300200b41786a2002370300200b41706a2001370300200b41686a2000370300200e2003370300200e200d1006200a4190026a24000f0b41db1341171004000b41f21341241004000b41961441221004000bb202010b7f230041306b220724002007220841206a10032007290320200741286a290300844200510440200741606a220b220a2400200741686a220d2001370300200b2000370300200741706a220e20023e0200200a220741606a220a22092400200741786a220f2006370300200741706a22102005370300200741686a22112004370300200a2003370300200941706a220722092400200941606a220c2400200c100720084200200c29030022004220862000422088200941686a290300220042208684200941706a350200422086200042208884100b2008290300200841086a290300200841106a350200200b290300200d290300200e350200200a29030020112903002010290300200f2903001015200741013a000020072d00002107200841306a240020070f0b41b81441171004000b820b020d7f047e230041f0026b220b2400200b220a41e0026a1003200a2903e002200a41e8026a290300844200510440200b220c41606a220b220f2400200c41686a220d2001370300200b2000370300200c41706a220c20023e0200200f41606a220e22112400200f41686a22102004370300200e2003370300200f41706a221220053e02002011220f41606a221122132400200f41786a22152009370300200f41706a22162008370300200f41686a220f200737030020112006370300201341706a221322142400200b290300200d290300200c350200200e290300201029030020123502002011290300200f290300201629030020152903001012200d2903002103200b2903002104200c35020021052014220e41606a22102212240020101007200a41c0026a4200201029030022004220862000422088200e41686a290300220042208684200e41706a350200422086200042208884100b200a41c8026a2903002106200a41d0026a3502002107200a2903c0022108200a41a0026a41800c29030041880c29030041900c29030041980c290300100b200a41a8026a2903002100200a41b0026a2903002101200a41b8026a2903002102200a2903a0022109200a4180026a200b290300200d290300200c3502004200100b200a4188026a2903002117200a4190026a2903002118200a4198026a2903002119200a29038002211a2012220b41406a220d220c2400200b41786a2002370300200b41706a2001370300200b41686a2000370300200b41606a2009370300200b41586a2019370300200b41506a2018370300200b41486a2017370300200d201a370300200c220b41606a220c220e2400200a41e0016a42c000420042004200200d100d200a41e8016a2903002100200a41f0016a2903002101200a2903e0012102200b41786a2210200a41f8016a290300370300200b41706a22122001370300200b41686a22142000370300200c2002370300200e220b41606a220d220e2400200d1007200a41c0016a4200200d29030022004220862000422088200b41686a290300220042208684200b41706a350200422086200042208884100b200a41a0016a200c290300201429030020122903002010290300100b200a41a8016a2903002100200a41b0016a2903002101200a41b8016a2903002102200a2903a0012109200a4180016a200a2903c001200a41c8016a290300200a41d0016a3502004200100b200a4188016a2903002117200a4190016a2903002118200a4198016a2903002119200a29038001211a200e220b41406a220d220c2400200b41786a2002370300200b41706a2001370300200b41686a2000370300200b41606a2009370300200b41586a2019370300200b41506a2018370300200b41486a2017370300200d201a370300200c220b41606a220c220e2400200a41e0006a42c000420042004200200d100d200a41e8006a2903002100200a41f0006a2903002101200a2903602102200b41786a200a41f8006a2903002209370300200b41706a2001370300200b41686a2000370300200c2002370300200a41406b2002200020012009100b200a41c8006a2903002100200a41d0006a2903002101200a41d8006a2903002102200a2903402109200e220b41606a220c220d2400200d41606a220e2400200b41786a2002370300200b41706a2001370300200b41686a2000370300200c2009370300200c200e1005200a41206a200e290300200d41686a290300200d41706a290300200d41786a290300100b200a200a290320200a41286a290300200a41306a290300200a41386a2903002011290300200f29030020162903002015290300100f200420032005200820062007200a290300200a41086a290300200a41106a290300200a41186a2903001015201341013a0000200a41f0026a240041010f0b41cf1441171004000b900a020d7f077e230041f0026b220824002008220741e0026a100320072903e002200741e8026a290300844200510440200841606a2209220e2400200841686a220b200137030020092000370300200841706a220c20023e0200200e220841606a220e220a2400200841786a220f2006370300200841706a22102005370300200841686a22112004370300200e2003370300200a41706a221222082400200841606a220a220d2400200a1007200741c0026a4200200a29030022004220862000422088200841686a290300220042208684200841706a350200422086200042208884100b200b290300210320092903002104200c3502002105200741c8026a2903002106200741d0026a350200211920072903c002211a200d220841606a220a220d2400200a1007200741a0026a4200200a29030022004220862000422088200841686a290300220042208684200841706a350200422086200042208884100b20074180026a41800c29030041880c29030041900c29030041980c290300100b20074188026a290300210020074190026a290300210120074198026a29030021022007290380022114200741e0016a20072903a002200741a8026a290300200741b0026a3502004200100b200741e8016a2903002115200741f0016a2903002116200741f8016a290300211720072903e0012118200d220841406a220a220d2400200841786a2002370300200841706a2001370300200841686a2000370300200841606a2014370300200841586a2017370300200841506a2016370300200841486a2015370300200a2018370300200d220841606a220d22132400200741c0016a42c000420042004200200a100d200741c8016a2903002100200741d0016a290300210120072903c0012102200841786a200741d8016a2903002214370300200841706a2001370300200841686a2000370300200d2002370300200741a0016a2002200020012014100b200741a8016a2903002100200741b0016a2903002101200741b8016a290300210220072903a001211420074180016a2009290300200b290300200c3502004200100b20074188016a290300211520074190016a290300211620074198016a290300211720072903800121182013220841406a2209220b2400200841786a2002370300200841706a2001370300200841686a2000370300200841606a2014370300200841586a2017370300200841506a2016370300200841486a201537030020092018370300200b220841606a220b220c2400200741e0006a42c0004200420042002009100d200741e8006a2903002100200741f0006a290300210120072903602102200841786a200741f8006a2903002214370300200841706a2001370300200841686a2000370300200b2002370300200741406b2002200020012014100b200741c8006a2903002100200741d0006a2903002101200741d8006a290300210220072903402114200c220841606a220b22092400200941606a220c2400200841786a2002370300200841706a2001370300200841686a2000370300200b2014370300200b200c1005200741206a200c290300200941686a290300200941706a290300200941786a290300100b20072007290320200741286a290300200741306a290300200741386a290300200e29030020112903002010290300200f290300100e201a200620192004200320052007290300200741086a290300200741106a290300200741186a2903001015201241013a0000200741f0026a240041010f0b41e61441171004000b900a020d7f077e230041f0026b220824002008220741e0026a100320072903e002200741e8026a290300844200510440200841606a2209220e2400200841686a220b200137030020092000370300200841706a220c20023e0200200e220841606a220e220a2400200841786a220f2006370300200841706a22102005370300200841686a22112004370300200e2003370300200a41706a221222082400200841606a220a220d2400200a1007200741c0026a4200200a29030022004220862000422088200841686a290300220042208684200841706a350200422086200042208884100b200b290300210320092903002104200c3502002105200741c8026a2903002106200741d0026a350200211920072903c002211a200d220841606a220a220d2400200a1007200741a0026a4200200a29030022004220862000422088200841686a290300220042208684200841706a350200422086200042208884100b20074180026a41800c29030041880c29030041900c29030041980c290300100b20074188026a290300210020074190026a290300210120074198026a29030021022007290380022114200741e0016a20072903a002200741a8026a290300200741b0026a3502004200100b200741e8016a2903002115200741f0016a2903002116200741f8016a290300211720072903e0012118200d220841406a220a220d2400200841786a2002370300200841706a2001370300200841686a2000370300200841606a2014370300200841586a2017370300200841506a2016370300200841486a2015370300200a2018370300200d220841606a220d22132400200741c0016a42c000420042004200200a100d200741c8016a2903002100200741d0016a290300210120072903c0012102200841786a200741d8016a2903002214370300200841706a2001370300200841686a2000370300200d2002370300200741a0016a2002200020012014100b200741a8016a2903002100200741b0016a2903002101200741b8016a290300210220072903a001211420074180016a2009290300200b290300200c3502004200100b20074188016a290300211520074190016a290300211620074198016a290300211720072903800121182013220841406a2209220b2400200841786a2002370300200841706a2001370300200841686a2000370300200841606a2014370300200841586a2017370300200841506a2016370300200841486a201537030020092018370300200b220841606a220b220c2400200741e0006a42c0004200420042002009100d200741e8006a2903002100200741f0006a290300210120072903602102200841786a200741f8006a2903002214370300200841706a2001370300200841686a2000370300200b2002370300200741406b2002200020012014100b200741c8006a2903002100200741d0006a2903002101200741d8006a290300210220072903402114200c220841606a220b22092400200941606a220c2400200841786a2002370300200841706a2001370300200841686a2000370300200b2014370300200b200c1005200741206a200c290300200941686a290300200941706a290300200941786a290300100b20072007290320200741286a290300200741306a290300200741386a290300200e29030020112903002010290300200f290300100f201a200620192004200320052007290300200741086a290300200741106a290300200741186a2903001015201241013a0000200741f0026a240041010f0b41fd1441171004000bb309020d7f137e230041d0016b220224002002220141c0016a100320012903c001200141c8016a290300844200510440200241506a220722022400200141a0016a418010290300418810290300419010290300419810290300100b200141a8016a2903002114200141b0016a2903002111200141b8016a290300211520012903a0012112200241606a220422032400200341606a220522082400200241786a2015370300200241706a2011370300200241686a2014370300200420123703002004200510052005290300210e200341686a290300210f200341706a2903002113200341786a29030021102008220241606a220322042400200241786a2010370300200241706a2013370300200241686a200f3703002003200e3703000240201042808080808080808001835004402001200e200f20132010100b20012903002110200441606a2206240020062003201042fe01834201882218a7100c420021194200211a420021170c010b20014180016a200e200f20132010100b20014198016a290300210e20014190016a290300210f20014188016a2903002116200129038001211b2004220241606a220322042400200241786a2015370300200241706a2011370300200241686a201437030020032012370300200141e0006a42204200420042002003100d200141f8006a290300211c200141f0006a2903002113200141e8006a290300211420012903602110200441606a2202220324002003201b4201882211a7410f6a4170716b220622092400024020112016423f868422184220544100200f423f862016420188842219501b200e4201882217420053200e423f86200f42018884221a201784501b450440200141c8006a210a200141d0006a210b2018211b20192115201a211d2017210f200621030340200141406b201020142013201c100b200a290300210e200b290300211120012903402112200241186a200141d8006a290300370300200220113703102002200e370308200220123703002002200310052015201b42607c2212201b542204ad7c427f7c220e2015512105200e2015542108201d427f7c2220201d54210c201c2013201042017c2216201054220d2014200dad7c221e201454201620105a1bad7c221f201354ad7c211c200341206a21032012211b200e211520202004200820051bad7c2211211d20162110201e2114201f21132012421f56200e420052200e501b20114200522011202054ad200f200cad7c7c427f7c220f420055200f501b200f201184501b0d000b0c010b201821122019210e201a21112017210f20062103201021162014211e2013211f0b2012504100200e501b200f420053200f201184501b0d002009220241606a220422052400200141206a2016201e201f201c100b200141286a2903002110200141306a290300210e2001290320210f200241786a200141386a290300370300200241706a200e370300200241686a20103703002004200f370300200541606a22022400200420021005200320022012a7100c0b2007200636022020072018370300200720193703082007201a370310200741186a2017370300200041186a20173703002000201a370310200020193703082000201837030020002006360220200141d0016a24000f0b41941541171004000bb309020d7f137e230041d0016b220224002002220141c0016a100320012903c001200141c8016a290300844200510440200241506a220722022400200141a0016a418012290300418812290300419012290300419812290300100b200141a8016a2903002114200141b0016a2903002111200141b8016a290300211520012903a0012112200241606a220422032400200341606a220522082400200241786a2015370300200241706a2011370300200241686a2014370300200420123703002004200510052005290300210e200341686a290300210f200341706a2903002113200341786a29030021102008220241606a220322042400200241786a2010370300200241706a2013370300200241686a200f3703002003200e3703000240201042808080808080808001835004402001200e200f20132010100b20012903002110200441606a2206240020062003201042fe01834201882218a7100c420021194200211a420021170c010b20014180016a200e200f20132010100b20014198016a290300210e20014190016a290300210f20014188016a2903002116200129038001211b2004220241606a220322042400200241786a2015370300200241706a2011370300200241686a201437030020032012370300200141e0006a42204200420042002003100d200141f8006a290300211c200141f0006a2903002113200141e8006a290300211420012903602110200441606a2202220324002003201b4201882211a7410f6a4170716b220622092400024020112016423f868422184220544100200f423f862016420188842219501b200e4201882217420053200e423f86200f42018884221a201784501b450440200141c8006a210a200141d0006a210b2018211b20192115201a211d2017210f200621030340200141406b201020142013201c100b200a290300210e200b290300211120012903402112200241186a200141d8006a290300370300200220113703102002200e370308200220123703002002200310052015201b42607c2212201b542204ad7c427f7c220e2015512105200e2015542108201d427f7c2220201d54210c201c2013201042017c2216201054220d2014200dad7c221e201454201620105a1bad7c221f201354ad7c211c200341206a21032012211b200e211520202004200820051bad7c2211211d20162110201e2114201f21132012421f56200e420052200e501b20114200522011202054ad200f200cad7c7c427f7c220f420055200f501b200f201184501b0d000b0c010b201821122019210e201a21112017210f20062103201021162014211e2013211f0b2012504100200e501b200f420053200f201184501b0d002009220241606a220422052400200141206a2016201e201f201c100b200141286a2903002110200141306a290300210e2001290320210f200241786a200141386a290300370300200241706a200e370300200241686a20103703002004200f370300200541606a22022400200420021005200320022012a7100c0b2007200636022020072018370300200720193703082007201a370310200741186a2017370300200041186a20173703002000201a370310200020193703082000201837030020002006360220200141d0016a24000f0b41ab1541171004000be71402057f057e230041b0076b22012100200124000240100841034d0d00200141706a2201220224002001410041041009024002400240024002400240024002400240200128020022014185fafb1e4c0440200141a3af89be7d4c0d01200141a4af89be7d460d0320014198acb4e87d470d05200041206a101020002000290320200041286a290300200041306a290300200041386a290300100b200041086a2903002105200041106a2903002106200041186a2903002107200029030021082002220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c090b200141dcc5b5f7034c0d01200141ddc5b5f703460d0320014195b1ef8c04470d0520004188076a101b20002802a8072104200041e8066a200029038807220520004190076a29030020004198076a290300200041a0076a290300100b200041f0066a2903002106200041f8066a290300210720004180076a290300210820002903e806210920022005a72203412f6a4170716b22012400200141186a2008370300200120073703102001200637030820012009370300200141206a20042003100c2001200341206a100a0c080b20014189bc9d9d7b470d052002220141406a2202220324002002410441c0001009200041c0036a2002290300200141486a290300200141506a290300200141586a290300100b200041a0036a200141606a290300200141686a290300200141706a290300200141786a290300100b20004180036a20002903c003200041c8036a290300200041d0036a35020020002903a003200041a8036a290300200041b0036a290300200041b8036a2903001016ad420183420042004200100b20004188036a290300210520004190036a290300210620004198036a290300210720002903800321082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c070b20014186fafb1e470d05200041c0066a101a20002802e0062104200041a0066a20002903c0062205200041c8066a290300200041d0066a290300200041d8066a290300100b200041a8066a2903002106200041b0066a2903002107200041b8066a290300210820002903a006210920022005a72203412f6a4170716b22012400200141186a2008370300200120073703102001200637030820012009370300200141206a20042003100c2001200341206a100a0c060b2002220141406a2202220324002002410441c000100920004180066a2002290300200141486a290300200141506a290300200141586a290300100b200041e0056a200141606a290300200141686a290300200141706a290300200141786a290300100b200041c0056a20002903800620004188066a29030020004190066a35020020002903e005200041e8056a290300200041f0056a290300200041f8056a2903001019ad420183420042004200100b200041c8056a2903002105200041d0056a2903002106200041d8056a290300210720002903c00521082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c050b2002220141406a2202220324002002410441c0001009200041e0026a2002290300200141486a290300200141506a290300200141586a290300100b200041c0026a200141606a290300200141686a290300200141706a290300200141786a290300100b200041a0026a20002903e002200041e8026a290300200041f0026a35020020002903c002200041c8026a290300200041d0026a350200101420004180026a20002903a002200041a8026a290300200041b0026a290300200041b8026a290300100b20004188026a290300210520004190026a290300210620004198026a290300210720002903800221082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c040b200141a3f0caeb7d470d042002220141a07f6a2202220324002002410441e0001009200041c0046a2002290300200141a87f6a290300200141b07f6a290300200141b87f6a290300100b200041a0046a200141406a290300200141486a290300200141506a290300200141586a290300100b20004180046a200141606a290300200141686a290300200141706a290300200141786a290300100b200041e0036a20002903c004200041c8046a290300200041d0046a35020020002903a004200041a8046a290300200041b0046a35020020002903800420004188046a29030020004190046a29030020004198046a2903001017ad420183420042004200100b200041e8036a2903002105200041f0036a2903002106200041f8036a290300210720002903e00321082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c030b200141b9a0cd8c05470d032002220141406a2202220324002002410441c0001009200041a0056a2002290300200141486a290300200141506a290300200141586a290300100b20004180056a200141606a290300200141686a290300200141706a290300200141786a290300100b200041e0046a20002903a005200041a8056a290300200041b0056a35020020002903800520004188056a29030020004190056a29030020004198056a2903001018ad420183420042004200100b200041e8046a2903002105200041f0046a2903002106200041f8046a290300210720002903e00421082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c020b200141a98bf0dc7b470d022002220141406a2202220324002002410441c0001009200041e0016a2002290300200141486a290300200141506a290300200141586a290300100b200041c0016a200141606a290300200141686a290300200141706a290300200141786a290300100b200041a0016a20002903e001200041e8016a290300200041f0016a35020020002903c001200041c8016a290300200041d0016a290300200041d8016a2903001013ad420183420042004200100b200041a8016a2903002105200041b0016a2903002106200041b8016a290300210720002903a00121082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0c010b200141f0c08a8c03470d012002220141606a220222032400200241044120100920004180016a2002290300200141686a290300200141706a290300200141786a290300100b200041e0006a20002903800120004188016a29030020004190016a3502001011200041406b2000290360200041e8006a290300200041f0006a290300200041f8006a290300100b200041c8006a2903002105200041d0006a2903002106200041d8006a2903002107200029034021082003220141606a22022400200141786a2007370300200141706a2006370300200141686a20053703002002200837030020024120100a0b200041b0076a24000f0b410041001004000b0bb30406004180080b6746756e6374696f6e206973206e6f742070617961626c65536166654d6174683a206164646974696f6e206f766572666c6f7746756e6374696f6e206973206e6f742070617961626c65536166654d6174683a207375627472616374696f6e206f766572666c6f770041800c0b01010041800e0b0102004180100b0103004180120b01040041a0120ba20346756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a207472616e7366657220746f20746865207a65726f206164647265737346756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6545524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c6546756e6374696f6e206973206e6f742070617961626c65 -------------------------------------------------------------------------------- /docs/erc20/erc20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | contract ERC20 { 5 | // Safemath 6 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 7 | uint256 c = a + b; 8 | require(c >= a, "SafeMath: addition overflow"); 9 | 10 | return c; 11 | } 12 | 13 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 14 | require(b <= a, "SafeMath: subtraction overflow"); 15 | uint256 c = a - b; 16 | 17 | return c; 18 | } 19 | 20 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 21 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 22 | // benefit is lost if 'b' is also tested. 23 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 24 | if (a == 0) { 25 | return uint256(0); 26 | } 27 | 28 | uint256 c = a * b; 29 | require(c / a == b, "SafeMath: multiplication overflow"); 30 | 31 | return c; 32 | } 33 | 34 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 35 | require(b > 0, "SafeMath: division by zero"); 36 | uint256 c = a / b; 37 | return c; 38 | } 39 | 40 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 41 | require(b != 0, "SafeMath: modulo by zero"); 42 | return a % b; 43 | } 44 | 45 | // // real contract 46 | mapping(address => uint256) private _balances; 47 | mapping(address => mapping(address => uint256)) private _allowances; 48 | uint256 private _totalSupply; 49 | string private _name; 50 | string private _symbol; 51 | 52 | function totalSupply() public view returns (uint256) { 53 | return _totalSupply; 54 | } 55 | 56 | function balanceOf(address account) public view returns (uint256) { 57 | return _balances[account]; 58 | } 59 | 60 | function _transfer( 61 | address _sender, 62 | address recipient, 63 | uint256 amount 64 | ) internal { 65 | require(_sender != address(0), "ERC20: transfer from the zero address"); 66 | require(recipient != address(0), "ERC20: transfer to the zero address"); 67 | 68 | _balances[_sender] = sub(_balances[_sender], amount); 69 | _balances[recipient] = add(_balances[recipient], amount); 70 | } 71 | 72 | function transfer(address recipient, uint256 amount) public returns (bool) { 73 | _transfer(msg.sender, recipient, amount); 74 | return true; 75 | } 76 | 77 | function allowance(address owner, address spender) 78 | public 79 | view 80 | returns (uint256) 81 | { 82 | return _allowances[owner][spender]; 83 | } 84 | 85 | function _approve( 86 | address owner, 87 | address spender, 88 | uint256 value 89 | ) internal { 90 | require(owner != address(0), "ERC20: approve from the zero address"); 91 | require(spender != address(0), "ERC20: approve to the zero address"); 92 | 93 | _allowances[owner][spender] = value; 94 | } 95 | 96 | function approve(address spender, uint256 value) public returns (bool) { 97 | _approve(msg.sender, spender, value); 98 | return true; 99 | } 100 | 101 | function transferFrom( 102 | address _sender, 103 | address recipient, 104 | uint256 amount 105 | ) public returns (bool) { 106 | _transfer(_sender, recipient, amount); 107 | _approve( 108 | _sender, 109 | msg.sender, 110 | sub(_allowances[_sender][msg.sender], amount) 111 | ); 112 | return true; 113 | } 114 | 115 | function increaseAllowance(address spender, uint256 addedValue) 116 | public 117 | returns (bool) 118 | { 119 | _approve( 120 | msg.sender, 121 | spender, 122 | add(_allowances[msg.sender][spender], addedValue) 123 | ); 124 | return true; 125 | } 126 | 127 | function decreaseAllowance(address spender, uint256 subtractedValue) 128 | public 129 | returns (bool) 130 | { 131 | _approve( 132 | msg.sender, 133 | spender, 134 | sub(_allowances[msg.sender][spender], subtractedValue) 135 | ); 136 | return true; 137 | } 138 | 139 | function _mint(address account, uint256 amount) internal { 140 | require(account != address(0), "ERC20: mint to the zero address"); 141 | 142 | _totalSupply = add(_totalSupply, amount); 143 | _balances[account] = add(_balances[account], amount); 144 | } 145 | 146 | function _burn(address account, uint256 value) internal { 147 | require(account != address(0), "ERC20: burn from the zero address"); 148 | 149 | _balances[account] = sub(_balances[account], value); 150 | _totalSupply = sub(_totalSupply, value); 151 | } 152 | 153 | function _burnFrom(address account, uint256 amount) internal { 154 | _burn(account, amount); 155 | _approve( 156 | account, 157 | msg.sender, 158 | sub(_allowances[account][msg.sender], amount) 159 | ); 160 | } 161 | 162 | function name() public returns (string) { 163 | return _name; 164 | } 165 | 166 | function symbol() public returns (string) { 167 | return _symbol; 168 | } 169 | 170 | constructor() public { 171 | _name = "ERC20TokenDemo"; 172 | _symbol = "ETD"; 173 | _mint(msg.sender, 1000); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /docs/erc20/erc20.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/erc20/erc20.wasm -------------------------------------------------------------------------------- /docs/interact-using-web.md: -------------------------------------------------------------------------------- 1 | # Interact using Substrate web UI 2 | 3 | ## Build & Run node 4 | 5 | We use [secondstate/substrate-ssvm](https://hub.docker.com/r/secondstate/substrate-ssvm) as building & running environment: 6 | 7 | ```bash 8 | > git clone https://github.com/second-state/substrate-ssvm-node.git 9 | > docker run -it --rm \ 10 | --name substrate-ssvm \ 11 | -p 9944:9944 \ 12 | -v $(pwd):/root/node \ 13 | -w /root/node/substrate-ssvm-node \ 14 | secondstate/substrate-ssvm:latest \ 15 | /bin/bash -c "make init && make build && cargo run --release --bin ssvm-node -- --dev --ws-external" 16 | ``` 17 | 18 | > **Remember to publish 9944 port from container to use Substrate web UI.** 19 | 20 | ## Connect to node 21 | 22 | - Open https://polkadot.js.org/apps in the browser. 23 | - In [settings](https://polkadot.js.org/apps/#/settings), make sure you select `Local Node`. 24 | 25 | ![](./web-ui/local-node.png) 26 | 27 | ## Create Contract 28 | 29 | Here we use the following ERC20 contract files as an example: 30 | - [erc20.sol](./erc20/erc20.sol) 31 | - This file is an ERC20 contract written in Solidity. 32 | - [erc20.wasm](./erc20/erc20.wasm) 33 | - This file is a wasm file generate from `erc20.sol` by [SOLL](https://github.com/second-state/soll) 34 | - Command to generate wasm file: `soll -deploy=Normal erc20.sol` 35 | - [erc20.hex](./erc20/erc20.hex) 36 | - To deploy the wasm file to our node, we need to convert `erc20.wasm` to hex. 37 | - Command to generate hex file: `xxd -p erc20.wasm | tr -d $'\n' > erc20.hex` 38 | 39 | - In [Extrinsics](https://polkadot.js.org/apps/#/extrinsics), select `ssvm` and `create`. 40 | - Put the content of [erc20.hex](./erc20/erc20.hex) in the `code` section. 41 | - Select proper gas limit & gas price. 42 | - Submit Transaction 43 | 44 | ![](./web-ui/deploy-contract.png) 45 | 46 | The contract will be deployed at address `0xe2a313e210a6ec1d5a9c0806545670f2e6264f86`. 47 | 48 | ![](./web-ui/contract-address.png) 49 | 50 | ## Interact with contract 51 | 52 | ### Get ERC20 balance of Alice: 53 | 54 | - Prepare call data: 55 | - In EVM, call data is in `{function signature}{function arguments}` format 56 | - Data of `balanceOf(Alice)` is `0x70a082310000000000000000000000009621dde636de098b43efb0fa9b61facfe328f99d` 57 | - In [Extrinsics](https://polkadot.js.org/apps/#/extrinsics), select `ssvm` and `call`. 58 | - Fill contract address `0xe2a313e210a6ec1d5a9c0806545670f2e6264f86` in target section. 59 | - Fill call data in input section. 60 | - Select proper gas limit & gas price. 61 | - Submit Transaction 62 | 63 | ![](./web-ui/sendtx-balanceOfAlice.png) 64 | 65 | The output `0x00000000000000000000000000000000000000000000000000000000000003e8` shows that Alice has 0x3e8 = 1000 ERC20 tokens. 66 | 67 | ![](./web-ui/before-balanceOfAlice.png) 68 | 69 | ### Transfer 3 tokens from Alice to Bob: 70 | 71 | - Prepare call data: 72 | - Data of `transfer(Bob, 3)` is `0xa9059cbb00000000000000000000000041dccbd49b26c50d34355ed86ff0fa9e489d1e010000000000000000000000000000000000000000000000000000000000000003` 73 | - In [Extrinsics](https://polkadot.js.org/apps/#/extrinsics), select `ssvm` and `call`. 74 | - Fill contract address `0xe2a313e210a6ec1d5a9c0806545670f2e6264f86` in target section. 75 | - Fill call data in input section. 76 | - Select proper gas limit & gas price. 77 | - Submit Transaction 78 | 79 | ![](./web-ui/sendtx-transfer.png) 80 | 81 | The output `0x0000000000000000000000000000000000000000000000000000000000000001` shows that function call is success. 82 | 83 | ![](./web-ui/after-transfer.png) 84 | 85 | ## Check ERC20 balance of Alice again 86 | 87 | - Prepare call data: 88 | - Data of `balanceOf(Alice)` is `0x70a082310000000000000000000000009621dde636de098b43efb0fa9b61facfe328f99d` 89 | - In [Extrinsics](https://polkadot.js.org/apps/#/extrinsics), select `ssvm` and `call`. 90 | - Fill contract address `0xe2a313e210a6ec1d5a9c0806545670f2e6264f86` in target section. 91 | - Fill call data in input section. 92 | - Select proper gas limit & gas price. 93 | - Submit Transaction 94 | - And try again with 0x70a0823100000000000000000000000041dccbd49b26c50d34355ed86ff0fa9e489d1e01 95 | 96 | The output `0x00000000000000000000000000000000000000000000000000000000000003e5` shows that Alice has 0x3e5 = 997 ERC20 tokens after transfering. 97 | 98 | The output `0x0000000000000000000000000000000000000000000000000000000000000003` shows that Bob has 3 ERC20 tokens after transfering. 99 | 100 | ![](./web-ui/after-balanceOfAliceBob.png) -------------------------------------------------------------------------------- /docs/web-ui/after-balanceOfAliceBob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/after-balanceOfAliceBob.png -------------------------------------------------------------------------------- /docs/web-ui/after-transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/after-transfer.png -------------------------------------------------------------------------------- /docs/web-ui/before-balanceOfAlice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/before-balanceOfAlice.png -------------------------------------------------------------------------------- /docs/web-ui/contract-address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/contract-address.png -------------------------------------------------------------------------------- /docs/web-ui/deploy-contract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/deploy-contract.png -------------------------------------------------------------------------------- /docs/web-ui/local-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/local-node.png -------------------------------------------------------------------------------- /docs/web-ui/sendtx-balanceOfAlice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/sendtx-balanceOfAlice.png -------------------------------------------------------------------------------- /docs/web-ui/sendtx-transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ParaState/substrate-ssvm-node/8445611d3b586f5f4b6927ceed16581f0959cff5/docs/web-ui/sendtx-transfer.png -------------------------------------------------------------------------------- /node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ['Second State '] 3 | build = 'build.rs' 4 | description = 'A fresh FRAME-based Substrate node, ready for hacking.' 5 | edition = '2018' 6 | license = 'Unlicense' 7 | name = 'ssvm-node' 8 | repository = 'https://github.com/second-state/substrate-ssvm-node/' 9 | version = '2.0.1' 10 | 11 | [[bin]] 12 | name = 'ssvm-node' 13 | 14 | [package.metadata.docs.rs] 15 | targets = ['x86_64-unknown-linux-gnu'] 16 | 17 | [build-dependencies] 18 | substrate-build-script-utils = '2.0.1' 19 | 20 | [dependencies] 21 | jsonrpc-core = '15.0.0' 22 | structopt = '0.3.8' 23 | 24 | # local dependencies 25 | ssvm-node-runtime = { path = '../runtime', version = '2.0.1' } 26 | 27 | # Substrate dependencies 28 | frame-benchmarking = '2.0.1' 29 | frame-benchmarking-cli = '2.0.1' 30 | pallet-transaction-payment-rpc = '2.0.1' 31 | sc-basic-authorship = '0.8.1' 32 | sc-cli = { features = ['wasmtime'], version = '0.8.1' } 33 | sc-client-api = '2.0.1' 34 | sc-consensus = '0.8.1' 35 | sc-consensus-aura = '0.8.1' 36 | sc-executor = { features = ['wasmtime'], version = '0.8.1' } 37 | sc-finality-grandpa = '0.8.1' 38 | sc-rpc = '2.0.1' 39 | sc-rpc-api = '0.8.1' 40 | sc-service = { features = ['wasmtime'], version = '0.8.1' } 41 | sc-transaction-pool = '2.0.1' 42 | sp-api = '2.0.1' 43 | sp-block-builder = '2.0.1' 44 | sp-blockchain = '2.0.1' 45 | sp-consensus = '0.8.1' 46 | sp-consensus-aura = '0.8.1' 47 | sp-core = '2.0.1' 48 | sp-finality-grandpa = '2.0.1' 49 | sp-inherents = '2.0.1' 50 | sp-runtime = '2.0.1' 51 | sp-transaction-pool = '2.0.1' 52 | substrate-frame-rpc-system = '2.0.1' 53 | 54 | # SSVM 55 | pallet-ssvm = { default-features = false, version = "0.1.0-rc2" } 56 | 57 | [features] 58 | default = [] 59 | runtime-benchmarks = ['ssvm-node-runtime/runtime-benchmarks'] 60 | -------------------------------------------------------------------------------- /node/build.rs: -------------------------------------------------------------------------------- 1 | use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; 2 | 3 | fn main() { 4 | generate_cargo_keys(); 5 | 6 | rerun_if_git_head_changed(); 7 | } 8 | -------------------------------------------------------------------------------- /node/src/chain_spec.rs: -------------------------------------------------------------------------------- 1 | use sp_core::{Pair, Public, sr25519}; 2 | use ssvm_node_runtime::{ 3 | AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SSVMAccount, SSVMConfig, 4 | Sha3Hasher, Signature, SudoConfig, SystemConfig, WASM_BINARY, 5 | }; 6 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 7 | use sp_finality_grandpa::AuthorityId as GrandpaId; 8 | use sp_runtime::traits::{Verify, IdentifyAccount}; 9 | use sc_service::ChainType; 10 | use pallet_ssvm::{ConvertAccountId, HashTruncateConvertAccountId}; 11 | 12 | // The URL for the telemetry server. 13 | // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; 14 | 15 | /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. 16 | pub type ChainSpec = sc_service::GenericChainSpec; 17 | 18 | /// Generate a crypto pair from seed. 19 | pub fn get_from_seed(seed: &str) -> ::Public { 20 | TPublic::Pair::from_string(&format!("//{}", seed), None) 21 | .expect("static values are valid; qed") 22 | .public() 23 | } 24 | 25 | type AccountPublic = ::Signer; 26 | 27 | /// Generate an account ID from seed. 28 | pub fn get_account_id_from_seed(seed: &str) -> AccountId where 29 | AccountPublic: From<::Public> 30 | { 31 | AccountPublic::from(get_from_seed::(seed)).into_account() 32 | } 33 | 34 | /// Generate an Aura authority key. 35 | pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { 36 | ( 37 | get_from_seed::(s), 38 | get_from_seed::(s), 39 | ) 40 | } 41 | 42 | pub fn development_config() -> Result { 43 | let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; 44 | 45 | Ok(ChainSpec::from_genesis( 46 | // Name 47 | "Development", 48 | // ID 49 | "dev", 50 | ChainType::Development, 51 | move || testnet_genesis( 52 | wasm_binary, 53 | // Initial PoA authorities 54 | vec![ 55 | authority_keys_from_seed("Alice"), 56 | ], 57 | // Sudo account 58 | get_account_id_from_seed::("Alice"), 59 | // Pre-funded accounts 60 | vec![ 61 | get_account_id_from_seed::("Alice"), 62 | get_account_id_from_seed::("Bob"), 63 | get_account_id_from_seed::("Alice//stash"), 64 | get_account_id_from_seed::("Bob//stash"), 65 | ], 66 | true, 67 | ), 68 | // Bootnodes 69 | vec![], 70 | // Telemetry 71 | None, 72 | // Protocol ID 73 | None, 74 | // Properties 75 | None, 76 | // Extensions 77 | None, 78 | )) 79 | } 80 | 81 | pub fn local_testnet_config() -> Result { 82 | let wasm_binary = WASM_BINARY.ok_or("Development wasm binary not available".to_string())?; 83 | 84 | Ok(ChainSpec::from_genesis( 85 | // Name 86 | "Local Testnet", 87 | // ID 88 | "local_testnet", 89 | ChainType::Local, 90 | move || testnet_genesis( 91 | wasm_binary, 92 | // Initial PoA authorities 93 | vec![ 94 | authority_keys_from_seed("Alice"), 95 | authority_keys_from_seed("Bob"), 96 | ], 97 | // Sudo account 98 | get_account_id_from_seed::("Alice"), 99 | // Pre-funded accounts 100 | vec![ 101 | get_account_id_from_seed::("Alice"), 102 | get_account_id_from_seed::("Bob"), 103 | get_account_id_from_seed::("Charlie"), 104 | get_account_id_from_seed::("Dave"), 105 | get_account_id_from_seed::("Eve"), 106 | get_account_id_from_seed::("Ferdie"), 107 | get_account_id_from_seed::("Alice//stash"), 108 | get_account_id_from_seed::("Bob//stash"), 109 | get_account_id_from_seed::("Charlie//stash"), 110 | get_account_id_from_seed::("Dave//stash"), 111 | get_account_id_from_seed::("Eve//stash"), 112 | get_account_id_from_seed::("Ferdie//stash"), 113 | ], 114 | true, 115 | ), 116 | // Bootnodes 117 | vec![], 118 | // Telemetry 119 | None, 120 | // Protocol ID 121 | None, 122 | // Properties 123 | None, 124 | // Extensions 125 | None, 126 | )) 127 | } 128 | 129 | /// Configure initial storage state for FRAME modules. 130 | fn testnet_genesis( 131 | wasm_binary: &[u8], 132 | initial_authorities: Vec<(AuraId, GrandpaId)>, 133 | root_key: AccountId, 134 | endowed_accounts: Vec, 135 | _enable_println: bool, 136 | ) -> GenesisConfig { 137 | GenesisConfig { 138 | frame_system: Some(SystemConfig { 139 | // Add Wasm runtime to storage. 140 | code: wasm_binary.to_vec(), 141 | changes_trie_config: Default::default(), 142 | }), 143 | pallet_balances: Some(BalancesConfig { 144 | // Configure endowed accounts with initial balance of 1 << 60. 145 | balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), 146 | }), 147 | pallet_aura: Some(AuraConfig { 148 | authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), 149 | }), 150 | pallet_grandpa: Some(GrandpaConfig { 151 | authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), 152 | }), 153 | pallet_sudo: Some(SudoConfig { 154 | // Assign network admin rights. 155 | key: root_key, 156 | }), 157 | pallet_ssvm: Some(SSVMConfig { 158 | accounts: vec![( 159 | HashTruncateConvertAccountId::::convert_account_id( 160 | &get_account_id_from_seed::("Alice"), 161 | ), 162 | SSVMAccount { 163 | nonce: 0.into(), 164 | balance: 1000000.into(), 165 | }, 166 | )], 167 | }), 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /node/src/cli.rs: -------------------------------------------------------------------------------- 1 | use structopt::StructOpt; 2 | use sc_cli::RunCmd; 3 | 4 | #[derive(Debug, StructOpt)] 5 | pub struct Cli { 6 | #[structopt(subcommand)] 7 | pub subcommand: Option, 8 | 9 | #[structopt(flatten)] 10 | pub run: RunCmd, 11 | } 12 | 13 | #[derive(Debug, StructOpt)] 14 | pub enum Subcommand { 15 | /// Build a chain specification. 16 | BuildSpec(sc_cli::BuildSpecCmd), 17 | 18 | /// Validate blocks. 19 | CheckBlock(sc_cli::CheckBlockCmd), 20 | 21 | /// Export blocks. 22 | ExportBlocks(sc_cli::ExportBlocksCmd), 23 | 24 | /// Export the state of a given block into a chain spec. 25 | ExportState(sc_cli::ExportStateCmd), 26 | 27 | /// Import blocks. 28 | ImportBlocks(sc_cli::ImportBlocksCmd), 29 | 30 | /// Remove the whole chain. 31 | PurgeChain(sc_cli::PurgeChainCmd), 32 | 33 | /// Revert the chain to a previous state. 34 | Revert(sc_cli::RevertCmd), 35 | 36 | /// The custom benchmark subcommmand benchmarking runtime pallets. 37 | #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] 38 | Benchmark(frame_benchmarking_cli::BenchmarkCmd), 39 | } 40 | -------------------------------------------------------------------------------- /node/src/command.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | use crate::{chain_spec, service}; 19 | use crate::cli::{Cli, Subcommand}; 20 | use sc_cli::{SubstrateCli, RuntimeVersion, Role, ChainSpec}; 21 | use sc_service::PartialComponents; 22 | use ssvm_node_runtime::Block; 23 | 24 | impl SubstrateCli for Cli { 25 | fn impl_name() -> String { 26 | "Substrate Node".into() 27 | } 28 | 29 | fn impl_version() -> String { 30 | env!("SUBSTRATE_CLI_IMPL_VERSION").into() 31 | } 32 | 33 | fn description() -> String { 34 | env!("CARGO_PKG_DESCRIPTION").into() 35 | } 36 | 37 | fn author() -> String { 38 | env!("CARGO_PKG_AUTHORS").into() 39 | } 40 | 41 | fn support_url() -> String { 42 | "support.anonymous.an".into() 43 | } 44 | 45 | fn copyright_start_year() -> i32 { 46 | 2017 47 | } 48 | 49 | fn load_spec(&self, id: &str) -> Result, String> { 50 | Ok(match id { 51 | "dev" => Box::new(chain_spec::development_config()?), 52 | "" | "local" => Box::new(chain_spec::local_testnet_config()?), 53 | path => Box::new(chain_spec::ChainSpec::from_json_file( 54 | std::path::PathBuf::from(path), 55 | )?), 56 | }) 57 | } 58 | 59 | fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { 60 | &ssvm_node_runtime::VERSION 61 | } 62 | } 63 | 64 | /// Parse and run command line arguments 65 | pub fn run() -> sc_cli::Result<()> { 66 | let cli = Cli::from_args(); 67 | 68 | match &cli.subcommand { 69 | Some(Subcommand::BuildSpec(cmd)) => { 70 | let runner = cli.create_runner(cmd)?; 71 | runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) 72 | }, 73 | Some(Subcommand::CheckBlock(cmd)) => { 74 | let runner = cli.create_runner(cmd)?; 75 | runner.async_run(|config| { 76 | let PartialComponents { client, task_manager, import_queue, ..} 77 | = service::new_partial(&config)?; 78 | Ok((cmd.run(client, import_queue), task_manager)) 79 | }) 80 | }, 81 | Some(Subcommand::ExportBlocks(cmd)) => { 82 | let runner = cli.create_runner(cmd)?; 83 | runner.async_run(|config| { 84 | let PartialComponents { client, task_manager, ..} 85 | = service::new_partial(&config)?; 86 | Ok((cmd.run(client, config.database), task_manager)) 87 | }) 88 | }, 89 | Some(Subcommand::ExportState(cmd)) => { 90 | let runner = cli.create_runner(cmd)?; 91 | runner.async_run(|config| { 92 | let PartialComponents { client, task_manager, ..} 93 | = service::new_partial(&config)?; 94 | Ok((cmd.run(client, config.chain_spec), task_manager)) 95 | }) 96 | }, 97 | Some(Subcommand::ImportBlocks(cmd)) => { 98 | let runner = cli.create_runner(cmd)?; 99 | runner.async_run(|config| { 100 | let PartialComponents { client, task_manager, import_queue, ..} 101 | = service::new_partial(&config)?; 102 | Ok((cmd.run(client, import_queue), task_manager)) 103 | }) 104 | }, 105 | Some(Subcommand::PurgeChain(cmd)) => { 106 | let runner = cli.create_runner(cmd)?; 107 | runner.sync_run(|config| cmd.run(config.database)) 108 | }, 109 | Some(Subcommand::Revert(cmd)) => { 110 | let runner = cli.create_runner(cmd)?; 111 | runner.async_run(|config| { 112 | let PartialComponents { client, task_manager, backend, ..} 113 | = service::new_partial(&config)?; 114 | Ok((cmd.run(client, backend), task_manager)) 115 | }) 116 | }, 117 | Some(Subcommand::Benchmark(cmd)) => { 118 | if cfg!(feature = "runtime-benchmarks") { 119 | let runner = cli.create_runner(cmd)?; 120 | 121 | runner.sync_run(|config| cmd.run::(config)) 122 | } else { 123 | Err("Benchmarking wasn't enabled when building the node. \ 124 | You can enable it with `--features runtime-benchmarks`.".into()) 125 | } 126 | }, 127 | None => { 128 | let runner = cli.create_runner(&cli.run)?; 129 | runner.run_node_until_exit(|config| match config.role { 130 | Role::Light => service::new_light(config), 131 | _ => service::new_full(config), 132 | }) 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /node/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod chain_spec; 2 | pub mod service; 3 | pub mod rpc; 4 | -------------------------------------------------------------------------------- /node/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Substrate Node Template CLI library. 2 | #![warn(missing_docs)] 3 | 4 | mod chain_spec; 5 | #[macro_use] 6 | mod service; 7 | mod cli; 8 | mod command; 9 | mod rpc; 10 | 11 | fn main() -> sc_cli::Result<()> { 12 | command::run() 13 | } 14 | -------------------------------------------------------------------------------- /node/src/rpc.rs: -------------------------------------------------------------------------------- 1 | //! A collection of node-specific RPC methods. 2 | //! Substrate provides the `sc-rpc` crate, which defines the core RPC layer 3 | //! used by Substrate nodes. This file extends those RPC definitions with 4 | //! capabilities that are specific to this project's runtime configuration. 5 | 6 | #![warn(missing_docs)] 7 | 8 | use std::sync::Arc; 9 | 10 | use ssvm_node_runtime::{opaque::Block, AccountId, Balance, Index}; 11 | use sp_api::ProvideRuntimeApi; 12 | use sp_blockchain::{Error as BlockChainError, HeaderMetadata, HeaderBackend}; 13 | use sp_block_builder::BlockBuilder; 14 | pub use sc_rpc_api::DenyUnsafe; 15 | use sp_transaction_pool::TransactionPool; 16 | 17 | 18 | /// Full client dependencies. 19 | pub struct FullDeps { 20 | /// The client instance to use. 21 | pub client: Arc, 22 | /// Transaction pool instance. 23 | pub pool: Arc

, 24 | /// Whether to deny unsafe calls 25 | pub deny_unsafe: DenyUnsafe, 26 | } 27 | 28 | /// Instantiate all full RPC extensions. 29 | pub fn create_full( 30 | deps: FullDeps, 31 | ) -> jsonrpc_core::IoHandler where 32 | C: ProvideRuntimeApi, 33 | C: HeaderBackend + HeaderMetadata + 'static, 34 | C: Send + Sync + 'static, 35 | C::Api: substrate_frame_rpc_system::AccountNonceApi, 36 | C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, 37 | C::Api: BlockBuilder, 38 | P: TransactionPool + 'static, 39 | { 40 | use substrate_frame_rpc_system::{FullSystem, SystemApi}; 41 | use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; 42 | 43 | let mut io = jsonrpc_core::IoHandler::default(); 44 | let FullDeps { 45 | client, 46 | pool, 47 | deny_unsafe, 48 | } = deps; 49 | 50 | io.extend_with( 51 | SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe)) 52 | ); 53 | 54 | io.extend_with( 55 | TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone())) 56 | ); 57 | 58 | // Extend this RPC with a custom API by using the following syntax. 59 | // `YourRpcStruct` should have a reference to a client, which is needed 60 | // to call into the runtime. 61 | // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));` 62 | 63 | io 64 | } 65 | -------------------------------------------------------------------------------- /node/src/service.rs: -------------------------------------------------------------------------------- 1 | //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. 2 | 3 | use std::sync::Arc; 4 | use std::time::Duration; 5 | use sc_client_api::{ExecutorProvider, RemoteBackend}; 6 | use ssvm_node_runtime::{self, opaque::Block, RuntimeApi}; 7 | use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; 8 | use sp_inherents::InherentDataProviders; 9 | use sc_executor::native_executor_instance; 10 | pub use sc_executor::NativeExecutor; 11 | use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; 12 | use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; 13 | 14 | // Our native executor instance. 15 | native_executor_instance!( 16 | pub Executor, 17 | ssvm_node_runtime::api::dispatch, 18 | ssvm_node_runtime::native_version, 19 | frame_benchmarking::benchmarking::HostFunctions, 20 | ); 21 | 22 | type FullClient = sc_service::TFullClient; 23 | type FullBackend = sc_service::TFullBackend; 24 | type FullSelectChain = sc_consensus::LongestChain; 25 | 26 | pub fn new_partial(config: &Configuration) -> Result, 29 | sc_transaction_pool::FullPool, 30 | ( 31 | sc_consensus_aura::AuraBlockImport< 32 | Block, 33 | FullClient, 34 | sc_finality_grandpa::GrandpaBlockImport, 35 | AuraPair 36 | >, 37 | sc_finality_grandpa::LinkHalf 38 | ) 39 | >, ServiceError> { 40 | let inherent_data_providers = sp_inherents::InherentDataProviders::new(); 41 | 42 | let (client, backend, keystore, task_manager) = 43 | sc_service::new_full_parts::(&config)?; 44 | let client = Arc::new(client); 45 | 46 | let select_chain = sc_consensus::LongestChain::new(backend.clone()); 47 | 48 | let transaction_pool = sc_transaction_pool::BasicPool::new_full( 49 | config.transaction_pool.clone(), 50 | config.prometheus_registry(), 51 | task_manager.spawn_handle(), 52 | client.clone(), 53 | ); 54 | 55 | let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( 56 | client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), 57 | )?; 58 | 59 | let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( 60 | grandpa_block_import.clone(), client.clone(), 61 | ); 62 | 63 | let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( 64 | sc_consensus_aura::slot_duration(&*client)?, 65 | aura_block_import.clone(), 66 | Some(Box::new(grandpa_block_import.clone())), 67 | None, 68 | client.clone(), 69 | inherent_data_providers.clone(), 70 | &task_manager.spawn_handle(), 71 | config.prometheus_registry(), 72 | sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), 73 | )?; 74 | 75 | Ok(sc_service::PartialComponents { 76 | client, backend, task_manager, import_queue, keystore, select_chain, transaction_pool, 77 | inherent_data_providers, 78 | other: (aura_block_import, grandpa_link), 79 | }) 80 | } 81 | 82 | /// Builds a new service for a full client. 83 | pub fn new_full(config: Configuration) -> Result { 84 | let sc_service::PartialComponents { 85 | client, backend, mut task_manager, import_queue, keystore, select_chain, transaction_pool, 86 | inherent_data_providers, 87 | other: (block_import, grandpa_link), 88 | } = new_partial(&config)?; 89 | 90 | let finality_proof_provider = 91 | GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); 92 | 93 | let (network, network_status_sinks, system_rpc_tx, network_starter) = 94 | sc_service::build_network(sc_service::BuildNetworkParams { 95 | config: &config, 96 | client: client.clone(), 97 | transaction_pool: transaction_pool.clone(), 98 | spawn_handle: task_manager.spawn_handle(), 99 | import_queue, 100 | on_demand: None, 101 | block_announce_validator_builder: None, 102 | finality_proof_request_builder: None, 103 | finality_proof_provider: Some(finality_proof_provider.clone()), 104 | })?; 105 | 106 | if config.offchain_worker.enabled { 107 | sc_service::build_offchain_workers( 108 | &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(), 109 | ); 110 | } 111 | 112 | let role = config.role.clone(); 113 | let force_authoring = config.force_authoring; 114 | let name = config.network.node_name.clone(); 115 | let enable_grandpa = !config.disable_grandpa; 116 | let prometheus_registry = config.prometheus_registry().cloned(); 117 | let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); 118 | 119 | let rpc_extensions_builder = { 120 | let client = client.clone(); 121 | let pool = transaction_pool.clone(); 122 | 123 | Box::new(move |deny_unsafe, _| { 124 | let deps = crate::rpc::FullDeps { 125 | client: client.clone(), 126 | pool: pool.clone(), 127 | deny_unsafe, 128 | }; 129 | 130 | crate::rpc::create_full(deps) 131 | }) 132 | }; 133 | 134 | sc_service::spawn_tasks(sc_service::SpawnTasksParams { 135 | network: network.clone(), 136 | client: client.clone(), 137 | keystore: keystore.clone(), 138 | task_manager: &mut task_manager, 139 | transaction_pool: transaction_pool.clone(), 140 | telemetry_connection_sinks: telemetry_connection_sinks.clone(), 141 | rpc_extensions_builder: rpc_extensions_builder, 142 | on_demand: None, 143 | remote_blockchain: None, 144 | backend, network_status_sinks, system_rpc_tx, config, 145 | })?; 146 | 147 | if role.is_authority() { 148 | let proposer = sc_basic_authorship::ProposerFactory::new( 149 | client.clone(), 150 | transaction_pool, 151 | prometheus_registry.as_ref(), 152 | ); 153 | 154 | let can_author_with = 155 | sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); 156 | 157 | let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( 158 | sc_consensus_aura::slot_duration(&*client)?, 159 | client.clone(), 160 | select_chain, 161 | block_import, 162 | proposer, 163 | network.clone(), 164 | inherent_data_providers.clone(), 165 | force_authoring, 166 | keystore.clone(), 167 | can_author_with, 168 | )?; 169 | 170 | // the AURA authoring task is considered essential, i.e. if it 171 | // fails we take down the service with it. 172 | task_manager.spawn_essential_handle().spawn_blocking("aura", aura); 173 | } 174 | 175 | // if the node isn't actively participating in consensus then it doesn't 176 | // need a keystore, regardless of which protocol we use below. 177 | let keystore = if role.is_authority() { 178 | Some(keystore as sp_core::traits::BareCryptoStorePtr) 179 | } else { 180 | None 181 | }; 182 | 183 | let grandpa_config = sc_finality_grandpa::Config { 184 | // FIXME #1578 make this available through chainspec 185 | gossip_duration: Duration::from_millis(333), 186 | justification_period: 512, 187 | name: Some(name), 188 | observer_enabled: false, 189 | keystore, 190 | is_authority: role.is_network_authority(), 191 | }; 192 | 193 | if enable_grandpa { 194 | // start the full GRANDPA voter 195 | // NOTE: non-authorities could run the GRANDPA observer protocol, but at 196 | // this point the full voter should provide better guarantees of block 197 | // and vote data availability than the observer. The observer has not 198 | // been tested extensively yet and having most nodes in a network run it 199 | // could lead to finality stalls. 200 | let grandpa_config = sc_finality_grandpa::GrandpaParams { 201 | config: grandpa_config, 202 | link: grandpa_link, 203 | network, 204 | inherent_data_providers, 205 | telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), 206 | voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), 207 | prometheus_registry, 208 | shared_voter_state: SharedVoterState::empty(), 209 | }; 210 | 211 | // the GRANDPA voter task is considered infallible, i.e. 212 | // if it fails we take down the service with it. 213 | task_manager.spawn_essential_handle().spawn_blocking( 214 | "grandpa-voter", 215 | sc_finality_grandpa::run_grandpa_voter(grandpa_config)? 216 | ); 217 | } else { 218 | sc_finality_grandpa::setup_disabled_grandpa( 219 | client, 220 | &inherent_data_providers, 221 | network, 222 | )?; 223 | } 224 | 225 | network_starter.start_network(); 226 | Ok(task_manager) 227 | } 228 | 229 | /// Builds a new service for a light client. 230 | pub fn new_light(config: Configuration) -> Result { 231 | let (client, backend, keystore, mut task_manager, on_demand) = 232 | sc_service::new_light_parts::(&config)?; 233 | 234 | let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( 235 | config.transaction_pool.clone(), 236 | config.prometheus_registry(), 237 | task_manager.spawn_handle(), 238 | client.clone(), 239 | on_demand.clone(), 240 | )); 241 | 242 | let grandpa_block_import = sc_finality_grandpa::light_block_import( 243 | client.clone(), backend.clone(), &(client.clone() as Arc<_>), 244 | Arc::new(on_demand.checker().clone()) as Arc<_>, 245 | )?; 246 | let finality_proof_import = grandpa_block_import.clone(); 247 | let finality_proof_request_builder = 248 | finality_proof_import.create_finality_proof_request_builder(); 249 | 250 | let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( 251 | sc_consensus_aura::slot_duration(&*client)?, 252 | grandpa_block_import, 253 | None, 254 | Some(Box::new(finality_proof_import)), 255 | client.clone(), 256 | InherentDataProviders::new(), 257 | &task_manager.spawn_handle(), 258 | config.prometheus_registry(), 259 | sp_consensus::NeverCanAuthor, 260 | )?; 261 | 262 | let finality_proof_provider = 263 | GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); 264 | 265 | let (network, network_status_sinks, system_rpc_tx, network_starter) = 266 | sc_service::build_network(sc_service::BuildNetworkParams { 267 | config: &config, 268 | client: client.clone(), 269 | transaction_pool: transaction_pool.clone(), 270 | spawn_handle: task_manager.spawn_handle(), 271 | import_queue, 272 | on_demand: Some(on_demand.clone()), 273 | block_announce_validator_builder: None, 274 | finality_proof_request_builder: Some(finality_proof_request_builder), 275 | finality_proof_provider: Some(finality_proof_provider), 276 | })?; 277 | 278 | if config.offchain_worker.enabled { 279 | sc_service::build_offchain_workers( 280 | &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(), 281 | ); 282 | } 283 | 284 | sc_service::spawn_tasks(sc_service::SpawnTasksParams { 285 | remote_blockchain: Some(backend.remote_blockchain()), 286 | transaction_pool, 287 | task_manager: &mut task_manager, 288 | on_demand: Some(on_demand), 289 | rpc_extensions_builder: Box::new(|_, _| ()), 290 | telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), 291 | config, 292 | client, 293 | keystore, 294 | backend, 295 | network, 296 | network_status_sinks, 297 | system_rpc_tx, 298 | })?; 299 | 300 | network_starter.start_network(); 301 | 302 | Ok(task_manager) 303 | } 304 | -------------------------------------------------------------------------------- /pallets/template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ['Substrate DevHub '] 3 | description = 'FRAME pallet template for defining custom runtime logic.' 4 | edition = '2018' 5 | homepage = 'https://substrate.dev' 6 | license = 'Unlicense' 7 | name = 'pallet-template' 8 | repository = 'https://github.com/substrate-developer-hub/substrate-node-template/' 9 | version = '2.0.1' 10 | 11 | [package.metadata.docs.rs] 12 | targets = ['x86_64-unknown-linux-gnu'] 13 | 14 | # alias "parity-scale-code" to "codec" 15 | [dependencies.codec] 16 | default-features = false 17 | features = ['derive'] 18 | package = 'parity-scale-codec' 19 | version = '1.3.4' 20 | 21 | [dependencies] 22 | frame-support = { default-features = false, version = '2.0.1' } 23 | frame-system = { default-features = false, version = '2.0.1' } 24 | 25 | [dev-dependencies] 26 | sp-core = { default-features = false, version = '2.0.1' } 27 | sp-io = { default-features = false, version = '2.0.1' } 28 | sp-runtime = { default-features = false, version = '2.0.1' } 29 | 30 | [features] 31 | default = ['std'] 32 | std = [ 33 | 'codec/std', 34 | 'frame-support/std', 35 | 'frame-system/std', 36 | ] 37 | -------------------------------------------------------------------------------- /pallets/template/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | /// Edit this file to define custom logic or remove it if it is not needed. 4 | /// Learn more about FRAME and the core library of Substrate FRAME pallets: 5 | /// https://substrate.dev/docs/en/knowledgebase/runtime/frame 6 | 7 | use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch, traits::Get}; 8 | use frame_system::ensure_signed; 9 | 10 | #[cfg(test)] 11 | mod mock; 12 | 13 | #[cfg(test)] 14 | mod tests; 15 | 16 | /// Configure the pallet by specifying the parameters and types on which it depends. 17 | pub trait Trait: frame_system::Trait { 18 | /// Because this pallet emits events, it depends on the runtime's definition of an event. 19 | type Event: From> + Into<::Event>; 20 | } 21 | 22 | // The pallet's runtime storage items. 23 | // https://substrate.dev/docs/en/knowledgebase/runtime/storage 24 | decl_storage! { 25 | // A unique name is used to ensure that the pallet's storage items are isolated. 26 | // This name may be updated, but each pallet in the runtime must use a unique name. 27 | // ---------------------------------vvvvvvvvvvvvvv 28 | trait Store for Module as TemplateModule { 29 | // Learn more about declaring storage items: 30 | // https://substrate.dev/docs/en/knowledgebase/runtime/storage#declaring-storage-items 31 | Something get(fn something): Option; 32 | } 33 | } 34 | 35 | // Pallets use events to inform users when important changes are made. 36 | // https://substrate.dev/docs/en/knowledgebase/runtime/events 37 | decl_event!( 38 | pub enum Event where AccountId = ::AccountId { 39 | /// Event documentation should end with an array that provides descriptive names for event 40 | /// parameters. [something, who] 41 | SomethingStored(u32, AccountId), 42 | } 43 | ); 44 | 45 | // Errors inform users that something went wrong. 46 | decl_error! { 47 | pub enum Error for Module { 48 | /// Error names should be descriptive. 49 | NoneValue, 50 | /// Errors should have helpful documentation associated with them. 51 | StorageOverflow, 52 | } 53 | } 54 | 55 | // Dispatchable functions allows users to interact with the pallet and invoke state changes. 56 | // These functions materialize as "extrinsics", which are often compared to transactions. 57 | // Dispatchable functions must be annotated with a weight and must return a DispatchResult. 58 | decl_module! { 59 | pub struct Module for enum Call where origin: T::Origin { 60 | // Errors must be initialized if they are used by the pallet. 61 | type Error = Error; 62 | 63 | // Events must be initialized if they are used by the pallet. 64 | fn deposit_event() = default; 65 | 66 | /// An example dispatchable that takes a singles value as a parameter, writes the value to 67 | /// storage and emits an event. This function must be dispatched by a signed extrinsic. 68 | #[weight = 10_000 + T::DbWeight::get().writes(1)] 69 | pub fn do_something(origin, something: u32) -> dispatch::DispatchResult { 70 | // Check that the extrinsic was signed and get the signer. 71 | // This function will return an error if the extrinsic is not signed. 72 | // https://substrate.dev/docs/en/knowledgebase/runtime/origin 73 | let who = ensure_signed(origin)?; 74 | 75 | // Update storage. 76 | Something::put(something); 77 | 78 | // Emit an event. 79 | Self::deposit_event(RawEvent::SomethingStored(something, who)); 80 | // Return a successful DispatchResult 81 | Ok(()) 82 | } 83 | 84 | /// An example dispatchable that may throw a custom error. 85 | #[weight = 10_000 + T::DbWeight::get().reads_writes(1,1)] 86 | pub fn cause_error(origin) -> dispatch::DispatchResult { 87 | let _who = ensure_signed(origin)?; 88 | 89 | // Read a value from storage. 90 | match Something::get() { 91 | // Return an error if the value has not been set. 92 | None => Err(Error::::NoneValue)?, 93 | Some(old) => { 94 | // Increment the value read from storage; will error in the event of overflow. 95 | let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; 96 | // Update the value in storage with the incremented result. 97 | Something::put(new); 98 | Ok(()) 99 | }, 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pallets/template/src/mock.rs: -------------------------------------------------------------------------------- 1 | use crate::{Module, Trait}; 2 | use sp_core::H256; 3 | use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; 4 | use sp_runtime::{ 5 | traits::{BlakeTwo256, IdentityLookup}, testing::Header, Perbill, 6 | }; 7 | use frame_system as system; 8 | 9 | impl_outer_origin! { 10 | pub enum Origin for Test {} 11 | } 12 | 13 | // Configure a mock runtime to test the pallet. 14 | 15 | #[derive(Clone, Eq, PartialEq)] 16 | pub struct Test; 17 | parameter_types! { 18 | pub const BlockHashCount: u64 = 250; 19 | pub const MaximumBlockWeight: Weight = 1024; 20 | pub const MaximumBlockLength: u32 = 2 * 1024; 21 | pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); 22 | } 23 | 24 | impl system::Trait for Test { 25 | type BaseCallFilter = (); 26 | type Origin = Origin; 27 | type Call = (); 28 | type Index = u64; 29 | type BlockNumber = u64; 30 | type Hash = H256; 31 | type Hashing = BlakeTwo256; 32 | type AccountId = u64; 33 | type Lookup = IdentityLookup; 34 | type Header = Header; 35 | type Event = (); 36 | type BlockHashCount = BlockHashCount; 37 | type MaximumBlockWeight = MaximumBlockWeight; 38 | type DbWeight = (); 39 | type BlockExecutionWeight = (); 40 | type ExtrinsicBaseWeight = (); 41 | type MaximumExtrinsicWeight = MaximumBlockWeight; 42 | type MaximumBlockLength = MaximumBlockLength; 43 | type AvailableBlockRatio = AvailableBlockRatio; 44 | type Version = (); 45 | type PalletInfo = (); 46 | type AccountData = (); 47 | type OnNewAccount = (); 48 | type OnKilledAccount = (); 49 | type SystemWeightInfo = (); 50 | } 51 | 52 | impl Trait for Test { 53 | type Event = (); 54 | } 55 | 56 | pub type TemplateModule = Module; 57 | 58 | // Build genesis storage according to the mock runtime. 59 | pub fn new_test_ext() -> sp_io::TestExternalities { 60 | system::GenesisConfig::default().build_storage::().unwrap().into() 61 | } 62 | -------------------------------------------------------------------------------- /pallets/template/src/tests.rs: -------------------------------------------------------------------------------- 1 | use crate::{Error, mock::*}; 2 | use frame_support::{assert_ok, assert_noop}; 3 | 4 | #[test] 5 | fn it_works_for_default_value() { 6 | new_test_ext().execute_with(|| { 7 | // Dispatch a signed extrinsic. 8 | assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); 9 | // Read pallet storage and assert an expected result. 10 | assert_eq!(TemplateModule::something(), Some(42)); 11 | }); 12 | } 13 | 14 | #[test] 15 | fn correct_error_for_none_value() { 16 | new_test_ext().execute_with(|| { 17 | // Ensure the expected error is thrown when no value is present. 18 | assert_noop!( 19 | TemplateModule::cause_error(Origin::signed(1)), 20 | Error::::NoneValue 21 | ); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ['Second State '] 3 | edition = '2018' 4 | homepage = 'https://substrate.dev' 5 | license = 'Unlicense' 6 | name = 'ssvm-node-runtime' 7 | repository = 'https://github.com/second-state/substrate-ssvm-node/' 8 | version = '2.0.1' 9 | 10 | [package.metadata.docs.rs] 11 | targets = ['x86_64-unknown-linux-gnu'] 12 | 13 | [build-dependencies] 14 | substrate-wasm-builder = '3.0.0' 15 | 16 | # alias "parity-scale-code" to "codec" 17 | [dependencies.codec] 18 | default-features = false 19 | features = ['derive'] 20 | package = 'parity-scale-codec' 21 | version = '1.3.4' 22 | 23 | [dependencies] 24 | hex-literal = { optional = true, version = '0.3.1' } 25 | serde = { features = ['derive'], optional = true, version = '1.0.119' } 26 | 27 | # Substrate dependencies 28 | frame-benchmarking = { default-features = false, optional = true, version = '2.0.1' } 29 | frame-executive = { default-features = false, version = '2.0.1' } 30 | frame-support = { default-features = false, version = '2.0.1' } 31 | frame-system = { default-features = false, version = '2.0.1' } 32 | frame-system-benchmarking = { default-features = false, optional = true, version = '2.0.1' } 33 | frame-system-rpc-runtime-api = { default-features = false, version = '2.0.1' } 34 | pallet-aura = { default-features = false, version = '2.0.1' } 35 | pallet-balances = { default-features = false, version = '2.0.1' } 36 | pallet-grandpa = { default-features = false, version = '2.0.1' } 37 | pallet-randomness-collective-flip = { default-features = false, version = '2.0.1' } 38 | pallet-sudo = { default-features = false, version = '2.0.1' } 39 | pallet-timestamp = { default-features = false, version = '2.0.1' } 40 | pallet-transaction-payment = { default-features = false, version = '2.0.1' } 41 | pallet-transaction-payment-rpc-runtime-api = { default-features = false, version = '2.0.1' } 42 | sp-api = { default-features = false, version = '2.0.1' } 43 | sp-block-builder = { default-features = false, version = '2.0.1' } 44 | sp-consensus-aura = { default-features = false, version = '0.8.1' } 45 | sp-core = { default-features = false, version = '2.0.1' } 46 | sp-inherents = { default-features = false, version = '2.0.1' } 47 | sp-offchain = { default-features = false, version = '2.0.1' } 48 | sp-runtime = { default-features = false, version = '2.0.1' } 49 | sp-session = { default-features = false, version = '2.0.1' } 50 | sp-std = { default-features = false, version = '2.0.1' } 51 | sp-transaction-pool = { default-features = false, version = '2.0.1' } 52 | sp-version = { default-features = false, version = '2.0.1' } 53 | 54 | # SSVM 55 | pallet-ssvm = { default-features = false, version = "0.1.0-rc2" } 56 | sha3 = { default-features = false, version = "0.8" } 57 | hash256-std-hasher = { default-features = false, version = '0.15.2' } 58 | 59 | [features] 60 | default = ['std'] 61 | runtime-benchmarks = [ 62 | 'hex-literal', 63 | 'frame-benchmarking', 64 | 'frame-support/runtime-benchmarks', 65 | 'frame-system-benchmarking', 66 | 'frame-system/runtime-benchmarks', 67 | 'pallet-balances/runtime-benchmarks', 68 | 'pallet-timestamp/runtime-benchmarks', 69 | 'sp-runtime/runtime-benchmarks', 70 | ] 71 | std = [ 72 | 'codec/std', 73 | 'serde', 74 | 'frame-executive/std', 75 | 'frame-support/std', 76 | 'frame-system/std', 77 | 'frame-system-rpc-runtime-api/std', 78 | 'pallet-aura/std', 79 | 'pallet-balances/std', 80 | 'pallet-grandpa/std', 81 | 'pallet-randomness-collective-flip/std', 82 | 'pallet-sudo/std', 83 | 'pallet-timestamp/std', 84 | 'pallet-transaction-payment/std', 85 | 'pallet-transaction-payment-rpc-runtime-api/std', 86 | 'sp-api/std', 87 | 'sp-block-builder/std', 88 | 'sp-consensus-aura/std', 89 | 'sp-core/std', 90 | 'sp-inherents/std', 91 | 'sp-offchain/std', 92 | 'sp-runtime/std', 93 | 'sp-session/std', 94 | 'sp-std/std', 95 | 'sp-transaction-pool/std', 96 | 'sp-version/std', 97 | 'pallet-ssvm/std', 98 | ] 99 | -------------------------------------------------------------------------------- /runtime/build.rs: -------------------------------------------------------------------------------- 1 | use substrate_wasm_builder::WasmBuilder; 2 | 3 | fn main() { 4 | WasmBuilder::new() 5 | .with_current_project() 6 | .import_memory() 7 | .export_heap_base() 8 | .build() 9 | } 10 | -------------------------------------------------------------------------------- /runtime/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. 3 | #![recursion_limit = "256"] 4 | 5 | // Make the WASM binary available. 6 | #[cfg(feature = "std")] 7 | include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); 8 | 9 | use sp_std::prelude::*; 10 | use sp_core::{crypto::KeyTypeId, Hasher, OpaqueMetadata}; 11 | use sp_runtime::{ 12 | ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature, 13 | transaction_validity::{TransactionValidity, TransactionSource}, 14 | }; 15 | use sp_runtime::traits::{ 16 | BlakeTwo256, Block as BlockT, Verify, IdentifyAccount, NumberFor, Saturating, 17 | }; 18 | use hash256_std_hasher::Hash256StdHasher; 19 | use sha3::{Digest, Keccak256}; 20 | use sp_api::impl_runtime_apis; 21 | use sp_consensus_aura::sr25519::AuthorityId as AuraId; 22 | use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; 23 | use pallet_grandpa::fg_primitives; 24 | use sp_version::RuntimeVersion; 25 | #[cfg(feature = "std")] 26 | use sp_version::NativeVersion; 27 | 28 | // A few exports that help ease life for downstream crates. 29 | #[cfg(any(feature = "std", test))] 30 | pub use sp_runtime::BuildStorage; 31 | pub use pallet_timestamp::Call as TimestampCall; 32 | pub use pallet_balances::Call as BalancesCall; 33 | pub use sp_runtime::{Permill, Perbill}; 34 | pub use frame_support::{ 35 | construct_runtime, parameter_types, StorageValue, 36 | traits::{KeyOwnerProofSystem, Randomness}, 37 | weights::{ 38 | Weight, IdentityFee, 39 | constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, 40 | }, 41 | }; 42 | 43 | pub use pallet_ssvm::Account as SSVMAccount; 44 | use pallet_ssvm::HashTruncateConvertAccountId; 45 | 46 | /// An index to a block. 47 | pub type BlockNumber = u32; 48 | 49 | /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. 50 | pub type Signature = MultiSignature; 51 | 52 | /// Some way of identifying an account on the chain. We intentionally make it equivalent 53 | /// to the public key of our transaction signing scheme. 54 | pub type AccountId = <::Signer as IdentifyAccount>::AccountId; 55 | 56 | /// The type for looking up accounts. We don't expect more than 4 billion of them, but you 57 | /// never know... 58 | pub type AccountIndex = u32; 59 | 60 | /// Balance of an account. 61 | pub type Balance = u128; 62 | 63 | /// Index of a transaction in the chain. 64 | pub type Index = u32; 65 | 66 | /// A hash of some data used by the chain. 67 | pub type Hash = sp_core::H256; 68 | 69 | /// Digest item type. 70 | pub type DigestItem = generic::DigestItem; 71 | 72 | /// SSVM struct 73 | pub struct Sha3Hasher; 74 | impl Hasher for Sha3Hasher { 75 | type Out = sp_core::H256; 76 | type StdHasher = Hash256StdHasher; 77 | const LENGTH: usize = 32; 78 | fn hash(x: &[u8]) -> Self::Out { 79 | sp_core::H256::from_slice(Keccak256::digest(x).as_slice()) 80 | } 81 | } 82 | 83 | /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know 84 | /// the specifics of the runtime. They can then be made to be agnostic over specific formats 85 | /// of data like extrinsics, allowing for them to continue syncing the network through upgrades 86 | /// to even the core data structures. 87 | pub mod opaque { 88 | use super::*; 89 | 90 | pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; 91 | 92 | /// Opaque block header type. 93 | pub type Header = generic::Header; 94 | /// Opaque block type. 95 | pub type Block = generic::Block; 96 | /// Opaque block identifier type. 97 | pub type BlockId = generic::BlockId; 98 | 99 | impl_opaque_keys! { 100 | pub struct SessionKeys { 101 | pub aura: Aura, 102 | pub grandpa: Grandpa, 103 | } 104 | } 105 | } 106 | 107 | pub const VERSION: RuntimeVersion = RuntimeVersion { 108 | spec_name: create_runtime_str!("ssvm-node"), 109 | impl_name: create_runtime_str!("ssvm-node"), 110 | authoring_version: 1, 111 | spec_version: 100, 112 | impl_version: 1, 113 | apis: RUNTIME_API_VERSIONS, 114 | transaction_version: 1, 115 | }; 116 | 117 | pub const MILLISECS_PER_BLOCK: u64 = 6000; 118 | 119 | pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; 120 | 121 | // Time is measured by number of blocks. 122 | pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); 123 | pub const HOURS: BlockNumber = MINUTES * 60; 124 | pub const DAYS: BlockNumber = HOURS * 24; 125 | 126 | /// The version information used to identify this runtime when compiled natively. 127 | #[cfg(feature = "std")] 128 | pub fn native_version() -> NativeVersion { 129 | NativeVersion { 130 | runtime_version: VERSION, 131 | can_author_with: Default::default(), 132 | } 133 | } 134 | 135 | parameter_types! { 136 | pub const BlockHashCount: BlockNumber = 2400; 137 | /// We allow for 2 seconds of compute with a 6 second average block time. 138 | pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND; 139 | pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); 140 | /// Assume 10% of weight for average on_initialize calls. 141 | pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() 142 | .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); 143 | pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; 144 | pub const Version: RuntimeVersion = VERSION; 145 | } 146 | 147 | // Configure FRAME pallets to include in runtime. 148 | 149 | impl frame_system::Trait for Runtime { 150 | /// The basic call filter to use in dispatchable. 151 | type BaseCallFilter = (); 152 | /// The identifier used to distinguish between accounts. 153 | type AccountId = AccountId; 154 | /// The aggregated dispatch type that is available for extrinsics. 155 | type Call = Call; 156 | /// The lookup mechanism to get account ID from whatever is passed in dispatchers. 157 | type Lookup = multiaddress::AccountIdLookup; 158 | /// The index type for storing how many extrinsics an account has signed. 159 | type Index = Index; 160 | /// The index type for blocks. 161 | type BlockNumber = BlockNumber; 162 | /// The type for hashing blocks and tries. 163 | type Hash = Hash; 164 | /// The hashing algorithm used. 165 | type Hashing = BlakeTwo256; 166 | /// The header type. 167 | type Header = generic::Header; 168 | /// The ubiquitous event type. 169 | type Event = Event; 170 | /// The ubiquitous origin type. 171 | type Origin = Origin; 172 | /// Maximum number of block number to block hash mappings to keep (oldest pruned first). 173 | type BlockHashCount = BlockHashCount; 174 | /// Maximum weight of each block. 175 | type MaximumBlockWeight = MaximumBlockWeight; 176 | /// The weight of database operations that the runtime can invoke. 177 | type DbWeight = RocksDbWeight; 178 | /// The weight of the overhead invoked on the block import process, independent of the 179 | /// extrinsics included in that block. 180 | type BlockExecutionWeight = BlockExecutionWeight; 181 | /// The base weight of any extrinsic processed by the runtime, independent of the 182 | /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) 183 | type ExtrinsicBaseWeight = ExtrinsicBaseWeight; 184 | /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, 185 | /// idependent of the logic of that extrinsics. (Roughly max block weight - average on 186 | /// initialize cost). 187 | type MaximumExtrinsicWeight = MaximumExtrinsicWeight; 188 | /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. 189 | type MaximumBlockLength = MaximumBlockLength; 190 | /// Portion of the block weight that is available to all normal transactions. 191 | type AvailableBlockRatio = AvailableBlockRatio; 192 | /// Version of the runtime. 193 | type Version = Version; 194 | /// Converts a module to the index of the module in `construct_runtime!`. 195 | /// 196 | /// This type is being generated by `construct_runtime!`. 197 | type PalletInfo = PalletInfo; 198 | /// What to do if a new account is created. 199 | type OnNewAccount = (); 200 | /// What to do if an account is fully reaped from the system. 201 | type OnKilledAccount = (); 202 | /// The data to be stored in an account. 203 | type AccountData = pallet_balances::AccountData; 204 | /// Weight information for the extrinsics of this pallet. 205 | type SystemWeightInfo = (); 206 | } 207 | 208 | impl pallet_aura::Trait for Runtime { 209 | type AuthorityId = AuraId; 210 | } 211 | 212 | impl pallet_grandpa::Trait for Runtime { 213 | type Event = Event; 214 | type Call = Call; 215 | 216 | type KeyOwnerProofSystem = (); 217 | 218 | type KeyOwnerProof = 219 | >::Proof; 220 | 221 | type KeyOwnerIdentification = >::IdentificationTuple; 225 | 226 | type HandleEquivocation = (); 227 | 228 | type WeightInfo = (); 229 | } 230 | 231 | parameter_types! { 232 | pub const MinimumPeriod: u64 = SLOT_DURATION / 2; 233 | } 234 | 235 | impl pallet_timestamp::Trait for Runtime { 236 | /// A timestamp: milliseconds since the unix epoch. 237 | type Moment = u64; 238 | type OnTimestampSet = Aura; 239 | type MinimumPeriod = MinimumPeriod; 240 | type WeightInfo = (); 241 | } 242 | 243 | parameter_types! { 244 | pub const ExistentialDeposit: u128 = 500; 245 | pub const MaxLocks: u32 = 50; 246 | } 247 | 248 | impl pallet_balances::Trait for Runtime { 249 | type MaxLocks = MaxLocks; 250 | /// The type for recording an account's balance. 251 | type Balance = Balance; 252 | /// The ubiquitous event type. 253 | type Event = Event; 254 | type DustRemoval = (); 255 | type ExistentialDeposit = ExistentialDeposit; 256 | type AccountStore = System; 257 | type WeightInfo = (); 258 | } 259 | 260 | parameter_types! { 261 | pub const TransactionByteFee: Balance = 1; 262 | } 263 | 264 | impl pallet_transaction_payment::Trait for Runtime { 265 | type Currency = Balances; 266 | type OnTransactionPayment = (); 267 | type TransactionByteFee = TransactionByteFee; 268 | type WeightToFee = IdentityFee; 269 | type FeeMultiplierUpdate = (); 270 | } 271 | 272 | impl pallet_sudo::Trait for Runtime { 273 | type Event = Event; 274 | type Call = Call; 275 | } 276 | 277 | impl pallet_ssvm::Trait for Runtime { 278 | type ConvertAccountId = HashTruncateConvertAccountId; 279 | type Currency = Balances; 280 | type Event = Event; 281 | } 282 | 283 | // Create the runtime by composing the FRAME pallets that were previously configured. 284 | construct_runtime!( 285 | pub enum Runtime where 286 | Block = Block, 287 | NodeBlock = opaque::Block, 288 | UncheckedExtrinsic = UncheckedExtrinsic 289 | { 290 | System: frame_system::{Module, Call, Config, Storage, Event}, 291 | RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, 292 | Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, 293 | Aura: pallet_aura::{Module, Config, Inherent}, 294 | Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, 295 | Balances: pallet_balances::{Module, Call, Storage, Config, Event}, 296 | TransactionPayment: pallet_transaction_payment::{Module, Storage}, 297 | Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, 298 | // Include the custom logic from the template pallet in the runtime. 299 | SSVM: pallet_ssvm::{Module, Config, Call, Storage, Event}, 300 | } 301 | ); 302 | 303 | /// The address format for describing accounts. 304 | mod multiaddress; 305 | pub type Address = multiaddress::MultiAddress; 306 | /// Block header type as expected by this runtime. 307 | pub type Header = generic::Header; 308 | /// Block type as expected by this runtime. 309 | pub type Block = generic::Block; 310 | /// A Block signed with a Justification 311 | pub type SignedBlock = generic::SignedBlock; 312 | /// BlockId type as expected by this runtime. 313 | pub type BlockId = generic::BlockId; 314 | /// The SignedExtension to the basic transaction logic. 315 | pub type SignedExtra = ( 316 | frame_system::CheckSpecVersion, 317 | frame_system::CheckTxVersion, 318 | frame_system::CheckGenesis, 319 | frame_system::CheckEra, 320 | frame_system::CheckNonce, 321 | frame_system::CheckWeight, 322 | pallet_transaction_payment::ChargeTransactionPayment 323 | ); 324 | /// Unchecked extrinsic type as expected by this runtime. 325 | pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; 326 | /// Extrinsic type that has already been checked. 327 | pub type CheckedExtrinsic = generic::CheckedExtrinsic; 328 | /// Executive: handles dispatch to the various modules. 329 | pub type Executive = frame_executive::Executive< 330 | Runtime, 331 | Block, 332 | frame_system::ChainContext, 333 | Runtime, 334 | AllModules, 335 | >; 336 | 337 | impl_runtime_apis! { 338 | impl sp_api::Core for Runtime { 339 | fn version() -> RuntimeVersion { 340 | VERSION 341 | } 342 | 343 | fn execute_block(block: Block) { 344 | Executive::execute_block(block) 345 | } 346 | 347 | fn initialize_block(header: &::Header) { 348 | Executive::initialize_block(header) 349 | } 350 | } 351 | 352 | impl sp_api::Metadata for Runtime { 353 | fn metadata() -> OpaqueMetadata { 354 | Runtime::metadata().into() 355 | } 356 | } 357 | 358 | impl sp_block_builder::BlockBuilder for Runtime { 359 | fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { 360 | Executive::apply_extrinsic(extrinsic) 361 | } 362 | 363 | fn finalize_block() -> ::Header { 364 | Executive::finalize_block() 365 | } 366 | 367 | fn inherent_extrinsics(data: sp_inherents::InherentData) -> 368 | Vec<::Extrinsic> { 369 | data.create_extrinsics() 370 | } 371 | 372 | fn check_inherents( 373 | block: Block, 374 | data: sp_inherents::InherentData, 375 | ) -> sp_inherents::CheckInherentsResult { 376 | data.check_extrinsics(&block) 377 | } 378 | 379 | fn random_seed() -> ::Hash { 380 | RandomnessCollectiveFlip::random_seed() 381 | } 382 | } 383 | 384 | impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { 385 | fn validate_transaction( 386 | source: TransactionSource, 387 | tx: ::Extrinsic, 388 | ) -> TransactionValidity { 389 | Executive::validate_transaction(source, tx) 390 | } 391 | } 392 | 393 | impl sp_offchain::OffchainWorkerApi for Runtime { 394 | fn offchain_worker(header: &::Header) { 395 | Executive::offchain_worker(header) 396 | } 397 | } 398 | 399 | impl sp_consensus_aura::AuraApi for Runtime { 400 | fn slot_duration() -> u64 { 401 | Aura::slot_duration() 402 | } 403 | 404 | fn authorities() -> Vec { 405 | Aura::authorities() 406 | } 407 | } 408 | 409 | impl sp_session::SessionKeys for Runtime { 410 | fn generate_session_keys(seed: Option>) -> Vec { 411 | opaque::SessionKeys::generate(seed) 412 | } 413 | 414 | fn decode_session_keys( 415 | encoded: Vec, 416 | ) -> Option, KeyTypeId)>> { 417 | opaque::SessionKeys::decode_into_raw_public_keys(&encoded) 418 | } 419 | } 420 | 421 | impl fg_primitives::GrandpaApi for Runtime { 422 | fn grandpa_authorities() -> GrandpaAuthorityList { 423 | Grandpa::grandpa_authorities() 424 | } 425 | 426 | fn submit_report_equivocation_unsigned_extrinsic( 427 | _equivocation_proof: fg_primitives::EquivocationProof< 428 | ::Hash, 429 | NumberFor, 430 | >, 431 | _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, 432 | ) -> Option<()> { 433 | None 434 | } 435 | 436 | fn generate_key_ownership_proof( 437 | _set_id: fg_primitives::SetId, 438 | _authority_id: GrandpaId, 439 | ) -> Option { 440 | // NOTE: this is the only implementation possible since we've 441 | // defined our key owner proof type as a bottom type (i.e. a type 442 | // with no values). 443 | None 444 | } 445 | } 446 | 447 | impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { 448 | fn account_nonce(account: AccountId) -> Index { 449 | System::account_nonce(account) 450 | } 451 | } 452 | 453 | impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi 454 | for Runtime { 455 | fn query_info( 456 | uxt: ::Extrinsic, 457 | len: u32, 458 | ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { 459 | TransactionPayment::query_info(uxt, len) 460 | } 461 | } 462 | 463 | #[cfg(feature = "runtime-benchmarks")] 464 | impl frame_benchmarking::Benchmark for Runtime { 465 | fn dispatch_benchmark( 466 | config: frame_benchmarking::BenchmarkConfig 467 | ) -> Result, sp_runtime::RuntimeString> { 468 | use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; 469 | 470 | use frame_system_benchmarking::Module as SystemBench; 471 | impl frame_system_benchmarking::Trait for Runtime {} 472 | 473 | let whitelist: Vec = vec![ 474 | // Block Number 475 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac") 476 | .to_vec().into(), 477 | // Total Issuance 478 | hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") 479 | .to_vec().into(), 480 | // Execution Phase 481 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a") 482 | .to_vec().into(), 483 | // Event Count 484 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850") 485 | .to_vec().into(), 486 | // System Events 487 | hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7") 488 | .to_vec().into(), 489 | ]; 490 | 491 | let mut batches = Vec::::new(); 492 | let params = (&config, &whitelist); 493 | 494 | add_benchmark!(params, batches, frame_system, SystemBench::); 495 | add_benchmark!(params, batches, pallet_balances, Balances); 496 | add_benchmark!(params, batches, pallet_timestamp, Timestamp); 497 | 498 | if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } 499 | Ok(batches) 500 | } 501 | } 502 | } 503 | -------------------------------------------------------------------------------- /runtime/src/multiaddress.rs: -------------------------------------------------------------------------------- 1 | // This file is part of Substrate. 2 | 3 | // Copyright (C) 2017-2021 Parity Technologies (UK) Ltd. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | //! MultiAddress type is a wrapper for multiple downstream account formats. 19 | //! Copied from `sp_runtime::multiaddress`, and can be removed and replaced when 20 | //! updating to a newer version of Substrate. 21 | 22 | use codec::{Encode, Decode, Codec}; 23 | use sp_std::{vec::Vec, marker::PhantomData, fmt::Debug}; 24 | use sp_runtime::{RuntimeDebug, traits::{LookupError, StaticLookup}}; 25 | 26 | /// A multi-format address wrapper for on-chain accounts. 27 | #[derive(Encode, Decode, PartialEq, Eq, Clone, RuntimeDebug)] 28 | #[cfg_attr(feature = "std", derive(Hash))] 29 | pub enum MultiAddress { 30 | /// It's an account ID (pubkey). 31 | Id(AccountId), 32 | /// It's an account index. 33 | Index(#[codec(compact)] AccountIndex), 34 | /// It's some arbitrary raw bytes. 35 | Raw(Vec), 36 | /// It's a 32 byte representation. 37 | Address32([u8; 32]), 38 | /// Its a 20 byte representation. 39 | Address20([u8; 20]), 40 | } 41 | 42 | #[cfg(feature = "std")] 43 | impl std::fmt::Display for MultiAddress 44 | where 45 | AccountId: std::fmt::Debug, 46 | AccountIndex: std::fmt::Debug, 47 | { 48 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 49 | use sp_core::hexdisplay::HexDisplay; 50 | match self { 51 | MultiAddress::Raw(inner) => write!(f, "MultiAddress::Raw({})", HexDisplay::from(inner)), 52 | MultiAddress::Address32(inner) => write!(f, "MultiAddress::Address32({})", HexDisplay::from(inner)), 53 | MultiAddress::Address20(inner) => write!(f, "MultiAddress::Address20({})", HexDisplay::from(inner)), 54 | _ => write!(f, "{:?}", self), 55 | } 56 | } 57 | } 58 | 59 | impl From for MultiAddress { 60 | fn from(a: AccountId) -> Self { 61 | MultiAddress::Id(a) 62 | } 63 | } 64 | 65 | impl Default for MultiAddress { 66 | fn default() -> Self { 67 | MultiAddress::Id(Default::default()) 68 | } 69 | } 70 | 71 | /// A lookup implementation returning the `AccountId` from a `MultiAddress`. 72 | pub struct AccountIdLookup(PhantomData<(AccountId, AccountIndex)>); 73 | impl StaticLookup for AccountIdLookup 74 | where 75 | AccountId: Codec + Clone + PartialEq + Debug, 76 | AccountIndex: Codec + Clone + PartialEq + Debug, 77 | MultiAddress: Codec, 78 | { 79 | type Source = MultiAddress; 80 | type Target = AccountId; 81 | fn lookup(x: Self::Source) -> Result { 82 | match x { 83 | MultiAddress::Id(i) => Ok(i), 84 | _ => Err(LookupError), 85 | } 86 | } 87 | fn unlookup(x: Self::Target) -> Self::Source { 88 | MultiAddress::Id(x) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /scripts/docker_run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "*** Start Substrate node template ***" 6 | 7 | cd $(dirname ${BASH_SOURCE[0]})/.. 8 | 9 | docker-compose down --remove-orphans 10 | docker-compose run --rm --service-ports dev $@ -------------------------------------------------------------------------------- /scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "*** Initializing WASM build environment ***" 6 | 7 | if [ -z $CI_PROJECT_NAME ] ; then 8 | rustup update nightly 9 | rustup update stable 10 | fi 11 | 12 | rustup target add wasm32-unknown-unknown --toolchain nightly 13 | --------------------------------------------------------------------------------