-
Notifications
You must be signed in to change notification settings - Fork 588
IBC solo machine
This is a tutorial that mostly follows crypto.org's IBC solo machine documentation, but adding more details and output results.
- The repository for crypto.org's IBC solo machine. At the time of writing I used the branch
next
, because that's the one that was updated to ibc-go v7.0.0 changes. - IBC solo machine documentation. This is the tutorial that I followed to write this one.
- Pull the solo machine repository and follow the instructions to either build or install
stag
(from branchnext
at the time of writing). I personally built the CLI in release mode withjust build-cli-release
.
- One chain with chain ID
chain1
running ib-go'ssimd
binary (version v7.0.0-rc0 at the time of writing). -
chain1
's RPC endpoint runs onhttp://localhost:27000
and gRPC endpoint runs onhttp://localhost:27002
.
The solo machine requires a file that configure the signer for the chain it connects to. I created a file called signer.yaml
with the following contents:
chains:
- chain_id: chain1
mnemonic: voice orient old radar urge urge dirt put hawk fiscal charge vapor canal garbage broccoli loan fog cash antique during oxygen honey return gentle
hd_path: m/44'/118'/0'/0/0
account_prefix: cosmos
algo: secp256k1
The mnemonic
used is for an account on chain1
. I placed the file in the same directory as the stag
binary.
The solo machine also requires a file with configuration information for the chain it connects to. I created a file called chain.yaml
with the following contents:
grpc_addr: http://localhost:27002
rpc_addr: http://localhost:27000
fee:
amount: '1000'
denom: stake
gas_limit: 300000
trust_level: 1/3
trusting_period: 14days
max_clock_drift: 3s
rpc_timeout: 1m
diversifier: stag
trusted_height: 2
trusted_hash: 7381754AA8BFEDE794E4EF7E639125C653292030E10F37647B14AE724043803D
packet_timeout_height_offset: 20
I chose an arbitrary trusted_height
and picked the trusted_hash
(which is the block hash at the trusted_height
).
I placed the file in the same directory as the stag
binary and run:
> stag core add-chain chain.yaml
This adds the IBC-enabled chain to the solo machine.
We establish an IBC connection with chain1
:
> stag core connect chain1
When the command succeeds, we check that the light client for the solo machine is created on chain1
:
> simd q ibc client state 06-solomachine-0 --node http://localhost:27000
client_state:
'@type': /ibc.lightclients.solomachine.v3.ClientState
consensus_state:
diversifier: stag
public_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: A72+urUIyqjxSST3ptVNc309MgRPbsIPIq0rOqA54Q2x
timestamp: "1676025901"
is_frozen: false
sequence: "4"
proof: CsgCCsUCCiRjbGllbnRzLzA2LXNvbG9tYWNoaW5lLTAvY2xpZW50U3RhdGUSiAEKLC9pYmMubGlnaHRjbGllbnRzLnNvbG9tYWNoaW5lLnYzLkNsaWVudFN0YXRlElgIBBpUCkYKHy9jb3Ntb3MuY3J5cHRvLnNlY3AyNTZrMS5QdWJLZXkSIwohA72+urUIyqjxSST3ptVNc309MgRPbsIPIq0rOqA54Q2xEgRzdGFnGK3AmJ8GGgsIARgBIAEqAwACFCIrCAESBAIEFCAaISBYKtoyywJAdIUgqjGgvknEFy+9fUfwQxVKybOP43wuFyIrCAESBAQIFCAaISAN4qCtohJvN8rxDXl/F30aAdMwno8E7wHG66v0GcUrESIrCAESBAYMFCAaISA3ZLMr0Y+TbE4rGd1C1sMGGc76OzbdV7pt+NCnF8R5ZQr+AQr7AQoDaWJjEiApRvnrfRQnH7JhR5WFmCOFVcQvYGrg79pGvXBIR3YIoRoJCAEYASABKgEAIicIARIBARogxQXA/UixzytlYZ8SsxROGcYLTmtiUl7pNr6T0EFiPr8iJwgBEgEBGiDT9PlIvZOv6t0huJTUCr25G4tHtE/c8cAbNa+ql0HHvyIlCAESIQGIpP7BaQpATeMuv2fLbLd4QUAmHz/dMRhpbs/3cryXKyIlCAESIQGFvC3OCG+IaA28s8GhnzHzWXf80+2uOAlpl5ykrbVg1yInCAESAQEaIFSBVFbas2qPRPRDBJrT3dx155riWOPbGBfpFDMM+HtK
proof_height:
revision_height: "27"
revision_number: "0"
We query the connections on chain1
:
> simd q ibc connection connections --node http://localhost:27000
connections:
- client_id: 06-solomachine-0
counterparty:
client_id: 07-tendermint-zmLS
connection_id: connection-vAKG
prefix:
key_prefix: aWJj
delay_period: "0"
id: connection-0
state: STATE_OPEN
versions:
- features:
- ORDER_ORDERED
- ORDER_UNORDERED
identifier: "1"
height:
revision_height: "37"
revision_number: "0"
pagination:
next_key: null
total: "0"
And we see that the connection has been successfully created. The channel ID on the counterparty is connection-vAKG
.
We also query the solo machine for the current state stored for chain1
:
> stag query chain chain1
id: chain1
node_id: c566ddc717d720afe334a38f5bc937e74ca71f05
config:
grpc_addr: http://localhost:27002/
rpc_addr: http://localhost:27000/
fee:
amount: '1000'
denom: stake
gas_limit: 300000
trust_level: 1/3
trusting_period: 14days
max_clock_drift: 3s
rpc_timeout: 1m
diversifier: stag
trusted_height: 2
trusted_hash: 7381754aa8bfede794e4ef7e639125c653292030e10f37647b14ae724043803d
packet_timeout_height_offset: 20
consensus_timestamp: 2023-02-10T10:45:01Z
sequence: 4
connection_details:
solo_machine_client_id: 07-tendermint-zmLS
tendermint_client_id: 06-solomachine-0
solo_machine_connection_id: connection-vAKG
tendermint_connection_id: connection-0
channels: {}
created_at: 2023-02-10T10:45:01Z
updated_at: 2023-02-10T10:45:24.472871Z
We see that there are no channels created on the connection.
We create a transfer channel between the solo machine and chain1
:
> stag core channel create transfer chain1
When the command succeeds, we can query the solo machine client state on chain1
:
> simd q ibc client state 06-solomachine-0 --node http://localhost:27000
client_state:
'@type': /ibc.lightclients.solomachine.v3.ClientState
consensus_state:
diversifier: stag
public_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: A72+urUIyqjxSST3ptVNc309MgRPbsIPIq0rOqA54Q2x
timestamp: "1676025901"
is_frozen: false
sequence: "5"
proof: CsoCCscCCiRjbGllbnRzLzA2LXNvbG9tYWNoaW5lLTAvY2xpZW50U3RhdGUSiAEKLC9pYmMubGlnaHRjbGllbnRzLnNvbG9tYWNoaW5lLnYzLkNsaWVudFN0YXRlElgIBRpUCkYKHy9jb3Ntb3MuY3J5cHRvLnNlY3AyNTZrMS5QdWJLZXkSIwohA72+urUIyqjxSST3ptVNc309MgRPbsIPIq0rOqA54Q2xEgRzdGFnGK3AmJ8GGgwIARgBIAEqBAACkgEiKggBEiYCBJIBIFQc3cZJM4fEs9e9xBn68EkEJgiPSWPD4gKlBMKIqe8xICIsCAESBQQGkgEgGiEgWCraMssCQHSFIKoxoL5JxBcvvX1H8EMVSsmzj+N8LhciLAgBEgUIFJIBIBohINJay+SseLRzx8ABYl0toJ53XjV6o1B8DHCizlDzrJJfCv4BCvsBCgNpYmMSIIE8IXa+tWDn7pyNfeXARajwGW2hy/Sf+DRrNfijHILnGgkIARgBIAEqAQAiJwgBEgEBGiDFBcD9SLHPK2VhnxKzFE4ZxgtOa2JSXuk2vpPQQWI+vyInCAESAQEaINP0+Ui9k6/q3SG4lNQKvbkbi0e0T9zxwBs1r6qXQce/IiUIARIhAYik/sFpCkBN4y6/Z8tst3hBQCYfP90xGGluz/dyvJcrIiUIARIhAdVw7e54YXhgjRqEFGkrBOUhs8Iosx4UoI0a0DM30zwzIicIARIBARogJQ9fTXSMPDfIRg1891ajVvTpDsSWAhA4QjIgq6FNQzA=
proof_height:
revision_height: "86"
revision_number: "0"
We see that the sequence
has been increased because as part of the channel handshake, when chain1
processes MsgChannelOpenAck
it has to verify the channel state of the counterparty (i.e. the solo machine) and this operation involves performing a membership verification, as part of which the sequence of the client state is increased.
We query the channels on chain1
:
> simd q ibc channel channels --node http://localhost:27000
channels:
- channel_id: channel-0
connection_hops:
- connection-0
counterparty:
channel_id: channel-QQsp
port_id: transfer
ordering: ORDER_UNORDERED
port_id: transfer
state: STATE_OPEN
version: ics20-1
height:
revision_height: "88"
revision_number: "0"
pagination:
next_key: null
total: "0"
And we see that the channel has been successfully created. The channel ID on the counterparty is channel-QQsp
.
We can also use the solo machine to query the current state stored for chain1
:
> stag query chain chain1
id: chain1
node_id: c566ddc717d720afe334a38f5bc937e74ca71f05
config:
grpc_addr: http://localhost:27002/
rpc_addr: http://localhost:27000/
fee:
amount: '1000'
denom: stake
gas_limit: 300000
trust_level: 1/3
trusting_period: 14days
max_clock_drift: 3s
rpc_timeout: 1m
diversifier: stag
trusted_height: 2
trusted_hash: 7381754aa8bfede794e4ef7e639125c653292030e10f37647b14ae724043803d
packet_timeout_height_offset: 20
consensus_timestamp: 2023-02-10T10:45:01Z
sequence: 5
connection_details:
solo_machine_client_id: 07-tendermint-zmLS
tendermint_client_id: 06-solomachine-0
solo_machine_connection_id: connection-vAKG
tendermint_connection_id: connection-0
channels:
transfer:
packet_sequence: 1
solo_machine_port_id: transfer
tendermint_port_id: transfer
solo_machine_channel_id: channel-QQsp
tendermint_channel_id: channel-0
created_at: 2023-02-10T10:45:01Z
updated_at: 2023-02-10T10:50:46.909027Z
We see that packet_sequence
is 1, which is the next sequence receive on chain1
.
We use the solo machine to mint tokens on chain1
:
> stag transfer mint chain1 1000 gld
When the command succeeds, we query the balance of the account on chain1
:
> simd q bank balances cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck --node http://localhost:27000
balances:
- amount: "1000"
denom: ibc/1435A36F8027331ED1935FD47055044A33165F18F22F6270D5312075186F7027
- amount: "100000000"
denom: samoleans
- amount: "99994000"
denom: stake
pagination:
next_key: null
total: "0"
And we see that the balance contains 1000 units of denom ibc/1435A36F8027331ED1935FD47055044A33165F18F22F6270D5312075186F7027
. We convert this IBC denom to denom trace information:
> simd q ibc-transfer denom-trace ibc/1435A36F8027331ED1935FD47055044A33165F18F22F6270D5312075186F7027 --node http://localhost:27000
denom_trace:
base_denom: gld
path: transfer/channel-0
And see that the base denom is gld
, as we expected.
We can also use the solo machine to query the on-chain balance for gld
:
> stag query balance chain1 gld --ibc-denom
current balance: 1000 gld
Minting tokens with the solo machine is achieved by submitting a MsgRecvPacket
to chain1
with the same address for sender and receiver.
We use the solo machine to burn tokens on chain1
:
> stag transfer burn chain1 200 gld
When the command succeeds, we query the balance of the account on chain1
:
> simd q bank balances cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck --node http://localhost:27000
balances:
- amount: "800"
denom: ibc/1435A36F8027331ED1935FD47055044A33165F18F22F6270D5312075186F7027
- amount: "100000000"
denom: samoleans
- amount: "99992000"
denom: stake
pagination:
next_key: null
total: "0"
And see that the balance for ibc/1435A36F8027331ED1935FD47055044A33165F18F22F6270D5312075186F7027
has been reduced by 200 units.
The solo machine also provides a command to fetch the transaction history for a given chain:
> stag query history chain1
- id: 2
request_id: null
chain_id: chain1
port_id: transfer
operation_type:
type: Burn
from: cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
denom: gld
amount: '200'
transaction_hash: B8E3E0ED91D22B2716319BDFA0740EF69F291014DD027E930AD62931B508820D
created_at: 2023-02-10T11:02:33Z
- id: 1
request_id: null
chain_id: chain1
port_id: transfer
operation_type:
type: Mint
to: cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
denom: gld
amount: '1000'
transaction_hash: F7321F2228948C024480BE5732D67B848E214581504F891EB1CACBB97A16B74A
created_at: 2023-02-10T10:54:16Z
We see that we have performed 2 transactions so far with chain1
, and the response includes the hashes of both.
Burning tokens with the solo machine is achieved by submitting a MsgTransfer
to chain1
with the same address for sender and receiver.
We create an interchain accounts channel between the solo machine and chain1
:
> stag core channel create ica chain1
When the command succeeds, we can query the channels on chain1
:
> simd q ibc channel channels --node http://localhost:27000
channels:
- channel_id: channel-1
connection_hops:
- connection-0
counterparty:
channel_id: channel-Dojp
port_id: icacontroller-0
ordering: ORDER_ORDERED
port_id: icahost
state: STATE_OPEN
version: '{"version":"ics27-1","controller_connection_id":"connection-vAKG","host_connection_id":"connection-0","address":"cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt","encoding":"proto3","tx_type":"sdk_multi_msg"}'
- channel_id: channel-0
connection_hops:
- connection-0
counterparty:
channel_id: channel-QQsp
port_id: transfer
ordering: ORDER_UNORDERED
port_id: transfer
state: STATE_OPEN
version: ics20-1
height:
revision_height: "351"
revision_number: "0"
pagination:
next_key: null
total: "0"
We see that there are now 2 channels, one for transfer and one for interchain accounts. From the channel version of the interchain accounts channel we can get the interchain account address cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt
. We also retrieved the interchain account address with the following command on the solo machine:
> stag query ica-address chain1
cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt
If we use the solo machine to query the state stored for chain1
:
> stag query chain chain1
id: chain1
node_id: c566ddc717d720afe334a38f5bc937e74ca71f05
config:
grpc_addr: http://localhost:27002/
rpc_addr: http://localhost:27000/
fee:
amount: '1000'
denom: stake
gas_limit: 300000
trust_level: 1/3
trusting_period: 14days
max_clock_drift: 3s
rpc_timeout: 1m
diversifier: stag
trusted_height: 2
trusted_hash: 7381754aa8bfede794e4ef7e639125c653292030e10f37647b14ae724043803d
packet_timeout_height_offset: 20
consensus_timestamp: 2023-02-10T10:45:01Z
sequence: 9
connection_details:
solo_machine_client_id: 07-tendermint-zmLS
tendermint_client_id: 06-solomachine-0
solo_machine_connection_id: connection-vAKG
tendermint_connection_id: connection-0
channels:
icacontroller-0:
packet_sequence: 1
solo_machine_port_id: icacontroller-0
tendermint_port_id: icahost
solo_machine_channel_id: channel-Dojp
tendermint_channel_id: channel-1
transfer:
packet_sequence: 2
solo_machine_port_id: transfer
tendermint_port_id: transfer
solo_machine_channel_id: channel-QQsp
tendermint_channel_id: channel-0
created_at: 2023-02-10T10:45:01Z
updated_at: 2023-02-10T11:14:24.754399Z
We can also see that there is an interchain accounts channel.
We transfer some funds to the interchain account from another account on chain1
:
> simd tx bank send cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt 2000samoleans \
--keyring-backend test \
--chain-id chain1 \
--home ../../gm/chain1 \
--node http://localhost:27000
We check that the funds are received:
> simd q bank balances cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt --node http://localhost:27000
balances:
- amount: "2000"
denom: samoleans
pagination:
next_key: null
total: "0"
So now we can execute a x/bank
MsgSend
on the interchain account using ICA:
> stag ica bank send chain1 cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck 1000 samoleans
successfully sent 1000 samoleans to cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
We check again the balance of the interchain account:
> simd q bank balances cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt --node http://localhost:27000
balances:
- amount: "1000"
denom: samoleans
pagination:
next_key: null
total: "0"
To check that the balance has been accordingly reduced.
We use the solo machine to fetch the transaction history for chain1
:
> stag query history chain1
- id: 3
request_id: null
chain_id: chain1
port_id: icacontroller-0
operation_type:
type: IcaSend
to: cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
denom: samoleans
amount: '1000'
transaction_hash: 63BEDDF0DB4648A18551E8E76A121CA6711B43451D82DF1C0AE52AFB58216C1B
created_at: 2023-02-10T11:23:44Z
- id: 2
request_id: null
chain_id: chain1
port_id: transfer
operation_type:
type: Burn
from: cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
denom: gld
amount: '200'
transaction_hash: B8E3E0ED91D22B2716319BDFA0740EF69F291014DD027E930AD62931B508820D
created_at: 2023-02-10T11:02:33Z
- id: 1
request_id: null
chain_id: chain1
port_id: transfer
operation_type:
type: Mint
to: cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck
denom: gld
amount: '1000'
transaction_hash: F7321F2228948C024480BE5732D67B848E214581504F891EB1CACBB97A16B74A
created_at: 2023-02-10T10:54:16Z
So that we can see that a third transaction has been added for the ICA message.
We can use the solo machine to close any of the open channels. For example, to close the transfer channel:
> stag core channel close transfer chain1
Closing of the channel works by submitting a MsgChannelCloseConfirm
to chain1
.