4ca40fd3bc
* Starting on cosmwasm smart contracts * Mixnet contract now builds * Removing license and notice files, the monorepo already has these. * Removing generated README content * Simplified development instructions a bit. * Converted some network monitor files to use SPDX license headers * Renamed packaget to mixnet-contracts * Depending on the Nym topology crate * Renaming contract package in usage * Renamed "announce" to "register_node" in the defined messages * Fixed package name for mixnet contracts in defined release annotations * Added the mixnet contracts to the Cargo lock file * Renamed some fields in our contract topology * Using the stringy mixnode from the validator client. * Removing mix nodes count from state, we can infer that * Saving generated code in comment as it's a useful example for now * Renamed "count" to "get_topology" * Adding the beginnings of a validator client (in Typescript) * Starting to integrate example code. WIP. * Ignoring generated accounts * Making a few less mixnodes :) * Adding shebang to start script * Cranking up the Nym-related gas limits, as otherwise contract upload fails. * Simplest mixnode example is now working * Removing the external client code, it messed up wasm compilation. Will copy/paste for now. * Contract now wants to add a MixNode rather than an IP string * Adding mixnodes via contract now works (!) * Simplified mixnode registration example * Further mixnode-adding simplification. * Adding author name * Fixed description * Sent funds are now required to bond a mixnode * Ensuring that we send correct coin denomination * Unbonding now works (!). Quite primitivist. * Checking that unbonding works from the client. * Setting up a thief account to play with * Checking to see whether thief can unbond a node (it fails, happily) * Adding a more specific error for when an account attempts to unbond but owns no bonds * Figured out how to test contract balances * Set the console messages to explain things a little more nicely * Tests for insufficient funds result * Using more async in driver example * Added a bit more explanation of the actions taken by the driver example * Locking down wasm instantiate a bit more * Docs clarifications on how to run example * README clarification * Corrected the commit hash in the wasmd build command, it was still set for 0.14.0 * Moved models from types into state * Starting work on range queries * whitespace * Going back to slow but reliabel node uploads and disabling new contract upload * Cranking gas fees temporarily * Mixnode key retrieval working and tested * Range retrievals now working well * Removing unused clone * Compressing tests a bit * Testing node retrieval on large numbers of nodes. Not sure whether MockStorage has the same space limitations as production storage does. * Getting rid of spelling warning * Removing unused responses * Minor cleanup * Starting to map my way out of the tuples * Slightly more meaningful variable names * Returning a StdResult from nodes query * Fighting through the unwraps :) * Unfucking a bit more * Starting to use ranged nodes in contract * Testing node retrieval from range store * Ditching generated tests * Adding works, still need to test removing mixnodes * Attempting to remove a mixnode returns an error when no nodes exist * Un-registering when no accounts exist (edit) * un-registering someone else's mixnode fails * Ensuring proper ownership * Testing for only 1 mixnode getting deleted * Testing single-node retrieval * Removing mixnode working * Removed unused imports and unused variable warnings * Made handler functions private * Tested for error response on mixnode removal * Ensured proper post-state on mixnode removal * Using Vec<Coin> for currency equality comparisons * Removed todo, this amount is only for logging purposes anyway * Refactoring tests a bit * Adding a few storytelling comments * Putting helper methods into alphabetical order * Drying up mixnode adding in tests * Using the new add_mixnode helper * Checking full object equality in test * Removing the GetNodes handler * Taking a more "storytelling" approach to the contract tests * We need a few more methods to run our example driver * We now need to make a new address for each node we want to have, as each sending account can only have one node * HumanAddr not needed * Making call sequence a little more readable * Added the results of today's experiments with the REST API to the validator client readme * Corrected console.log message * Adding a note about how to run tests * More contract exercising fun * Updating mocha * Whitespace * Adding a note about running tests * Adding typed rest client * Starting to mess with typescript paging client * Removing the rest client, we'll use the cosmjs one for this * Noting a few more contract requirements * Starting client restructuring * Importing cosmjs stargate client * Starting to work on the chain cache * Cleanup * Removing type annotations which hilariously worked, confusing the compiler * Might as well do each cache individually * Renaming chaincache so that it handles only mixnodes * Renaming chaincache * Setting dynamic per-page value to ease testing * Using perPage in tests * Moving tests back into their own special home so they don't bloat our package * Ignoring generated docs * Adding TypeDoc documentation generator * Removing unused NetClient import * Added docs generation * Noting existence of docs generation * Starting to test paged responses * Working paging tests * Clarified test names a bit * Removed console.logs * Added a test for two full pages. * Formatting * Starting to query for mix nodes * Removed the topology in preparation for paging * Removing unused struct * Getting ready for series-based paging * We're now setting page size limits on list retrievals * Pagination starting to work, needs more testing * Moved test support stuff into its own home * Removing duplicate testy code * Testing all paging stuff in the contract * Removed useless method duplicate * Moving queries into their own file * Removing redundant tests * Testing default paging limit * Testing max paging limit * We don't need to c/p pagination stuff from the cw-plus contracts, removing * Testing pagination * Making next key calculation explict via a function * Removing temporary variable * Commenting final state * Incorporating the PagedResponse * On the road to a working TypeScript client * Adding some logging utilities * Paged retrieval working but needs improvement - it's very brittle * Getting the loop right * Removing unused logger * Setting up a request count * Documenting the ins and outs of the client network interface * Removing requestCount as we're not using it yet * Success! Making paginated requests for mixnodes! * Differentiating between MixNode and MixNodeBond * Checking that Fred can upload a mixnode * Fixing export * Adding the ability for client to get balances * Docs fix * Converting interfaces to types * Changing `mixNodes()` to `getMixNodes()` on client * We might as well return the nodes we've just retrieved when we refresh * Starting work on unbonding * Fixed a caching bug which was causing multiple result sets to be cached * Using the sender address as the key for removal * Importing some result stuff so we can find out what happened on execution * Minor messing around to prove that the sequence fully works * Displaying a nicer message on mixnode unbond * Renamed announce to bond in validator client * Fixed unstable clippy warnings * Removing commented fields * Comment spacing * Changed announce to bond in example code * Making the test accounts directory configurable * Rebuilt * Loading keys from the local ./accounts directory * Ignoring contract lockfile * Saving out a contract lockfile so things continue working after contract upload * Splitting the driver example into smaller self-contained examples * Deleting the example that Andrew hates so much * Making dependabot happy * Stricter equals * Removing unused import
96 lines
3.8 KiB
Markdown
96 lines
3.8 KiB
Markdown
# Developing
|
|
|
|
You probably could use some help on how to build and test the contract, as well as prepare it for production. This
|
|
file attempts to provide a brief overview, assuming you have installed a recent
|
|
version of Rust already (eg. 1.47.0+).
|
|
|
|
## Prerequisites
|
|
|
|
Before starting, make sure you have [rustup](https://rustup.rs/) along with a
|
|
recent `rustc` and `cargo` version installed. Currently, we are testing on 1.44.1+.
|
|
|
|
And you need to have the `wasm32-unknown-unknown` target installed as well.
|
|
|
|
You can check that via:
|
|
|
|
```sh
|
|
rustc --version
|
|
cargo --version
|
|
rustup target list --installed
|
|
# if wasm32 is not listed above, run this
|
|
rustup target add wasm32-unknown-unknown
|
|
```
|
|
|
|
## Compiling and running tests
|
|
|
|
Now that you created your custom contract, make sure you can compile and run it before
|
|
making any changes. Go into the repository and do:
|
|
|
|
```sh
|
|
# this will produce a wasm build in ./target/wasm32-unknown-unknown/release/YOUR_NAME_HERE.wasm
|
|
cargo wasm
|
|
|
|
# this runs unit tests with helpful backtraces
|
|
RUST_BACKTRACE=1 cargo unit-test
|
|
|
|
# auto-generate json schema
|
|
cargo schema
|
|
```
|
|
|
|
### Understanding the tests
|
|
|
|
The main code is in `src/contract.rs` and the unit tests there run in pure rust,
|
|
which makes them very quick to execute and give nice output on failures, especially
|
|
if you do `RUST_BACKTRACE=1 cargo unit-test`.
|
|
|
|
We consider testing critical for anything on a blockchain, and recommend to always keep
|
|
the tests up to date.
|
|
|
|
## Generating JSON Schema
|
|
|
|
While the Wasm calls (`init`, `handle`, `query`) accept JSON, this is not enough
|
|
information to use it. We need to expose the schema for the expected messages to the
|
|
clients. You can generate this schema by calling `cargo schema`, which will output
|
|
4 files in `./schema`, corresponding to the 3 message types the contract accepts,
|
|
as well as the internal `State`.
|
|
|
|
These files are in standard json-schema format, which should be usable by various
|
|
client side tools, either to auto-generate codecs, or just to validate incoming
|
|
json wrt. the defined schema.
|
|
|
|
## Preparing the Wasm bytecode for production
|
|
|
|
Before we upload it to a chain, we need to ensure the smallest output size possible,
|
|
as this will be included in the body of a transaction. We also want to have a
|
|
reproducible build process, so third parties can verify that the uploaded Wasm
|
|
code did indeed come from the claimed rust code.
|
|
|
|
To solve both these issues, we have produced `rust-optimizer`, a docker image to
|
|
produce an extremely small build output in a consistent manner. The suggest way
|
|
to run it is this:
|
|
|
|
```sh
|
|
docker run --rm -v "$(pwd)":/code \
|
|
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
|
|
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
|
|
cosmwasm/rust-optimizer:0.10.7
|
|
```
|
|
|
|
We must mount the contract code to `/code`. You can use a absolute path instead
|
|
of `$(pwd)` if you don't want to `cd` to the directory first. The other two
|
|
volumes are nice for speedup. Mounting `/code/target` in particular is useful
|
|
to avoid docker overwriting your local dev files with root permissions.
|
|
Note the `/code/target` cache is unique for each contract being compiled to limit
|
|
interference, while the registry cache is global.
|
|
|
|
This is rather slow compared to local compilations, especially the first compile
|
|
of a given contract. The use of the two volume caches is very useful to speed up
|
|
following compiles of the same contract.
|
|
|
|
This produces an `artifacts` directory with a `PROJECT_NAME.wasm`, as well as
|
|
`checksums.txt`, containing the Sha256 hash of the wasm file.
|
|
The wasm file is compiled deterministically (anyone else running the same
|
|
docker on the same git commit should get the identical file with the same Sha256 hash).
|
|
It is also stripped and minimized for upload to a blockchain (we will also
|
|
gzip it in the uploading process to make it even smaller).
|