github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/dev/wasm/escrow/Developing.md (about)

     1  # Developing
     2  
     3  If you have recently created a contract with this template, you probably could use some
     4  help on how to build and test the contract, as well as prepare it for production. This
     5  file attempts to provide a brief overview, assuming you have installed a recent
     6  version of Rust already (eg. 1.44.1+).
     7  
     8  ## Prerequisites
     9  
    10  Before starting, make sure you have [rustup](https://rustup.rs/) along with a
    11  recent `rustc` and `cargo` version installed. Currently, we are testing on 1.44.1+.
    12  
    13  And you need to have the `wasm32-unknown-unknown` target installed as well.
    14  
    15  You can check that via:
    16  
    17  ```sh
    18  rustc --version
    19  cargo --version
    20  rustup target list --installed
    21  # if wasm32 is not listed above, run this
    22  rustup target add wasm32-unknown-unknown
    23  ```
    24  
    25  ## Compiling and running tests
    26  
    27  Now that you created your custom contract, make sure you can compile and run it before
    28  making any changes. Go into the
    29  
    30  ```sh
    31  # this will produce a wasm build in ./target/wasm32-unknown-unknown/release/YOUR_NAME_HERE.wasm
    32  cargo wasm
    33  
    34  # this runs unit tests with helpful backtraces
    35  RUST_BACKTRACE=1 cargo unit-test
    36  
    37  # this runs integration tests with cranelift backend (uses rust stable)
    38  cargo integration-test
    39  
    40  # this runs integration tests with singlepass backend (needs rust nightly)
    41  cargo integration-test --no-default-features --features singlepass
    42  
    43  # auto-generate json schema
    44  cargo schema
    45  ```
    46  
    47  The wasmer engine, embedded in `cosmwasm-vm` supports multiple backends:
    48  singlepass and cranelift. Singlepass has fast compile times and slower run times,
    49  and supportes gas metering. It also requires rust `nightly`. This is used as default
    50  when embedding `cosmwasm-vm` in `go-cosmwasm` and is needed to use if you want to
    51  check the gas usage.
    52  
    53  However, when just building contacts, if you don't want to worry about installing
    54  two rust toolchains, you can run all tests with cranelift. The integration tests
    55  may take a small bit longer, but the results will be the same. The only difference
    56  is that you can not check gas usage here, so if you wish to optimize gas, you must
    57  switch to nightly and run with cranelift.
    58  
    59  ### Understanding the tests
    60  
    61  The main code is in `src/contract.rs` and the unit tests there run in pure rust,
    62  which makes them very quick to execute and give nice output on failures, especially
    63  if you do `RUST_BACKTRACE=1 cargo unit-test`.
    64  
    65  However, we don't just want to test the logic rust, but also the compiled Wasm artifact
    66  inside a VM. You can look in `tests/integration.rs` to see some examples there. They
    67  load the Wasm binary into the vm and call the contract externally. Effort has been
    68  made that the syntax is very similar to the calls in the native rust contract and
    69  quite easy to code. In fact, usually you can just copy a few unit tests and modify
    70  a few lines to make an integration test (this should get even easier in a future release).
    71  
    72  To run the latest integration tests, you need to explicitely rebuild the Wasm file with
    73  `cargo wasm` and then run `cargo integration-test`.
    74  
    75  We consider testing critical for anything on a blockchain, and recommend to always keep
    76  the tests up to date. While doing active development, it is often simplest to disable
    77  the integration tests completely and iterate rapidly on the code in `contract.rs`,
    78  both the logic and the tests. Once the code is finalized, you can copy over some unit
    79  tests into the integration.rs and make the needed changes. This ensures the compiled
    80  Wasm also behaves as desired in the real system.
    81  
    82  ## Generating JSON Schema
    83  
    84  While the Wasm calls (`init`, `handle`, `query`) accept JSON, this is not enough
    85  information to use it. We need to expose the schema for the expected messages to the
    86  clients. You can generate this schema by calling `cargo schema`, which will output
    87  4 files in `./schema`, corresponding to the 3 message types the contract accepts,
    88  as well as the internal `State`.
    89  
    90  These files are in standard json-schema format, which should be usable by various
    91  client side tools, either to auto-generate codecs, or just to validate incoming
    92  json wrt. the defined schema.
    93  
    94  ## Preparing the Wasm bytecode for production
    95  
    96  Before we upload it to a chain, we need to ensure the smallest output size possible,
    97  as this will be included in the body of a transaction. We also want to have a
    98  reproducible build process, so third parties can verify that the uploaded Wasm
    99  code did indeed come from the claimed rust code.
   100  
   101  To solve both these issues, we have produced `rust-optimizer`, a docker image to
   102  produce an extremely small build output in a consistent manner. The suggest way
   103  to run it is this:
   104  
   105  ```sh
   106  docker run --rm -v "$(pwd)":/code \
   107    --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
   108    --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
   109    cosmwasm/rust-optimizer:0.10.4
   110  ```
   111  
   112  We must mount the contract code to `/code`. You can use a absolute path instead
   113  of `$(pwd)` if you don't want to `cd` to the directory first. The other two
   114  volumes are nice for speedup. Mounting `/code/target` in particular is useful
   115  to avoid docker overwriting your local dev files with root permissions.
   116  Note the `/code/target` cache is unique for each contract being compiled to limit
   117  interference, while the registry cache is global.
   118  
   119  This is rather slow compared to local compilations, especially the first compile
   120  of a given contract. The use of the two volume caches is very useful to speed up
   121  following compiles of the same contract.
   122  
   123  This produces a `contract.wasm` file in the current directory (which must be the root
   124  directory of your rust project, the one with `Cargo.toml` inside). As well as
   125  `hash.txt` containing the Sha256 hash of `contract.wasm`, and it will rebuild
   126  your schema files as well.
   127  
   128  ### Testing production build
   129  
   130  Once we have this compressed `contract.wasm`, we may want to ensure it is actually
   131  doing everything it is supposed to (as it is about 4% of the original size).
   132  If you update the "WASM" line in `tests/integration.rs`, it will run the integration
   133  steps on the optimized build, not just the normal build. I have never seen a different
   134  behavior, but it is nice to verify sometimes.
   135  
   136  ```rust
   137  static WASM: &[u8] = include_bytes!("../contract.wasm");
   138  ```
   139  
   140  Note that this is the same (deterministic) code you will be uploading to
   141  a blockchain to test it out, as we need to shrink the size and produce a
   142  clear mapping from wasm hash back to the source code.