Skip to content

Deploy contracts

ian edited this page Mar 29, 2024 · 5 revisions

How to use ckb-cli to deploy a contract

1. Initialization config

ckb-cli deploy init-config --deployment-config deployment.toml

After the command is executed, we can find the deployment.toml file. Mainly deal with the file afterwards.

2. The edit deployment.toml file and generate information

We need to fill in a few items, for example:

[[cells]]
name = "compact_udt_lock"
enable_type_id = false
location = { file = "compact_udt_lock" }

[[dep_groups]]
name = "my_dep_group"
cells = []

[lock]
code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
args = "0x6023b5ccbd0c60bb02f0fef669cc2ca7d39fdb11"
hash_type = "type"

File structure notes

cells

Cell required for this transaction

name

Mark the name of the cells for some future business.

enable_type_id

This cell enable type id.

location

The field of this cell can be in the chain, or it can be uploaded locally.

  • If in local, need incoming file, this field cab be relative path.
  • If in chain, need incoming tx_hash and index.

Then execute the following command:

ckb-cli deploy gen-txs \
    --deployment-config ./deployment.toml \
    --migration-dir ./migrations \
    --from-address ckt1qyqxqga4ej7scc9mqtc0aanfesk205ulmvgsl747l8 \
    --sign-now \
    --info-file info.json

The parameter --from-address use the current miner's account. (same afterwards)

dep_groups

The cells that the transaction depends on. If you don’t need it, don’t remove it.

cells

Cells added above.

lock

The lock script information of the transaction. Replace with your own lock if you want to unlock deployed cells. Default is secp256k1

3. Signature

ckb-cli deploy sign-txs \
    --from-account ckt1qyqxqga4ej7scc9mqtc0aanfesk205ulmvgsl747l8 \
    --add-signatures \
    --info-file info.json

4. Apply this transaction

ckb-cli deploy apply-txs --migration-dir ./migrations --info-file info.json

5. Start mining

Note

  • After executing apply-txs, you need to start mining to make this transaction take effect.
  • If you have configured a proxy, you need to be aware that ckb-cli may fail to access local services through the proxy.
  • There may currently be capacity not enough, deposit or mining.

Real world example: deploy and update contract binary with multisig lock

In this example, we will deploy a lock script and a type script from ckb-production-scripts, which are omni_lock and simple_udt. We build out the contract binary and put them in cells directory.

Prepare config (deployment.toml)

First we need init a config file:

ckb-cli deploy init-config --deployment-config deployment.toml
status: success

The init deployment.toml will looks like below:

[[cells]]
name = "my_cell"
enable_type_id = true
location = { file = "build/release/my_cell" }

