Skip to content

Commit

Permalink
Improve README
Browse files Browse the repository at this point in the history
  • Loading branch information
pmikolajczyk41 committed Oct 26, 2023
1 parent 14330cf commit 9ae61fb
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 54 deletions.
130 changes: 76 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,105 @@
[![Built for ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/built-for-ink.svg)](https://github.com/paritytech/ink)

<h1 align="center"> DRink! </h1>
<p align="center"> Dechained Ready-to-play ink! playground </p>
<p align="center"> <b>D</b>echained <b>R</b>eady-to-play <b>ink!</b> playground </p>

https://github.com/Cardinal-Cryptography/drink/assets/27450471/4a45ef8a-a7ec-4a2f-84ab-0a2a36c1cb4e
# What is DRink!?

# What is DRink?
## In brief

DRink! aims to provide support for ink! developers.
It comes in two parts:
1. `drink` library, which provides a minimal Substrate runtime allowing for ink! contracts development together with a facade interface for interacting with it
2. `drink-cli` command line tool, which puts `drink` behind friendly TUI
DRink! is a toolbox for ink! developers that allows for a fully functional ink! contract development without any running node.
It provides you with a unique, yet very powerful environment for interacting with contracts:
- deploy and call your contracts synchronously, **without any delays** related to block production or networking
- gain access to **powerful features** that are not available with standard methods like **contract mocking, enhanced debugging and call tracing**
- work with **multiple contracts** at the same time
- work with **arbitrary runtime** configurations, including custom chain extensions and runtime calls
- have **full control over runtime state**, including block number, timestamp, etc.

# DRink architecture
## In detail

## Motivation
The key concept behind DRink! is to provide a nodeless environment.
To understand it fully, we need to have a high-level overview of the Substrate architecture.

Actually, there are already some great tools for local contracts development like [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node) or [swanky](https://github.com/AstarNetwork/swanky-cli).
However, they all rely on a running node, which is not always convenient.
Especially in the early stage, when you want to test your contract quickly and don't want to bother with setting up a node, networking issues, block time, etc.
_Note: While here we use Substrate-specific terms, these concepts are pretty universal and apply to at least most of the blockchain designs._

For testing purposes, ink! 4.x provides an awesome framework, but in some complex cases, it is still not enough.
For example, working with multiple contracts with different environments is not possible yet.
And still, unless you are working with off-chain execution, there's a node running behind the scenes.
### 'Blockchain onion'

## Solution
<img src="resources/blockchain-onion.svg">

We work with minimal sufficient architecture that allows for a fully functional ink! contract development.
The only thing we need is a Substrate runtime with a contract pallet.
Having put it into `TextExternalities` we are ready to deploy and interact with contracts.
It's just like working within pallet's unit tests.
Any blockchain network participant runs a single binary, which is usually called a _node_ or a _host_.
It is responsible for the fundamental operations like:
- communication with other nodes (networking protocols, information dissemination, gossiping, etc.)
- block production and finalization (consensus, block authoring, etc.)
- storage (blockchain state, database, etc.)
- sometimes also transaction pool, RPC, etc.

# How to use DRink?
When it receives a new transaction (or a block), it has to update the blockchain state.
For that, it uses a _state transition function_, called a _runtime_.
This is an auxiliary binary, which serves as the core logic function, taking as an input the current state and a transaction, and returning the updated state.

You can use DRink in two ways.
In case the transaction is some smart contract interaction, the runtime has to execute it within an _isolated environment_.
(This is where the _contract pallet_ comes into play and spawns a dedicated sandbox.)

### Directly as a library from your e2e tests
As a result, we have a layered architecture resembling an onion (actually, there are a few layers more, but we don't need to dig that deep).

```rust
let mut sandbox = Sandbox::new().unwrap();
### Testing strategies

let contract_bytes = fs::read("path/to/contract.wasm").unwrap();
let address = sandbox.deploy_contract(contract_bytes, compute_selector("new"), Default::default());
let result = sandbox.call_contract(address, compute_selector("foo"));
```
Depending on the part of technology stack involved, we can derive three main testing strategies for smart contracts.

<img src="resources/testing-strategies.svg">


Before DRink!, you could have used ink!'s native test framework to execute either unit tests (with `#[ink::test]` macro) or end-to-end tests (with `#[ink_e2e::test]` macro).
DRink! enabled the third option, i.e. _quasi-end-to-end_ testing.

### quasi-E2E testing

This paradigm is a peculiar compromise between the two other strategies.
We give up the node layer (including networking, block production etc.), but we still have a fully functional runtime with attached storage.
In other words, we keep bare blockchain state in-memory, and we can interact with it directly however we want.

### Via the `drink-cli` command line tool
This way, we gain full control over the runtime, sacrificing real simulation of the blockchain environment.
However, usually, this is higly beneficial for the development process, as it allows for a much faster feedback loop, assisted with better insights into execution externalities.

#### Dependencies
---

The only requirement for running DRInk! is having Rust installed. The code was tested with version `1.69.0-nightly`. All other dependencies are managed by Cargo and will be installed upon running `cargo build` or `cargo run`.
# How to use DRink!?

#### Running DRInk! CLI
You can use DRink! in three ways:

When you run the binary (`cargo run --release`) you'll see a DRink! TUI. You can also choose to start from a specific path by supplying the `--path` argument like:
```bash
cargo run --release -- --path <absolute path to e.g. example/flipper>
## Directly as a library

This way you gain access to full DRink! power in your test suites.
Check our helpful and verbose examples in the [examples](examples) directory.

`drink` library is continuously published to [crates.io](https://crates.io/crates/drink), so you can use it in your project with either `cargo add drink` or by adding the following line to your `Cargo.toml`:
```toml
drink = { version = "0.5" }
```

### CLI modes
Full library documentation is available at: https://docs.rs/drink.

## As an alternative backend to ink!'s E2E testing framework

DRink! is already integrated with ink! and can be used as a drop-in replacement for the standard E2E testing environment.
Just use corresponding argument in the test macro:
```rust
#[ink_e2e::test(backend = "runtime_only")]
```
to your test function and you have just switched from E2E testcase to quasi-E2E one, that doesn't use any running node in the background!

In a somewhat Vim-inspired way, the `drink-cli` allows you to work in two modes: the Managing mode and the Drinking mode.
For a full example check out [ink! repository](https://github.com/paritytech/ink/blob/master/integration-tests/e2e-runtime-only-backend/lib.rs).

#### Managing mode
## With a command line tool

This is the default mode, facilitating high-level interactions with the TUI itself.
At any point, you can enter it by pressing the `Esc` key. Once in the Managing mode:
- Press `h` to see a list of available commands with their brief descriptions;
- Press `q` to quit the TUI;
- Press `i` to enter the Drinking mode.
We provide a CLI which puts DRink! behind friendly TUI.
Below you can find a short demo of how it works.
For more details, consult [its README](drink-cli/README.md).

#### Drinking mode
https://github.com/Cardinal-Cryptography/drink/assets/27450471/4a45ef8a-a7ec-4a2f-84ab-0a2a36c1cb4e

This is the mode where you can interact with your environment and type your commands inside the `User input` field. When in Managing mode, you can enter the Drinking mode by pressing 'i' on your keyboard.
You have several commands at your disposal (you can list them in the Managing mode by pressing the 'h' key):
- `cd` and `clear` will, just like their Bash counterparts, change the directory and clear the output, respectively. You will see the current working directory as the first entry in the `Current environment` pane;
- `build` command will build a contract from the sources in the current directory;
- `deploy` command will deploy a contract from the current directory. Note that if your constructor takes arguments, you will need to supply them to this command, like: `deploy true` in the case of the Flipper example;
- by pressing `Tab` you can switch between all deployed contracts (with automatic directory change);
- `call` command will call a contract with the given message. Again, if the message takes arguments, they need to be supplied here;
- `next-block` command will advance the current block number;
- `add-tokens` command will add tokens to the given account.
Similarly to `drink` library, `drink-cli` is published to [crates.io](https://crates.io/crates/drink-cli) as well.
You can install it with:
```shell
cargo install drink-cli
```
44 changes: 44 additions & 0 deletions drink-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<h1 align="center"> DRink! CLI </h1>

https://github.com/Cardinal-Cryptography/drink/assets/27450471/4a45ef8a-a7ec-4a2f-84ab-0a2a36c1cb4e

We provide this simple command line tool to help you play with your local contracts in a convenient way.

# Dependencies

The only requirement for running DRInk! is having Rust installed. The code was tested with version `1.70`.
All other dependencies are managed by Cargo and will be installed upon running `cargo build` or `cargo run`.

# Running DRInk! CLI

When you run the binary (`cargo run --release`) you'll see a DRink! TUI.
You can also choose to start from a specific path by supplying the `--path` argument like:
```bash
cargo run --release -- --path <absolute path to e.g. example/flipper>
```

## CLI modes

In a somewhat Vim-inspired way, the `drink-cli` allows you to work in two modes: the Managing mode and the Drinking mode.

### Managing mode

This is the default mode, facilitating high-level interactions with the TUI itself.
At any point, you can enter it by pressing the `Esc` key. Once in the Managing mode:
- Press `h` to see a list of available commands with their brief descriptions;
- Press `q` to quit the TUI;
- Press `i` to enter the Drinking mode.

### Drinking mode

This is the mode where you can interact with your environment and type your commands inside the `User input` field.
When in Managing mode, you can enter the Drinking mode by pressing 'i' on your keyboard.

You have several commands at your disposal (you can list them in the Managing mode by pressing the 'h' key):
- `cd` and `clear` will, just like their Bash counterparts, change the directory and clear the output, respectively. You will see the current working directory as the first entry in the `Current environment` pane;
- `build` command will build a contract from the sources in the current directory;
- `deploy` command will deploy a contract from the current directory. Note that if your constructor takes arguments, you will need to supply them to this command, like: `deploy true` in the case of the Flipper example;
- by pressing `Tab` you can switch between all deployed contracts (with automatic directory change);
- `call` command will call a contract with the given message. Again, if the message takes arguments, they need to be supplied here;
- `next-block` command will advance the current block number;
- `add-tokens` command will add tokens to the given account.

0 comments on commit 9ae61fb

Please sign in to comment.