From aba6bbc8536e3bb99ad87512ae426e8f46dc16b5 Mon Sep 17 00:00:00 2001 From: Aten Date: Mon, 15 Mar 2021 17:51:38 +0800 Subject: [PATCH] fix readme/doc for cargo-contract (#57) --- README.md | 9 ++++---- doc/europa.md | 42 ++++++++++++++++++-------------------- doc/imgs/call_other_1.png | Bin 0 -> 12332 bytes doc/imgs/call_other_2.png | Bin 0 -> 13116 bytes 4 files changed, 25 insertions(+), 26 deletions(-) create mode 100644 doc/imgs/call_other_1.png create mode 100644 doc/imgs/call_other_2.png diff --git a/README.md b/README.md index e79e0cb..1b0f1bf 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ We provide tow branches now: We may keep it in this way until `pallet-contracts` release v3.0.0 * `master` branch is our default branch, which provides our forked `pallet-contracts` crate that tracks the newest substrate `pallet-contracts` module. - + In `master` branch, Europa use `vender/substrate`'s `pallet-contracts` as dependency. This forked `pallet-contracts` is from the branch `europa-contracts` in our `vendor/substrate` repo. In this forked `pallet-contracts` Europa provides many self test features. @@ -70,7 +70,7 @@ Europa **current** "extending types" is (This may be changed for different Europ "Address": "MultiAddress" } ``` - + ## Features In details, current Europa sandbox framework provides: 1. This framework is another implementation for [substrate client](https://github.com/paritytech/substrate/tree/master/client). @@ -100,7 +100,8 @@ Europa self modifications: - [ ] Using `wasmtime` as WASM JIT-executor and support gdb/lldb debug. (developing) - [ ] Using `wasm3` as a more faster WASM interpreter. (not in plan) - [x] Supporting `NestedRuntime` event track feature to record all useful thing in `pallet-contracts`. - When instantiate or call a contract (This contract needs to be compiled by [PatractLabs's `cargo-contract`](https://github.com/patractlabs/cargo-contract/tree/cmd/debug) now), Europa would print: + When instantiate or call a contract (This contract needs to be compiled by [PatractLabs's `cargo-contract`](https://github.com/patractlabs/cargo-contract/) now), Europa would print: + ```bash 1: NestedRuntime { ext_result: [success] ExecReturnValue { flags: 0, data: 01 }, @@ -130,7 +131,7 @@ ChainExtensions features: *Currently we use a simple static way to charge weight for ZKP, we would change this part with benchmarks result in future.* More information about Europa `pallet-contracts` sandbox detailed features refers to the doc: [europa.md](./doc/europa.md) - + ## Build and run ### Build #### clone this repo diff --git a/doc/europa.md b/doc/europa.md index 400941c..a6b0f7a 100644 --- a/doc/europa.md +++ b/doc/europa.md @@ -30,18 +30,18 @@ We do following things to support those features: * ChainExtension: * Contract logger - We integrate the lib which is provided by PatractLabs: [ink-log](https://github.com/patractlabs/ink-log). This + We integrate the lib which is provided by Patract: [ink-log](https://github.com/patractlabs/ink-log). This lib pass log data from contract to Europa through ChainExtensions. * ZKP feature - We integrate the lib which is provided by PatractLabs: [megaclite](https://github.com/patractlabs/megaclite). + We integrate the lib which is provided by Patract: [megaclite](https://github.com/patractlabs/megaclite). This lib providers different curves to support basic function to run Groth16 algorithm in contracts. ### Prepare -For using all features when running contracts in Europa, we advice developers use [Patract Labs's `cargo-contract`](https://github.com/paritytech/cargo-contract) +For using all features when running contracts in Europa, we advice developers use [Patract's `cargo-contract`](https://github.com/paritytech/cargo-contract) to compile ink! contract, until [this pr#131 Enable debug info to the source warehouse with flag in command build](https://github.com/paritytech/cargo-contract/pull/131) could be merged by paritytech. -In Patract Labs's `cargo-contract`, we will contain the "name section" while compile contracts. Before this PR is merged, -currently, only the `cargo-contract` version provided by us (Patract Labs) can be used: +In Patract's `cargo-contract`, we will contain the "name section" while compile contracts. Before this PR is merged, +currently, only the `cargo-contract` version provided by us (Patract) can be used: ```bash cargo install --git https://github.com/patractlabs/cargo-contract --branch v0.10.0 --force @@ -77,25 +77,25 @@ FLAGS: Emits debug info into wasm file ``` -It means that you are using the `cargo-contract` provided by Patract Labs. If you want to see the backtrace of the WASM +It means that you are using the `cargo-contract` provided by Patract. If you want to see the backtrace of the WASM contract execution crash while using Europa, you need to add the `--debug` command when compiling the contract. Using the `--debug` command will generate file in the `target/ink` directory of the originally compiled contract, -ending with `*.wasm`. This `*.wasm` file is the WASM contract file containing the "name section" part. +replacing original `*.wasm/*.contract` file. **Notice that the file generated by this method is usually much larger than the original file**, for the `*.wasm/*.contract` file is the WASM contract file containing the "name section" part. -**If you need to use Europa for testing, the contract deployed to Europa needs to use this `*.wasm` file instead of the originally generated `*opt.wasm` file.** +**If you need to use Europa for testing, the contract deployed to Europa needs to use the file `*.wasm/*.contract` compiled by adding `-d/--debug` instead of the originally generated file.** -> In following doc, about the log part, if the contract do not have "name section" (contracts are not compiled by `--debug` -> or not submit `*.wasm` file), the output may contain a batch of ``. If you meet this, please use the contract +> In following doc, about the log part, if the contract do not have "name section" (contracts are not compiled by `--debug`), the output may contain a batch of ``. If you meet this, please use the contract > which has "name section". +> > ```bash > wasm_error: Error::WasmiExecution(Trap(Trap { kind: Unreachable })) -> wasm backtrace: -> | [...] -> | [...] -> ╰─>[...] +> wasm backtrace: +> | [...] +> | [...] +> ╰─>[...] > ``` - + ### Design and examples #### 1. Contract execution event tracker In our forked `pallet-contracts`, we define the struct `NestedRuntime` to track the event when developers execute contracts: @@ -222,7 +222,7 @@ Let's explain the information printed above: 1. After A calls B, it returns to A to continue execution, and then calls contract C - ![call_other_1](/Users/jenner/codes/substrate-contracts-book/src/zh_CN/europa/img/call_other_1.png) + ![call_other_1](imgs/call_other_1.png) Then it will produce a log print similar to the following: @@ -244,7 +244,7 @@ Let's explain the information printed above: 2. After A calls B, B calls contract C again, and finally returns to A - ![call_other_2](/Users/jenner/codes/substrate-contracts-book/src/zh_CN/europa/img/call_other_2.png) + ![call_other_2](imgs/call_other_2.png) Then it will produce a log print similar to the following: @@ -462,12 +462,10 @@ More information refers to [ink-log](https://github.com/patractlabs/ink-log). ##### 3.2 ZKP feature More information refers to [megaclite](https://github.com/patractlabs/megaclite), and the example contracts in [metis/groth16](https://github.com/patractlabs/metis/tree/master/groth16). - - #### Other examples: ##### Example 1:`ContractTrap` caused by locating duplicate topics -Some time ago, we (Patract Labs) reported a bug to `ink!`, see issue:["When set '0' value in contracts event, may cause `Error::ContractTrapped` and panic in contract #589" ](https://github.com/paritytech/ink/issues/589). It is very difficult to locate this error before Europa has developed the relevant function. Thank you @athei [located the error](https://github.com/paritytech/ink/issues/589#issuecomment-731571918). Here we reproduce this error and use Europa's log to quickly analyze and locate the place where the bug appears: +Some time ago, we (Patract) reported a bug to `ink!`, see issue:["When set '0' value in contracts event, may cause `Error::ContractTrapped` and panic in contract #589" ](https://github.com/paritytech/ink/issues/589). It is very difficult to locate this error before Europa has developed the relevant function. Thank you @athei [located the error](https://github.com/paritytech/ink/issues/589#issuecomment-731571918). Here we reproduce this error and use Europa's log to quickly analyze and locate the place where the bug appears: 1. checkout `ink!` to commit `8e8fe09565ca6d2fad7701d68ff13f12deda7eed` @@ -571,14 +569,14 @@ The `call` stage, such as calling `transfer`: From the wasm backtrace, it is very obvious that the execution process is ```bash - call -> deny_payment -> expect +call -> deny_payment -> expect ``` According to the code expanded macro (`cd ink/examples/erc20; cargo expand> tmp.rs`), we can see: ```bash #[no_mangle] -fn call() -> u32 { + fn call() -> u32 { if true { ::ink_lang::deny_payment::<::Env>() .expect("caller transferred value even though all ink! message deny payments") diff --git a/doc/imgs/call_other_1.png b/doc/imgs/call_other_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe6135f0b61c2b0a301d46d64b7b123ad25a4bb GIT binary patch literal 12332 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 zȀ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