# reference to on-chain cells, this config is referenced by dep_groups.cells
[[cells]]
name = "genesis_cell"
enable_type_id = false
location = { tx_hash = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", index = 0 }

# Dep group cells
[[dep_groups]]
name = "my_dep_group"
cells = [
  "my_cell",
  "genesis_cell"
]

# The lock script set to output cells
[lock]
code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
args = "0x0000000000000000000000000000000000000000"
hash_type = "type"

# For unlocking inputs with multisig lock script
[multisig_config]
sighash_addresses = [
  "ckt1qyq111111111111111111111111111111111111111",
  "ckt1qyq222222222222222222222222222222222222222",
  "ckt1qyq333333333333333333333333333333333333333",
]
require_first_n = 1
threshold = 2

Then we will edit the deployment.toml file to:

[[cells]]
name = "omni_lock"
enable_type_id = true
location = { file = "cells/omni_lock" }

[[cells]]
name = "simple_udt"
enable_type_id = true
location = { file = "cells/simple_udt" }

# reference to on-chain cells, this config is referenced by dep_groups.cells
[[cells]]
name = "seck256k1_data"
enable_type_id = false
location = { tx_hash = "0x549f8043e001717b2e999c5f1238367516f7bd0dc1be502051f639c274ac266d", index = 3 }

# Dep group cells
[[dep_groups]]
name = "omni_lock_dep_group"
cells = [ "omni_lock", "seck256k1_data" ]

# The lock script set to output cells
[lock]
code_hash = "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8"
args = "0x2c46bc153a7b6da502ab442a115fec13610013f1"
hash_type = "type"

# For unlocking inputs with multisig lock script
[multisig_config]
sighash_addresses = [
  "ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95",
  "ckt1qyqqs022tdfnut49a0hf9fhhss4ae2ky258s6dnz0s",
  "ckt1qyq03qlrzc0lfggp98z87qx7eq6vc5wvxj9qgjuu5u",
]
require_first_n = 0
threshold = 2

There many things changed above, let me explain.

In [cells] section, we added 3 cells:

  1. omni_lock cell represent the binary file location of omni lock script
  2. simple_udt cell represent the binary file location of simple udt type script
  3. secp256k1_data cell represent a reference to an on-chain cell, which is the secp256k1 multiplication table data

The last cell is special, and the location from the output of ckb-cli util genesis-scripts:

dao: ...
secp256k1_blake160_multisig_all: ...
secp256k1_blake160_sighash_all: ...
secp256k1_data:
  out_point:
    index: 3
    tx_hash: 0x549f8043e001717b2e999c5f1238367516f7bd0dc1be502051f639c274ac266d
type_id: ...

Since omni-lock required to work together with secp256k1 data, so we create a dep_group in [dep_groups] section to include omni_lock and secp256k1_data cells.

Then in [lock] section we create a new multisig lock script to setup the output's lock:

ckb-cli tx build-multisig-address \
  --require-first-n 0 \
  --threshold 2 \
  --sighash-address ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95 \
  --sighash-address ckt1qyqqs022tdfnut49a0hf9fhhss4ae2ky258s6dnz0s \
  --sighash-address ckt1qyq03qlrzc0lfggp98z87qx7eq6vc5wvxj9qgjuu5u
lock-arg: ...
lock-hash: ...
mainnet: ...
testnet: ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqfvg67p2wnmdkjs926y9gg4lmqnvyqp8ugep7cp9

ckb-cli util address-info --address ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqfvg67p2wnmdkjs926y9gg4lmqnvyqp8ugep7cp9
extra: ...
lock_script:
  args: 0x2c46bc153a7b6da502ab442a115fec13610013f1
  code_hash: 0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8
  hash_type: type
network: ckb_testnet

Then the [multisig_config] section we add above multisig lock script for future use (update cell binary). NOTE : due to a bug, the address in sighash_addresses list must all be short sighash address before v1.8.0.

Generate the deploy transaction

ckb-cli deploy gen-txs \
  --deployment-config ./deployment.toml \
  --migration-dir ./migrations \
  --from-address ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95 \
  --info-file deploy-tx.json

==== Cell transaction ====
[cell] NewAdded , name:      omni_lock, old-capacity: 0.0, new-capacity: 111390.0
[cell] NewAdded , name:     simple_udt, old-capacity: 0.0, new-capacity: 1822.0
[cell] Reference, name: seck256k1_data, old-capacity: 0.0, new-capacity: 0.0
> old total capacity: 0.0 (CKB) (removed items not included)
> new total capacity: 113212.0 (CKB)
[transaction fee]: 0.00116652
==== DepGroup transaction ====
[dep_group] NewAdded , name: omni_lock_dep_group, old-capacity: 0.0, new-capacity: 137.0
> old total capacity: 0.0 (CKB) (removed items not included)
> new total capacity: 137.0 (CKB)
[transaction fee]: 0.00000577
status: success

Sign and Send the deploy transaction

Since there is no multisig lock script in inputs yet, we just need signature from cell capacity provider.

ckb-cli deploy sign-txs --from-account ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95 --info-file ./deploy-tx.json --add-signatures
Password:
cell_tx_signatures:
  0x21a42eb6f66c0c32409218bdf7c0d88e8d095c6f: 0x9aae70dab973fef5159ac27e62dd3b9c261db15cda695bae2dce3ffd675ca00d422657eb5971bdef1538d22e4bfdc85242a5c8e751d4ef9b65fce3b0c039b90c00
dep_group_tx_signatures:
  0x21a42eb6f66c0c32409218bdf7c0d88e8d095c6f: 0xfe318631a6255e020eca9bd1c8c99a7852e5aebab69a40ae33314d9d7a671d440bc813036c62a255d056db2ef3c6c89700223fa8bdbb3427f684bb72dd47499000

Send the transaction to ckb chain:

ckb-cli deploy apply-txs --info-file ./deploy-tx.json --migration-dir ./migrations
> [send cell transaction]: 0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7
> [send dep group transaction]: 0x3eab12375b95075c79fe6c457e0eaabaa9b41f6796048a0e4b61e57a08c5ab32
cell_tx: 0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7
dep_group_tx: 0x3eab12375b95075c79fe6c457e0eaabaa9b41f6796048a0e4b61e57a08c5ab32

And we will have a recipes file in migrations directory, which is migrations/2022-12-16-080646.json:

{
  "cell_recipes": [
    {
      "name": "omni_lock",
      "tx_hash": "0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7",
      "index": 0,
      "occupied_capacity": 11139000000000,
      "data_hash": "0x4386173157083954d5f253f52a21fcf67b3d3c9deb4bb8f093a2b100a45f823d",
      "type_id": "0x52e7f2633597edf383f9046d8e96649def08cb2dbb5b0ad6dd3b0ef3fd7da210"
    },
    {
      "name": "simple_udt",
      "tx_hash": "0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7",
      "index": 1,
      "occupied_capacity": 182200000000,
      "data_hash": "0xe1e354d6d643ad42724d40967e334984534e0367405c5ae42a9d7d63d77df419",
      "type_id": "0x298eb4f6d8bc4bfbba64bfe5bc4621c6e8305969b16038e0d6fe56051507b59d"
    }
  ],
  "dep_group_recipes": [
    {
      "name": "omni_lock_dep_group",
      "tx_hash": "0x3eab12375b95075c79fe6c457e0eaabaa9b41f6796048a0e4b61e57a08c5ab32",
      "index": 0,
      "data_hash": "0x34feb050df0d55af7dadbbe6737ad1769c4d6ce1084647375f91063050254a8e",
      "occupied_capacity": 13700000000
    }
  ]
}

Then we check all those recipes by getting the metadata of those cells:

# ckb-cli util cell-meta --tx-hash 0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7 --index 0
address: ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqfvg67p2wnmdkjs926y9gg4lmqnvyqp8ugep7cp9
data_hash: 0x4386173157083954d5f253f52a21fcf67b3d3c9deb4bb8f093a2b100a45f823d
lock_hash: 0xa90f0c93310c31215df7639ed10a96a4ef64f8a4a5d714e93a3125b27bfa1cb8
output:
  capacity: 0xa2180235e00
  lock:
    args: 0x2c46bc153a7b6da502ab442a115fec13610013f1
    code_hash: 0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8
    hash_type: type
  type:
    args: 0xf8755a1cebdf2424205f1bad8861ad624411aa292b0e690c3b464d4073dca58b
    code_hash: 0x00000000000000000000000000000000000000000000000000545950455f4944
    hash_type: type
type_hash: 0x52e7f2633597edf383f9046d8e96649def08cb2dbb5b0ad6dd3b0ef3fd7da210

# ckb-cli util cell-meta --tx-hash 0xfc856712001862df1178ea0467cfb459aeecaae3e4ff2f3e3de15bdeec3e36c7 --index 1
address: ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqfvg67p2wnmdkjs926y9gg4lmqnvyqp8ugep7cp9
data_hash: 0xe1e354d6d643ad42724d40967e334984534e0367405c5ae42a9d7d63d77df419
lock_hash: 0xa90f0c93310c31215df7639ed10a96a4ef64f8a4a5d714e93a3125b27bfa1cb8
output:
  capacity: 0x2a6bf75e00
  lock:
    args: 0x2c46bc153a7b6da502ab442a115fec13610013f1
    code_hash: 0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8
    hash_type: type
  type:
    args: 0x7af24b0f1e7d4b7b742db8aea9fa8d68322c995bcd00ce358ddc29f6780d80c1
    code_hash: 0x00000000000000000000000000000000000000000000000000545950455f4944
    hash_type: type
type_hash: 0x298eb4f6d8bc4bfbba64bfe5bc4621c6e8305969b16038e0d6fe56051507b59d

# ckb-cli util cell-meta --tx-hash 0x3eab12375b95075c79fe6c457e0eaabaa9b41f6796048a0e4b61e57a08c5ab32 --index 0
address: ckt1qpw9q60tppt7l3j7r09qcp7lxnp3vcanvgha8pmvsa3jplykxn32sqfvg67p2wnmdkjs926y9gg4lmqnvyqp8ugep7cp9
data_hash: 0x34feb050df0d55af7dadbbe6737ad1769c4d6ce1084647375f91063050254a8e
lock_hash: 0xa90f0c93310c31215df7639ed10a96a4ef64f8a4a5d714e93a3125b27bfa1cb8
output:
  capacity: 0x330956900
  lock:
    args: 0x2c46bc153a7b6da502ab442a115fec13610013f1
    code_hash: 0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876c876320fc9634e2a8
    hash_type: type
  type: ~
type_hash: ~

Generate the update transaction

When contract updated we need to update the cells. We just put the new binary in cells directory and generate the transaction:

ckb-cli deploy gen-txs \
  --deployment-config ./deployment.toml \
  --migration-dir ./migrations \
  --from-address ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95 \
  --info-file update-tx.json

==== Cell transaction ====
[cell] Changed  , name:      omni_lock, old-capacity: 111390.0, new-capacity: 111394.0
[cell] Changed  , name:     simple_udt, old-capacity: 1822.0, new-capacity: 1826.0
[cell] Reference, name: seck256k1_data, old-capacity: 0.0, new-capacity: 0.0
> old total capacity: 113212.0 (CKB) (removed items not included)
> new total capacity: 113220.0 (CKB)
[transaction fee]: 0.00114066
==== DepGroup transaction ====
[dep_group] Changed  , name: omni_lock_dep_group, old-capacity: 137.0, new-capacity: 137.0
> old total capacity: 137.0 (CKB) (removed items not included)
> new total capacity: 137.0 (CKB)
[transaction fee]: 0.00000843
status: success

Sign and Send the update transaction

Sign by cell capacity provider and also the first multisig participant:

ckb-cli deploy sign-txs --from-account ckt1qyqzrfpwkmmxcrpjgzfp300hcrvgargft3hsvn3n95 --info-file ./update-tx.json --add-signatures
Password:
cell_tx_signatures:
  0x21a42eb6f66c0c32409218bdf7c0d88e8d095c6f: 0x3c8dd69f5d70124f04589b48faea48ab72eb79dc0d504fc649613332d0444f917e2e4c52ffc371326b5dfd758e22bb57d854c3712da2d6a8545bac41d0973dec00
  0x2c46bc153a7b6da502ab442a115fec13610013f1: 0xeb3c6d68122f8e88e50c0ae829f9f191421fe5a242700f9371885e9c17f2749d1a985668de61f29250878aca690f0c9bcbc6b86e9114c8582825c7ad09acebcf01
dep_group_tx_signatures:
  0x21a42eb6f66c0c32409218bdf7c0d88e8d095c6f: 0x49322aa0d87e0c83abb3e2f1d34dda8c65aa2d7138e0f4f684a9a036a36a32cd10df4dfbcb2e6b082c3be42433fa644c0395b7961f117b6277d39c3c835fdd9001
  0x2c46bc153a7b6da502ab442a115fec13610013f1: 0x9611e7747460aa0fefde6dfafeee5be8597706869c9278ed19c61babab2e375d23ac8cfbaa348ea151245ceb43c6864e85d9f39ee06c577c6b082fb7672dce1a01

Sign the second multisig participant:

ckb-cli deploy sign-txs --from-account ckt1qyqqs022tdfnut49a0hf9fhhss4ae2ky258s6dnz0s --info-file ./update-tx.json --add-signatures
Password:
cell_tx_signatures:
  0x2c46bc153a7b6da502ab442a115fec13610013f1: 0x98581395c627813c05836b420b74538b0a196335e48e9caba222626877d5f3e139bf1bcb55d7cb1de2298899d1114c287360a138bc840ab516364c1643db33b401
dep_group_tx_signatures:
  0x2c46bc153a7b6da502ab442a115fec13610013f1: 0x960a5b107edcf6f7facffd2cec62df0a3b2cc38af49330df3e56928d2647428d48b02f6908b0779a10cbb158274273cd6d93caa5e48ffa844c037eb4ead05ee201

Send the signed transaction:

ckb-cli deploy apply-txs --info-file ./update-tx.json --migration-dir ./migrations
> [send cell transaction]: 0x1226939511f53f59b928a4f56f417e18230a82bd86d8a2136b18bf25c70f3c58
> [send dep group transaction]: 0x4314bf1d1e734dd17296f4e77ef135379e899a0e27b1138dad37f692be145ca4
cell_tx: 0x1226939511f53f59b928a4f56f417e18230a82bd86d8a2136b18bf25c70f3c58
dep_group_tx: 0x4314bf1d1e734dd17296f4e77ef135379e899a0e27b1138dad37f692be145ca4

And we have a new recipes file in migrations directory, which is migrations/2022-12-16-082327.json:

{
  "cell_recipes": [
    {
      "name": "omni_lock",
      "tx_hash": "0x1226939511f53f59b928a4f56f417e18230a82bd86d8a2136b18bf25c70f3c58",
      "index": 0,
      "occupied_capacity": 11139400000000,
      "data_hash": "0xeb1411f13f41d7853bb7c40333f5340abebd2ac5da12a8594966ca279d1d091f",
      "type_id": "0x52e7f2633597edf383f9046d8e96649def08cb2dbb5b0ad6dd3b0ef3fd7da210"
    },
    {
      "name": "simple_udt",
      "tx_hash": "0x1226939511f53f59b928a4f56f417e18230a82bd86d8a2136b18bf25c70f3c58",
      "index": 1,
      "occupied_capacity": 182600000000,
      "data_hash": "0x12d7f33ac8b8f5cc5072acdb79595f635c5bb59231cf68b97aae771bbee7bbee",
      "type_id": "0x298eb4f6d8bc4bfbba64bfe5bc4621c6e8305969b16038e0d6fe56051507b59d"
    }
  ],
  "dep_group_recipes": [
    {
      "name": "omni_lock_dep_group",
      "tx_hash": "0x4314bf1d1e734dd17296f4e77ef135379e899a0e27b1138dad37f692be145ca4",
      "index": 0,
      "data_hash": "0xd0888aa5fdd1166a814f7fcf0b78fd77472e045f598a8b85fd6167b59accbe9d",
      "occupied_capacity": 13700000000
    }
  ]
}

As you can see, the type_id field of omni_lock and simple_udt is unchanged, which means the lock script is unchanged.