-
Notifications
You must be signed in to change notification settings - Fork 731
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 branchnextat the time of writing). I personally built the CLI in release mode withjust build-cli-release.
- One chain with chain ID
chain1running ib-go'ssimdbinary (version v7.0.0-rc0 at the time of writing). -
chain1's RPC endpoint runs onhttp://localhost:27000and 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: secp256k1The 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: 20I 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.yamlThis adds the IBC-enabled chain to the solo machine.
We establish an IBC connection with chain1:
> stag core connect chain1When 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:27000client_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:27000connections:
- 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 chain1id: 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.472871ZWe 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:27000client_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:27000channels:
- 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 chain1id: 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.909027ZWe 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 gldWhen the command succeeds, we query the balance of the account on chain1:
> simd q bank balances cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck --node http://localhost:27000balances:
- 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:27000denom_trace:
base_denom: gld
path: transfer/channel-0And 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 gldMinting 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 gldWhen the command succeeds, we query the balance of the account on chain1:
> simd q bank balances cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvck --node http://localhost:27000balances:
- 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:16ZWe 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 chain1When the command succeeds, we can query the channels on chain1:
> simd q ibc channel channels --node http://localhost:27000channels:
- 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
cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacptIf we use the solo machine to query the state stored for chain1:
> stag query chain chain1id: 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.754399ZWe 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:27000We check that the funds are received:
> simd q bank balances cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt --node http://localhost:27000balances:
- 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 cosmos1ay5j4j76xatjwlc2vhnu8mqn48v4hj5hn9kvckWe check again the balance of the interchain account:
> simd q bank balances cosmos1ue2h5v2pd0rlayf6zs7p7hnqcus2uprpsahdvf4q9eenapnsjdvqukacpt --node http://localhost:27000balances:
- 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:16ZSo 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.