mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
doc/testnet: smart contracts deployment documentation added
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
- [Payments](testnet/payment.md)
|
||||
- [Atomic Swap](testnet/atomic-swap.md)
|
||||
- [DAO](testnet/dao.md)
|
||||
- [Contracts](testnet/contract.md)
|
||||
- [DarkIRC](misc/darkirc/darkirc.md)
|
||||
- [Private Message](misc/darkirc/private_message.md)
|
||||
- [Node Configurations](misc/nodes/node-configurations.md)
|
||||
|
||||
267
doc/src/testnet/contract.md
Normal file
267
doc/src/testnet/contract.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Custom Smart Contracts
|
||||
|
||||
Users can deploy their own zero-knowledge contracts, written for the
|
||||
DarkFi [zkVM](../zkas/index.md), becoming anonymous engineers
|
||||
themselves!
|
||||
|
||||
More information about the smart contracts architecture can be found
|
||||
[here](../arch/sc/sc.md).
|
||||
|
||||
## Hello World
|
||||
|
||||
For the porpuses of this guide, an example smart contract is provided,
|
||||
which users can deploy to the testnet and interact with. This is a very
|
||||
simple smart contract simulating a registration ledger, where users can
|
||||
register or remove themselves from it, and each user is represented as
|
||||
the [poseidon hash](../spec/crypto-schemes.md#poseidonhash-function) of their
|
||||
public key.
|
||||
|
||||
First, open another terminal and navigate (from repo root) to the
|
||||
example:
|
||||
|
||||
```shell
|
||||
$ cd example/wasm-hello-world
|
||||
```
|
||||
|
||||
Here, generate the contract `WASM` bincode by executing:
|
||||
|
||||
```shell
|
||||
$ make
|
||||
|
||||
"../../zkas" proof/secret_commitment.zk -o proof/secret_commitment.zk.bin
|
||||
Wrote output to proof/secret_commitment.zk.bin
|
||||
RUSTFLAGS="" cargo build --target=wasm32-unknown-unknown \
|
||||
--release --package wasm_hello_world
|
||||
...
|
||||
Compiling wasm_hello_world v0.0.1 (/home/anon/darkfi/example/wasm-hello-world)
|
||||
Finished `release` profile [optimized] target(s) in 15.90s
|
||||
cp -f target/wasm32-unknown-unknown/release/wasm_hello_world.wasm wasm_hello_world.wasm
|
||||
wasm-strip wasm_hello_world.wasm
|
||||
```
|
||||
|
||||
Apart from the contract, an example client to interact with it is
|
||||
provided, which we also need to compile:
|
||||
|
||||
```shell
|
||||
$ cd client
|
||||
$ make
|
||||
|
||||
RUSTFLAGS="" cargo build --target=x86_64-unknown-linux-gnu --release --package client
|
||||
...
|
||||
Compiling client v0.0.1 (/home/anon/darkfi/example/wasm-hello-world/client)
|
||||
Finished `release` profile [optimized] target(s) in 2m 29s
|
||||
cp -f target/x86_64-unknown-linux-gnu/release/client client
|
||||
```
|
||||
|
||||
Now both the contract and its client are ready to use. Leave this
|
||||
terminal open, as we will come back to it later in the guide, and
|
||||
return back to your `drk` interactive shell.
|
||||
|
||||
## Creating contracts
|
||||
|
||||
Each contract is controlled by a secret key, from which its Contract ID
|
||||
derives. To deploy a smart contract, we need to generate an authority
|
||||
keypair first. The Contract ID shown in the outputs is a placeholder
|
||||
for the one that will be generated from you. In rest of the guide, use
|
||||
the one you generated by replacing the corresponding placeholder. We
|
||||
can create our own contract authority by executing the following
|
||||
command:
|
||||
|
||||
```shell
|
||||
drk> contract generate-deploy
|
||||
|
||||
Generating a new keypair
|
||||
Created new contract deploy authority
|
||||
Contract ID: {CONTRACT_ID}
|
||||
```
|
||||
|
||||
You can list your mint authorities with:
|
||||
|
||||
```shell
|
||||
drk> contract list
|
||||
|
||||
Index | Contract ID | Locked | Lock Height
|
||||
-------+---------------+--------+-------------
|
||||
1 | {CONTRACT_ID} | false | -
|
||||
```
|
||||
|
||||
## Deploy transaction
|
||||
|
||||
Now that we have a contract authority, we can deploy the example
|
||||
contract we compiled earlier using it:
|
||||
|
||||
```shell
|
||||
drk> contract deploy {CONTRACT_ID} example/wasm-hello-world/wasm_hello_world.wasm | broadcast
|
||||
|
||||
[mark_tx_spend] Processing transaction: d0824bb0ecb9b12af69579c01c570c0275e399b80ef10f0a9c645af65bdd0415
|
||||
[mark_tx_spend] Found Money contract in call 1
|
||||
Broadcasting transaction...
|
||||
Transaction ID: d0824bb0ecb9b12af69579c01c570c0275e399b80ef10f0a9c645af65bdd0415
|
||||
```
|
||||
|
||||
Now the transaction should be published to the network. When the
|
||||
transaction is confirmed, the contract history will show its record:
|
||||
|
||||
```shell
|
||||
drk> contract list {CONTRACT_ID}
|
||||
|
||||
Transaction Hash | Type | Block Height
|
||||
------------------+------------+--------------
|
||||
{TX_HASH} | DEPLOYMENT | 34
|
||||
```
|
||||
|
||||
We can redeploy the contract as many times as we want, as long as it's
|
||||
not locked. Each redeployment will show a new record in the contract
|
||||
history. We can also export the deployed data by executing:
|
||||
|
||||
```shell
|
||||
drk> contract export-data {TX_HASH} > wasm_hello_world.dat
|
||||
```
|
||||
|
||||
The exported files contains the `WASM` bincode and instruction data
|
||||
deployed by that transaction, encoded in `base64` as a tuple.
|
||||
|
||||
## Lock transaction
|
||||
|
||||
After we finished deploying our contract and don't require further code
|
||||
changes, we can lock it. This will not allow further deployment
|
||||
transactions, effectively locking the smart contract on-chain code. To
|
||||
lock down the contract, execute:
|
||||
|
||||
```shell
|
||||
drk> contract lock {CONTRACT_ID} | broadcast
|
||||
|
||||
[mark_tx_spend] Processing transaction: 9eee9799d77d0ef1dd115738982296c9c481b4412c75a0a0955fd67d87bfe6a0
|
||||
[mark_tx_spend] Found Money contract in call 1
|
||||
Broadcasting transaction...
|
||||
Transaction ID: 9eee9799d77d0ef1dd115738982296c9c481b4412c75a0a0955fd67d87bfe6a0
|
||||
```
|
||||
|
||||
After the transaction has been confirmed, we will see our contract
|
||||
`Locked` status set to `true`, along with the block height it was
|
||||
locked on:
|
||||
|
||||
```shell
|
||||
drk> contract list
|
||||
|
||||
Index | Contract ID | Locked | Lock Height
|
||||
-------+---------------+--------+-------------
|
||||
1 | {CONTRACT_ID} | true | 36
|
||||
```
|
||||
|
||||
We will also see the lock transaction in its history:
|
||||
|
||||
```shell
|
||||
drk> contract list {CONTRACT_ID}
|
||||
|
||||
Transaction Hash | Type | Block Height
|
||||
------------------+------------+--------------
|
||||
{TX_HASH} | DEPLOYMENT | 34
|
||||
{LOCK_TX_HASH} | LOCK | 36
|
||||
```
|
||||
|
||||
## Interacting with the smart contract
|
||||
|
||||
Now that the contract code is set on-chain and cannot be modified
|
||||
further, let's interact with it using its client!
|
||||
|
||||
> NOTE: This is a very basic example client so secrets keys are used
|
||||
> as plainext for simplicity. Do not run this in a machine with
|
||||
> commands history or in a hostile environment where your secret key
|
||||
> can be exposed.
|
||||
|
||||
First lets generate a new throwaway address to register:
|
||||
|
||||
```shell
|
||||
drk> wallet keygen
|
||||
|
||||
Generating a new keypair
|
||||
New address:
|
||||
{DUMMY_ADDRESS}
|
||||
```
|
||||
|
||||
Set it as the default one in the wallet and grab its secret key:
|
||||
|
||||
```shell
|
||||
drk> wallet addresses
|
||||
|
||||
Key ID | Public Key | Secret Key | Is Default
|
||||
-----------------------+------------------+-----------------------------+------------
|
||||
1 | {NORMAL_ADDRESS} | {NORMAL_ADDRESS_SECRET_KEY} | *
|
||||
...
|
||||
{DUMMY_ADDRESS_INDEX} | {DUMMY_ADDRESS} | {DUMMY_ADDRESS_SECRET_KEY} |
|
||||
|
||||
drk> wallet default-address {DUMMY_ADDRESS_INDEX}
|
||||
```
|
||||
|
||||
### List members
|
||||
|
||||
Let's go to the contract client terminal, and check current members:
|
||||
|
||||
```shell
|
||||
$ ./client -c {CONTRACT_ID} list
|
||||
|
||||
{CONTRACT_ID} members:
|
||||
No members found
|
||||
```
|
||||
|
||||
No one has registered yet, so let's change that!
|
||||
|
||||
### Registration
|
||||
|
||||
Let's go to the contract client terminal, and register ourselves:
|
||||
|
||||
```shell
|
||||
$ ./client -c {CONTRACT_ID} register {DUMMY_ADDRESS_SECRET_KEY} > register.tx
|
||||
```
|
||||
|
||||
The produced transaction doesn't contain a fee, so we need to attach it
|
||||
in our `drk` interactive shell:
|
||||
|
||||
```shell
|
||||
drk> attach-fee < example/wasm-hello-world/client/register.tx | broadcast
|
||||
|
||||
[mark_tx_spend] Processing transaction: 23ea7d01ae16389e71d73fa27748ce1633d39c6b55a4aa31d8f5ba1017a4f840
|
||||
[mark_tx_spend] Found Money contract in call 1
|
||||
Broadcasting transaction...
|
||||
Transaction ID: 23ea7d01ae16389e71d73fa27748ce1633d39c6b55a4aa31d8f5ba1017a4f840
|
||||
```
|
||||
|
||||
After a while, we will see a new member in our contract registry:
|
||||
|
||||
```shell
|
||||
$ ./client -c {CONTRACT_ID} list
|
||||
|
||||
{CONTRACT_ID} members:
|
||||
1. 0x242d4a0dc358e0b61053c28352f666bace79889559b65e91efd1c83c7c817fdd
|
||||
```
|
||||
|
||||
### Deregistration
|
||||
|
||||
To remove ourselves from the registry, we create a deregister
|
||||
transaction with the contract client:
|
||||
|
||||
```shell
|
||||
$ ./client -c {CONTRACT_ID} deregister {DUMMY_ADDRESS_SECRET_KEY} > deregister.tx
|
||||
```
|
||||
|
||||
Then, we attach the fee again and broadcast it to the network:
|
||||
|
||||
```shell
|
||||
drk> attach-fee < example/wasm-hello-world/client/deregister.tx | broadcast
|
||||
|
||||
[mark_tx_spend] Processing transaction: f3304e6f5673d9ece211af6dd85c70ec8c8e85e91439b8cffbcf5387b11de1d0
|
||||
[mark_tx_spend] Found Money contract in call 1
|
||||
Broadcasting transaction...
|
||||
Transaction ID: f3304e6f5673d9ece211af6dd85c70ec8c8e85e91439b8cffbcf5387b11de1d0
|
||||
```
|
||||
|
||||
When the transaction gets confirmed, our registry will not have members
|
||||
again:
|
||||
|
||||
```shell
|
||||
$ ./client -c {CONTRACT_ID} list
|
||||
|
||||
{CONTRACT_ID} members:
|
||||
No members found
|
||||
```
|
||||
@@ -449,7 +449,8 @@ $ ./wallet-balance.sh
|
||||
|
||||
Don't forget that when using this local node, all operations
|
||||
should be executed inside the `contrib/localnet/darkfid-single-node`
|
||||
folder, and `./drk` command to be replaced by `../../../drk -c drk.toml`
|
||||
folder, and `./drk` command to be replaced by
|
||||
`../../../drk -c drk.toml`. All paths should be relative to this one.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ You can check your wallet balance using `drk`:
|
||||
|
||||
```shell
|
||||
drk> wallet balance
|
||||
|
||||
Token ID | Aliases | Balance
|
||||
----------------------------------------------+---------+---------
|
||||
241vANigf1Cy3ytjM1KHXiVECxgxdK4yApddL8KcLssb | DRK | 20
|
||||
|
||||
Reference in New Issue
Block a user