Last active
September 20, 2024 08:02
-
-
Save sainoe/f05710aba34b4bd2647c6501d1bcc770 to your computer and use it in GitHub Desktop.
ICS Permissionless testnet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eux | |
## Prerequisites: | |
# * ICS v6.x | |
# * Hermes v1.10.3+45a29cc00 | |
# User balance of stake tokens | |
USER_COINS="100000000000stake" | |
# Amount of stake tokens staked | |
STAKE="100000000stake" | |
# Node IP address | |
NODE_IP="127.0.0.1" | |
# Home directory | |
HOME_DIR=$HOME | |
# Validator moniker | |
MONIKERS=("coordinator" "alice" "bob") | |
LEAD_VALIDATOR_MONIKER="coordinator" | |
# Hermes will connect to this node on both provider and consumer | |
HERMES_VALIDATOR_MONIKER="bob" | |
PROV_NODES_ROOT_DIR=${HOME_DIR}/nodes/provider | |
CONS_NODES_ROOT_DIR=${HOME_DIR}/nodes/consumer | |
# Base port. Ports assigned after these ports sequentially by nodes. | |
RPC_LADDR_BASEPORT=29170 | |
P2P_LADDR_BASEPORT=29180 | |
GRPC_LADDR_BASEPORT=29190 | |
NODE_ADDRESS_BASEPORT=29200 | |
PPROF_LADDR_BASEPORT=29210 | |
CLIENT_BASEPORT=29220 | |
# Clean start | |
pkill -f interchain-security-pd &> /dev/null || true | |
sleep 1 | |
rm -rf ${PROV_NODES_ROOT_DIR} | |
# Let lead validator create genesis file | |
LEAD_VALIDATOR_PROV_DIR=${PROV_NODES_ROOT_DIR}/provider-${LEAD_VALIDATOR_MONIKER} | |
LEAD_VALIDATOR_CONS_DIR=${CONS_NODES_ROOT_DIR}/consumer-${LEAD_VALIDATOR_MONIKER} | |
LEAD_PROV_KEY=${LEAD_VALIDATOR_MONIKER}-key | |
LEAD_PROV_LISTEN_ADDR=tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# Build genesis file and node directory structure | |
interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} | |
jq ".app_state.gov.params.voting_period = \"10s\" \ | |
| .app_state.gov.params.expedited_voting_period = \"9s\" \ | |
| .app_state.staking.params.unbonding_time = \"86400s\" \ | |
| .app_state.provider.params.blocks_per_epoch = \"5\"" \ | |
${PROV_NODE_DIR}/config/genesis.json > \ | |
${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
sleep 1 | |
# Create account keypair | |
interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 | |
sleep 1 | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
# Add stake to user | |
PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) | |
interchain-security-pd genesis add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test | |
sleep 1 | |
# copy genesis out, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${PROV_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json | |
fi | |
PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) | |
# adjust configs of this node | |
sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml | |
sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml | |
# make address book non-strict. necessary for this setup | |
sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${PROV_NODE_DIR}/config/config.toml | |
# avoid port double binding | |
sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${PROV_NODE_DIR}/config/config.toml | |
# allow duplicate IP addresses (all nodes are on the same machine) | |
sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${PROV_NODE_DIR}/config/config.toml | |
done | |
for MONIKER in "${MONIKERS[@]}" | |
do | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json* ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
# Stake 1/1000 user's coins | |
interchain-security-pd genesis gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER | |
sleep 1 | |
# Copy gentxs to the lead validator for possible future collection. | |
# Obviously we don't need to copy the first validator's gentx to itself | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${PROV_NODE_DIR}/config/gentx/* ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ | |
fi | |
done | |
# Collect genesis transactions with lead validator | |
interchain-security-pd genesis collect-gentxs --home ${LEAD_VALIDATOR_PROV_DIR} --gentx-dir ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ | |
sleep 1 | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
PERSISTENT_PEERS="" | |
for peer_index in "${!MONIKERS[@]}" | |
do | |
if [ $index == $peer_index ]; then | |
continue | |
fi | |
PEER_MONIKER=${MONIKERS[$peer_index]} | |
PEER_PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${PEER_MONIKER} | |
PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_PROV_NODE_DIR}) | |
PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $peer_index)) | |
PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" | |
done | |
# remove trailing comma from persistent peers | |
PERSISTENT_PEERS=${PERSISTENT_PEERS:1} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${PROV_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# copy genesis in, unless this validator is already the lead validator and thus it already has its genesis | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) | |
GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + $index)) | |
NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + $index)) | |
if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then | |
PRPC_LADDR_PORT=$RPC_LADDR_PORT | |
PGRPC_LADDR_PORT=$GRPC_LADDR_PORT | |
fi | |
# Start gaia | |
interchain-security-pd start \ | |
--home ${PROV_NODE_DIR} \ | |
--p2p.persistent_peers ${PERSISTENT_PEERS} \ | |
--rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
--grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ | |
--address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ | |
--p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ | |
--grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & | |
sleep 5 | |
done | |
# Build consumer chain proposal file | |
tee ${PROV_NODE_DIR}/create-consumer-msg.json<<EOF | |
{ | |
"chain_id" : "consumer", | |
"metadata": { | |
"name": "consumer-1-metadata-name", | |
"description":"consumer-1-metadata-description", | |
"metadata": "consumer-1-metadata-metadata" | |
} | |
} | |
EOF | |
sleep 5 | |
TX_RES=$(interchain-security-pd tx provider create-consumer \ | |
${PROV_NODE_DIR}/create-consumer-msg.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y) | |
sleep 5 | |
TX_RES=$(interchain-security-pd q tx --type=hash $(echo $TX_RES | jq -r '.txhash') \ | |
--home ${PROV_NODE_DIR} \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json) | |
echo $TX_RES | jq .code | |
if [ "$(echo $TX_RES | jq -r .code )" != "0" ]; then | |
echo consumer creation failed with code: $(echo $TX_RES | jq .code ) | |
exit 1 | |
fi | |
EVENTS=$(echo $TX_RES | jq -c '.events[]') | |
found=false | |
CONSUMER_ID="" | |
for event in $EVENTS; do | |
type=$(echo "$event" | jq -r '.type') | |
echo $type | |
if [ "$type" = "create_consumer" ]; then | |
attrs=$(echo $event | jq -c '.attributes[]') | |
for attr in $attrs; do | |
key=$(echo "$attr" | jq -r '.key') | |
if [ "$key" = "consumer_id" ]; then | |
CONSUMER_ID=$(echo "$attr" | jq -r '.value') | |
fi | |
done | |
found=true | |
break | |
fi | |
done | |
if [ "$found" = false ]; then | |
echo "consumer creation event not found" | |
exit 1 | |
fi | |
echo "consumer created: $CONSUMER_ID" | |
AUTHORITY=cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn | |
PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) | |
## Grant the consumer ownership to the Gov module | |
tee ${PROV_NODE_DIR}/update-consumer-msg.json<<EOF | |
{ | |
"consumer_id" : "$CONSUMER_ID", | |
"owner_address": "$PROV_ACCOUNT_ADDR", | |
"new_owner_address": "$AUTHORITY", | |
"metadata": $(jq -r '.metadata' ${PROV_NODE_DIR}/create-consumer-msg.json) | |
} | |
EOF | |
TX_RES=$(interchain-security-pd tx provider update-consumer \ | |
${PROV_NODE_DIR}/update-consumer-msg.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y) | |
sleep 5 | |
## Update consumer to TopN by submitting a gov proposal | |
tee ${PROV_NODE_DIR}/consumer_prop.json<<EOF | |
{ | |
"messages": [ | |
{ | |
"@type": "/interchain_security.ccv.provider.v1.MsgUpdateConsumer", | |
"consumer_id": "${CONSUMER_ID}", | |
"owner": "$AUTHORITY", | |
"metadata": $(jq -r '.metadata' ${PROV_NODE_DIR}/create-consumer-msg.json), | |
"initialization_parameters": { | |
"initial_height": { | |
"revision_number": 0, | |
"revision_height": 1 | |
}, | |
"genesis_hash": "2D5C2110941DA54BE07CBB9FACD7E4A2E3253E79BE7BE3E5A1A7BDA518BAA4BE", | |
"binary_hash": "2D5C2110941DA54BE07CBB9FACD7E4A2E3253E79BE7BE3E5A1A7BDA518BAA4BE", | |
"spawn_time": "2023-03-11T09:02:14.718477-08:00", | |
"ccv_timeout_period": "2419200s", | |
"unbonding_period": "2419200s", | |
"transfer_timeout_period": "3600s", | |
"consumer_redistribution_fraction": "0.75", | |
"blocks_per_distribution_transmission": 1500, | |
"historical_entries": 1000, | |
"distribution_transmission_channel": "" | |
}, | |
"power_shaping_parameters": { | |
"top_N": 100, | |
"validators_power_cap": 0, | |
"validator_set_cap": 50, | |
"allowlist": [], | |
"denylist": [], | |
"min_stake": 1000, | |
"allow_inactive_vals": true | |
} | |
} | |
], | |
"metadata": "ipfs://CID", | |
"deposit": "10000000stake", | |
"title": "\"update consumer 0 to top N\"", | |
"summary": "\"update consumer 0 to top N\"", | |
"expedited": false | |
} | |
EOF | |
PROP_ID=1 | |
interchain-security-pd tx gov submit-proposal ${PROV_NODE_DIR}/consumer_prop.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y | |
sleep 3 | |
## Vote yes to proposal | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
# Start gaia | |
interchain-security-pd tx gov vote $PROP_ID yes \ | |
--home ${PROV_NODE_DIR} \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y | |
sleep 1 | |
done | |
sleep 10 | |
## Note that the validators should validate the consumer once the proposal passes | |
# # ## CONSUMER CHAIN ## | |
# # Clean start | |
pkill -f interchain-security-cd &> /dev/null || true | |
sleep 1 | |
rm -rf ${CONS_NODES_ROOT_DIR} | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# Build genesis file and node directory structure | |
interchain-security-cd init $MONIKER --chain-id consumer --home ${CONS_NODE_DIR} | |
sleep 1 | |
# Create account keypair | |
interchain-security-cd keys add $PROV_KEY --home ${CONS_NODE_DIR} --keyring-backend test --output json > ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 | |
sleep 1 | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
fi | |
# Add stake to user | |
CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) | |
interchain-security-cd genesis add-genesis-account $CONS_ACCOUNT_ADDR $USER_COINS --home ${CONS_NODE_DIR} | |
### this probably doesnt have to be done for each node | |
# Add consumer genesis states to genesis file | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
RPC_LADDR=tcp://${NODE_IP}:${RPC_LADDR_PORT} | |
interchain-security-pd query provider consumer-genesis $CONSUMER_ID \ | |
--home ${PROV_NODE_DIR} \ | |
--node ${RPC_LADDR} -o json > consumer_gen.json | |
jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ | |
&& mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
rm consumer_gen.json | |
### | |
# copy genesis out, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${CONS_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json | |
fi | |
PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
# adjust configs of this node | |
sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${CONS_NODE_DIR}/config/config.toml | |
sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${CONS_NODE_DIR}/config/config.toml | |
# make address book non-strict. necessary for this setup | |
sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${CONS_NODE_DIR}/config/config.toml | |
# avoid port double binding | |
sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${CONS_NODE_DIR}/config/config.toml | |
# allow duplicate IP addresses (all nodes are on the same machine) | |
sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${CONS_NODE_DIR}/config/config.toml | |
# Create validator states | |
echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json | |
# Copy validator key files | |
cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json | |
cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json | |
# Set default client port | |
CLIENT_PORT=$(($CLIENT_BASEPORT + ${#MONIKERS[@]} + $index)) | |
sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:${CLIENT_PORT}\"/" ${CONS_NODE_DIR}/config/client.toml | |
done | |
sleep 1 | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
PERSISTENT_PEERS="" | |
for peer_index in "${!MONIKERS[@]}" | |
do | |
if [ $index == $peer_index ]; then | |
continue | |
fi | |
PEER_MONIKER=${MONIKERS[$peer_index]} | |
PEER_CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${PEER_MONIKER} | |
PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_CONS_NODE_DIR}) | |
PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $peer_index)) | |
PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" | |
done | |
# remove trailing comma from persistent peers | |
PERSISTENT_PEERS=${PERSISTENT_PEERS:1} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# copy genesis in, unless this validator is already the lead validator and thus it already has its genesis | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
fi | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + ${#MONIKERS[@]} + $index)) | |
if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then | |
CRPC_LADDR_PORT=$RPC_LADDR_PORT | |
CGRPC_LADDR_PORT=$GRPC_LADDR_PORT | |
fi | |
# Start gaia | |
interchain-security-cd start \ | |
--home ${CONS_NODE_DIR} \ | |
--p2p.persistent_peers ${PERSISTENT_PEERS} \ | |
--rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
--grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ | |
--address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ | |
--p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ | |
--grpc-web.enable=false &> ${CONS_NODE_DIR}/logs & | |
sleep 6 | |
done | |
## Setup Hermes | |
HERMES_PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${HERMES_VALIDATOR_MONIKER} | |
HERMES_KEY=${HERMES_VALIDATOR_MONIKER}-key | |
HERMES_CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${HERMES_VALIDATOR_MONIKER} | |
tee ~/.hermes/config.toml<<EOF | |
[global] | |
log_level = "debug" | |
[mode] | |
[mode.clients] | |
enabled = true | |
refresh = true | |
misbehaviour = true | |
[mode.connections] | |
enabled = false | |
[mode.channels] | |
enabled = false | |
[mode.packets] | |
enabled = true | |
[[chains]] | |
account_prefix = "cosmos" | |
clock_drift = "5s" | |
gas_multiplier = 1.1 | |
grpc_addr = "tcp://${NODE_IP}:${PGRPC_LADDR_PORT}" | |
id = "provider" | |
key_name = "query" | |
max_gas = 20000000 | |
rpc_addr = "http://${NODE_IP}:${PRPC_LADDR_PORT}" | |
rpc_timeout = "10s" | |
store_prefix = "ibc" | |
trusting_period = "14days" | |
event_source = { mode = 'push', url = 'ws://${NODE_IP}:${PRPC_LADDR_PORT}/websocket' , batch_delay = '50ms' } | |
ccv_consumer_chain = false | |
[chains.gas_price] | |
denom = "stake" | |
price = 0.000 | |
[chains.trust_threshold] | |
denominator = "3" | |
numerator = "1" | |
[[chains]] | |
account_prefix = "consumer" | |
clock_drift = "5s" | |
gas_multiplier = 1.1 | |
grpc_addr = "tcp://${NODE_IP}:${CGRPC_LADDR_PORT}" | |
id = "consumer" | |
key_name = "query" | |
max_gas = 20000000 | |
rpc_addr = "http://${NODE_IP}:${CRPC_LADDR_PORT}" | |
rpc_timeout = "10s" | |
store_prefix = "ibc" | |
trusting_period = "14days" | |
event_source = { mode = 'push', url = 'ws://${NODE_IP}:${CRPC_LADDR_PORT}/websocket' , batch_delay = '50ms' } | |
ccv_consumer_chain = true | |
[chains.gas_price] | |
denom = "stake" | |
price = 0.000 | |
[chains.trust_threshold] | |
denominator = "3" | |
numerator = "1" | |
EOF | |
# Delete all previous keys in relayer | |
hermes keys delete --chain consumer --all | |
hermes keys delete --chain provider --all | |
# Restore keys to hermes relayer | |
hermes keys add --key-file ${HERMES_PROV_NODE_DIR}/${HERMES_KEY}.json --chain provider | |
hermes keys add --key-file ${HERMES_CONS_NODE_DIR}/${HERMES_KEY}.json --chain consumer | |
sleep 5 | |
hermes create connection \ | |
--a-chain consumer \ | |
--a-client 07-tendermint-0 \ | |
--b-client 07-tendermint-0 | |
hermes create channel \ | |
--a-chain consumer \ | |
--a-port consumer \ | |
--b-port provider \ | |
--order ordered \ | |
--channel-version 1 \ | |
--a-connection connection-0 | |
sleep 5 | |
## Cause double signing | |
CONS_NODE_SYBIL_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER}-sybil | |
# create directory for double signing node | |
mkdir $CONS_NODE_SYBIL_DIR | |
cp -r $CONS_NODE_DIR/* $CONS_NODE_SYBIL_DIR | |
# clear state in sybil node directory | |
echo '{"height": "0","round": 0,"step": 0,"signature":"","signbytes":""}' \ | |
> $CONS_NODE_SYBIL_DIR/data/priv_validator_state.json | |
# add new node key to sybil | |
# key was generated using gaiad init | |
# if the node key is not unique, double signing cannot be achieved | |
# and errors such as this can be seen in the terminal | |
# 5:54PM ERR found conflicting vote from ourselves; did you unsafe_reset a validator? height=1961 module=consensus round=0 type=2 | |
# 5:54PM ERR failed to process message err="conflicting votes from validator C888306A908A217B9A943D1DAD8790044D0947A4" | |
echo '{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"tj55by/yYwruSz4NxsOG9y9k2WrPvKLXKQdz/9jL9Uptmi647OYpcisjwf92TyA+wCUYVDOgW7D53Q+638l9/w=="}}' \ | |
> $CONS_NODE_SYBIL_DIR/config/node_key.json | |
# does not use persistent peers; will do a lookup in genesis.json to find peers | |
# start double signing node - it should not talk to the node with the same key | |
# Start gaia | |
interchain-security-cd start \ | |
--home ${CONS_NODE_SYBIL_DIR} \ | |
--rpc.laddr tcp://${NODE_IP}:$((RPC_LADDR_PORT+1)) \ | |
--grpc.address ${NODE_IP}:$((GRPC_LADDR_PORT+1)) \ | |
--address tcp://${NODE_IP}:$((NODE_ADDRESS_PORT+1)) \ | |
--p2p.laddr tcp://${NODE_IP}:$((P2P_LADDR_PORT+1)) \ | |
--grpc-web.enable=false &> ${CONS_NODE_SYBIL_DIR}/logs & | |
sleep 5 | |
## start Hermes in evidence mode | |
hermes evidence --chain consumer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -eux | |
## Prerequisites: | |
# * ICS v6.x | |
# * Hermes >= v1.10.3 | |
# User balance of stake tokens | |
USER_COINS="100000000000stake" | |
# Amount of stake tokens staked | |
STAKE="100000000stake" | |
# Node IP address | |
NODE_IP="127.0.0.1" | |
# Home directory | |
HOME_DIR=$HOME | |
# Validator moniker | |
MONIKERS=("coordinator" "alice" "bob") | |
LEAD_VALIDATOR_MONIKER="coordinator" | |
# Hermes will connect to this node on both provider and consumer | |
HERMES_VALIDATOR_MONIKER="bob" | |
PROV_NODES_ROOT_DIR=${HOME_DIR}/nodes/provider | |
CONS_NODES_ROOT_DIR=${HOME_DIR}/nodes/consumer | |
# Base port. Ports assigned after these ports sequentially by nodes. | |
RPC_LADDR_BASEPORT=29170 | |
P2P_LADDR_BASEPORT=29180 | |
GRPC_LADDR_BASEPORT=29190 | |
NODE_ADDRESS_BASEPORT=29200 | |
PPROF_LADDR_BASEPORT=29210 | |
CLIENT_BASEPORT=29220 | |
# Clean start | |
pkill -f interchain-security-pd &> /dev/null || true | |
sleep 1 | |
rm -rf ${PROV_NODES_ROOT_DIR} | |
# Let lead validator create genesis file | |
LEAD_VALIDATOR_PROV_DIR=${PROV_NODES_ROOT_DIR}/provider-${LEAD_VALIDATOR_MONIKER} | |
LEAD_VALIDATOR_CONS_DIR=${CONS_NODES_ROOT_DIR}/consumer-${LEAD_VALIDATOR_MONIKER} | |
LEAD_PROV_KEY=${LEAD_VALIDATOR_MONIKER}-key | |
LEAD_PROV_LISTEN_ADDR=tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# Build genesis file and node directory structure | |
interchain-security-pd init $MONIKER --chain-id provider --home ${PROV_NODE_DIR} | |
jq ".app_state.gov.params.voting_period = \"10s\" \ | |
| .app_state.gov.params.expedited_voting_period = \"9s\" \ | |
| .app_state.staking.params.unbonding_time = \"86400s\" \ | |
| .app_state.provider.params.blocks_per_epoch = \"5\"" \ | |
${PROV_NODE_DIR}/config/genesis.json > \ | |
${PROV_NODE_DIR}/edited_genesis.json && mv ${PROV_NODE_DIR}/edited_genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
sleep 1 | |
# Create account keypair | |
interchain-security-pd keys add $PROV_KEY --home ${PROV_NODE_DIR} --keyring-backend test --output json > ${PROV_NODE_DIR}/${PROV_KEY}.json 2>&1 | |
sleep 1 | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
# Add stake to user | |
PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) | |
interchain-security-pd genesis add-genesis-account $PROV_ACCOUNT_ADDR $USER_COINS --home ${PROV_NODE_DIR} --keyring-backend test | |
sleep 1 | |
# copy genesis out, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${PROV_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json | |
fi | |
PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) | |
# adjust configs of this node | |
sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${PROV_NODE_DIR}/config/config.toml | |
sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${PROV_NODE_DIR}/config/config.toml | |
# make address book non-strict. necessary for this setup | |
sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${PROV_NODE_DIR}/config/config.toml | |
# avoid port double binding | |
sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${PROV_NODE_DIR}/config/config.toml | |
# allow duplicate IP addresses (all nodes are on the same machine) | |
sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${PROV_NODE_DIR}/config/config.toml | |
done | |
for MONIKER in "${MONIKERS[@]}" | |
do | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json* ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
# Stake 1/1000 user's coins | |
interchain-security-pd genesis gentx $PROV_KEY $STAKE --chain-id provider --home ${PROV_NODE_DIR} --keyring-backend test --moniker $MONIKER | |
sleep 1 | |
# Copy gentxs to the lead validator for possible future collection. | |
# Obviously we don't need to copy the first validator's gentx to itself | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${PROV_NODE_DIR}/config/gentx/* ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ | |
fi | |
done | |
# Collect genesis transactions with lead validator | |
interchain-security-pd genesis collect-gentxs --home ${LEAD_VALIDATOR_PROV_DIR} --gentx-dir ${LEAD_VALIDATOR_PROV_DIR}/config/gentx/ | |
sleep 1 | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
PERSISTENT_PEERS="" | |
for peer_index in "${!MONIKERS[@]}" | |
do | |
if [ $index == $peer_index ]; then | |
continue | |
fi | |
PEER_MONIKER=${MONIKERS[$peer_index]} | |
PEER_PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${PEER_MONIKER} | |
PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_PROV_NODE_DIR}) | |
PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $peer_index)) | |
PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" | |
done | |
# remove trailing comma from persistent peers | |
PERSISTENT_PEERS=${PERSISTENT_PEERS:1} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${PROV_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# copy genesis in, unless this validator is already the lead validator and thus it already has its genesis | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_PROV_DIR}/config/genesis.json ${PROV_NODE_DIR}/config/genesis.json | |
fi | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + $index)) | |
GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + $index)) | |
NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + $index)) | |
if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then | |
PRPC_LADDR_PORT=$RPC_LADDR_PORT | |
PGRPC_LADDR_PORT=$GRPC_LADDR_PORT | |
fi | |
# Start gaia | |
interchain-security-pd start \ | |
--home ${PROV_NODE_DIR} \ | |
--p2p.persistent_peers ${PERSISTENT_PEERS} \ | |
--rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
--grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ | |
--address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ | |
--p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ | |
--grpc-web.enable=false &> ${PROV_NODE_DIR}/logs & | |
sleep 5 | |
done | |
# Build consumer chain proposal file | |
tee ${PROV_NODE_DIR}/create-consumer-msg.json<<EOF | |
{ | |
"chain_id" : "consumer", | |
"metadata": { | |
"name": "consumer-1-metadata-name", | |
"description":"consumer-1-metadata-description", | |
"metadata": "consumer-1-metadata-metadata" | |
} | |
} | |
EOF | |
sleep 5 | |
TX_RES=$(interchain-security-pd tx provider create-consumer \ | |
${PROV_NODE_DIR}/create-consumer-msg.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y) | |
sleep 5 | |
TX_RES=$(interchain-security-pd q tx --type=hash $(echo $TX_RES | jq -r '.txhash') \ | |
--home ${PROV_NODE_DIR} \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json) | |
echo $TX_RES | jq .code | |
if [ "$(echo $TX_RES | jq -r .code )" != "0" ]; then | |
echo consumer creation failed with code: $(echo $TX_RES | jq .code ) | |
exit 1 | |
fi | |
EVENTS=$(echo $TX_RES | jq -c '.events[]') | |
found=false | |
CONSUMER_ID="" | |
for event in $EVENTS; do | |
type=$(echo "$event" | jq -r '.type') | |
echo $type | |
if [ "$type" = "create_consumer" ]; then | |
attrs=$(echo $event | jq -c '.attributes[]') | |
for attr in $attrs; do | |
key=$(echo "$attr" | jq -r '.key') | |
if [ "$key" = "consumer_id" ]; then | |
CONSUMER_ID=$(echo "$attr" | jq -r '.value') | |
fi | |
done | |
found=true | |
break | |
fi | |
done | |
if [ "$found" = false ]; then | |
echo "consumer creation event not found" | |
exit 1 | |
fi | |
echo "consumer created: $CONSUMER_ID" | |
AUTHORITY=cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn | |
PROV_ACCOUNT_ADDR=$(jq -r '.address' ${PROV_NODE_DIR}/${PROV_KEY}.json) | |
## Grant the consumer ownership to the Gov module | |
tee ${PROV_NODE_DIR}/update-consumer-msg.json<<EOF | |
{ | |
"consumer_id" : "$CONSUMER_ID", | |
"owner_address": "$PROV_ACCOUNT_ADDR", | |
"new_owner_address": "$AUTHORITY", | |
"metadata": $(jq -r '.metadata' ${PROV_NODE_DIR}/create-consumer-msg.json) | |
} | |
EOF | |
TX_RES=$(interchain-security-pd tx provider update-consumer \ | |
${PROV_NODE_DIR}/update-consumer-msg.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y) | |
sleep 5 | |
## Update consumer to TopN by submitting a gov proposal | |
tee ${PROV_NODE_DIR}/consumer_prop.json<<EOF | |
{ | |
"messages": [ | |
{ | |
"@type": "/interchain_security.ccv.provider.v1.MsgUpdateConsumer", | |
"consumer_id": "${CONSUMER_ID}", | |
"owner": "$AUTHORITY", | |
"metadata": $(jq -r '.metadata' ${PROV_NODE_DIR}/create-consumer-msg.json), | |
"initialization_parameters": { | |
"initial_height": { | |
"revision_number": 0, | |
"revision_height": 1 | |
}, | |
"genesis_hash": "2D5C2110941DA54BE07CBB9FACD7E4A2E3253E79BE7BE3E5A1A7BDA518BAA4BE", | |
"binary_hash": "2D5C2110941DA54BE07CBB9FACD7E4A2E3253E79BE7BE3E5A1A7BDA518BAA4BE", | |
"spawn_time": "2023-03-11T09:02:14.718477-08:00", | |
"ccv_timeout_period": "2419200s", | |
"unbonding_period": "2419200s", | |
"transfer_timeout_period": "3600s", | |
"consumer_redistribution_fraction": "0.75", | |
"blocks_per_distribution_transmission": 1500, | |
"historical_entries": 1000, | |
"distribution_transmission_channel": "" | |
}, | |
"power_shaping_parameters": { | |
"top_N": 100, | |
"validators_power_cap": 0, | |
"validator_set_cap": 50, | |
"allowlist": [], | |
"denylist": [], | |
"min_stake": 1000, | |
"allow_inactive_vals": true | |
} | |
} | |
], | |
"metadata": "ipfs://CID", | |
"deposit": "10000000stake", | |
"title": "\"update consumer 0 to top N\"", | |
"summary": "\"update consumer 0 to top N\"", | |
"expedited": false | |
} | |
EOF | |
PROP_ID=1 | |
interchain-security-pd tx gov submit-proposal ${PROV_NODE_DIR}/consumer_prop.json \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--home $PROV_NODE_DIR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y | |
sleep 3 | |
## Vote yes to proposal | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
# Start gaia | |
interchain-security-pd tx gov vote $PROP_ID yes \ | |
--home ${PROV_NODE_DIR} \ | |
--chain-id provider \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
-o json -y | |
sleep 1 | |
done | |
sleep 10 | |
## Note that the validators should validate the consumer once the proposal passes | |
# # ## CONSUMER CHAIN ## | |
# # Clean start | |
pkill -f interchain-security-cd &> /dev/null || true | |
sleep 1 | |
rm -rf ${CONS_NODES_ROOT_DIR} | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# Build genesis file and node directory structure | |
interchain-security-cd init $MONIKER --chain-id consumer --home ${CONS_NODE_DIR} | |
sleep 1 | |
# Create account keypair | |
interchain-security-cd keys add $PROV_KEY --home ${CONS_NODE_DIR} --keyring-backend test --output json > ${CONS_NODE_DIR}/${PROV_KEY}.json 2>&1 | |
sleep 1 | |
# copy genesis in, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
fi | |
# Add stake to user | |
CONS_ACCOUNT_ADDR=$(jq -r '.address' ${CONS_NODE_DIR}/${PROV_KEY}.json) | |
interchain-security-cd genesis add-genesis-account $CONS_ACCOUNT_ADDR $USER_COINS --home ${CONS_NODE_DIR} | |
### this probably doesnt have to be done for each node | |
# Add consumer genesis states to genesis file | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + $index)) | |
RPC_LADDR=tcp://${NODE_IP}:${RPC_LADDR_PORT} | |
interchain-security-pd query provider consumer-genesis $CONSUMER_ID \ | |
--home ${PROV_NODE_DIR} \ | |
--node ${RPC_LADDR} -o json > consumer_gen.json | |
jq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' ${CONS_NODE_DIR}/config/genesis.json consumer_gen.json > ${CONS_NODE_DIR}/edited_genesis.json \ | |
&& mv ${CONS_NODE_DIR}/edited_genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
rm consumer_gen.json | |
### | |
# copy genesis out, unless this validator is the lead validator | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${CONS_NODE_DIR}/config/genesis.json ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json | |
fi | |
PPROF_LADDR=${NODE_IP}:$(($PPROF_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
# adjust configs of this node | |
sed -i -r 's/timeout_commit = "5s"/timeout_commit = "3s"/g' ${CONS_NODE_DIR}/config/config.toml | |
sed -i -r 's/timeout_propose = "3s"/timeout_propose = "1s"/g' ${CONS_NODE_DIR}/config/config.toml | |
# make address book non-strict. necessary for this setup | |
sed -i -r 's/addr_book_strict = true/addr_book_strict = false/g' ${CONS_NODE_DIR}/config/config.toml | |
# avoid port double binding | |
sed -i -r "s/pprof_laddr = \"localhost:6060\"/pprof_laddr = \"${PPROF_LADDR}\"/g" ${CONS_NODE_DIR}/config/config.toml | |
# allow duplicate IP addresses (all nodes are on the same machine) | |
sed -i -r 's/allow_duplicate_ip = false/allow_duplicate_ip = true/g' ${CONS_NODE_DIR}/config/config.toml | |
# Create validator states | |
echo '{"height": "0","round": 0,"step": 0}' > ${CONS_NODE_DIR}/data/priv_validator_state.json | |
# Copy validator key files | |
cp ${PROV_NODE_DIR}/config/priv_validator_key.json ${CONS_NODE_DIR}/config/priv_validator_key.json | |
cp ${PROV_NODE_DIR}/config/node_key.json ${CONS_NODE_DIR}/config/node_key.json | |
# Set default client port | |
CLIENT_PORT=$(($CLIENT_BASEPORT + ${#MONIKERS[@]} + $index)) | |
sed -i -r "/node =/ s/= .*/= \"tcp:\/\/${NODE_IP}:${CLIENT_PORT}\"/" ${CONS_NODE_DIR}/config/client.toml | |
done | |
sleep 1 | |
for index in "${!MONIKERS[@]}" | |
do | |
MONIKER=${MONIKERS[$index]} | |
PERSISTENT_PEERS="" | |
for peer_index in "${!MONIKERS[@]}" | |
do | |
if [ $index == $peer_index ]; then | |
continue | |
fi | |
PEER_MONIKER=${MONIKERS[$peer_index]} | |
PEER_CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${PEER_MONIKER} | |
PEER_NODE_ID=$(interchain-security-pd tendermint show-node-id --home ${PEER_CONS_NODE_DIR}) | |
PEER_P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $peer_index)) | |
PERSISTENT_PEERS="$PERSISTENT_PEERS,$PEER_NODE_ID@${NODE_IP}:${PEER_P2P_LADDR_PORT}" | |
done | |
# remove trailing comma from persistent peers | |
PERSISTENT_PEERS=${PERSISTENT_PEERS:1} | |
# validator key | |
PROV_KEY=${MONIKER}-key | |
# home directory of this validator on provider | |
PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${MONIKER} | |
# home directory of this validator on consumer | |
CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${MONIKER} | |
# copy genesis in, unless this validator is already the lead validator and thus it already has its genesis | |
if [ $MONIKER != $LEAD_VALIDATOR_MONIKER ]; then | |
cp ${LEAD_VALIDATOR_CONS_DIR}/config/genesis.json ${CONS_NODE_DIR}/config/genesis.json | |
fi | |
RPC_LADDR_PORT=$(($RPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
P2P_LADDR_PORT=$(($P2P_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
GRPC_LADDR_PORT=$(($GRPC_LADDR_BASEPORT + ${#MONIKERS[@]} + $index)) | |
NODE_ADDRESS_PORT=$(($NODE_ADDRESS_BASEPORT + ${#MONIKERS[@]} + $index)) | |
if [ $MONIKER == $HERMES_VALIDATOR_MONIKER ]; then | |
CRPC_LADDR_PORT=$RPC_LADDR_PORT | |
CGRPC_LADDR_PORT=$GRPC_LADDR_PORT | |
fi | |
# Start gaia | |
interchain-security-cd start \ | |
--home ${CONS_NODE_DIR} \ | |
--p2p.persistent_peers ${PERSISTENT_PEERS} \ | |
--rpc.laddr tcp://${NODE_IP}:${RPC_LADDR_PORT} \ | |
--grpc.address ${NODE_IP}:${GRPC_LADDR_PORT} \ | |
--address tcp://${NODE_IP}:${NODE_ADDRESS_PORT} \ | |
--p2p.laddr tcp://${NODE_IP}:${P2P_LADDR_PORT} \ | |
--grpc-web.enable=false &> ${CONS_NODE_DIR}/logs & | |
sleep 6 | |
done | |
## Setup Hermes | |
HERMES_PROV_NODE_DIR=${PROV_NODES_ROOT_DIR}/provider-${HERMES_VALIDATOR_MONIKER} | |
HERMES_KEY=${HERMES_VALIDATOR_MONIKER}-key | |
HERMES_CONS_NODE_DIR=${CONS_NODES_ROOT_DIR}/consumer-${HERMES_VALIDATOR_MONIKER} | |
tee ~/.hermes/config.toml<<EOF | |
[global] | |
log_level = "debug" | |
[mode] | |
[mode.clients] | |
enabled = true | |
refresh = true | |
misbehaviour = true | |
[mode.connections] | |
enabled = false | |
[mode.channels] | |
enabled = false | |
[mode.packets] | |
enabled = true | |
[[chains]] | |
account_prefix = "cosmos" | |
clock_drift = "5s" | |
gas_multiplier = 1.1 | |
grpc_addr = "tcp://${NODE_IP}:${PGRPC_LADDR_PORT}" | |
id = "provider" | |
key_name = "query" | |
max_gas = 20000000 | |
rpc_addr = "http://${NODE_IP}:${PRPC_LADDR_PORT}" | |
rpc_timeout = "10s" | |
store_prefix = "ibc" | |
trusting_period = "14days" | |
event_source = { mode = 'push', url = 'ws://${NODE_IP}:${PRPC_LADDR_PORT}/websocket' , batch_delay = '50ms' } | |
ccv_consumer_chain = false | |
[chains.gas_price] | |
denom = "stake" | |
price = 0.000 | |
[chains.trust_threshold] | |
denominator = "3" | |
numerator = "1" | |
[[chains]] | |
account_prefix = "consumer" | |
clock_drift = "5s" | |
gas_multiplier = 1.1 | |
grpc_addr = "tcp://${NODE_IP}:${CGRPC_LADDR_PORT}" | |
id = "consumer" | |
key_name = "query" | |
max_gas = 20000000 | |
rpc_addr = "http://${NODE_IP}:${CRPC_LADDR_PORT}" | |
rpc_timeout = "10s" | |
store_prefix = "ibc" | |
trusting_period = "14days" | |
event_source = { mode = 'push', url = 'ws://${NODE_IP}:${CRPC_LADDR_PORT}/websocket' , batch_delay = '50ms' } | |
ccv_consumer_chain = true | |
[chains.gas_price] | |
denom = "stake" | |
price = 0.000 | |
[chains.trust_threshold] | |
denominator = "3" | |
numerator = "1" | |
EOF | |
# Delete all previous keys in relayer | |
hermes keys delete --chain consumer --all | |
hermes keys delete --chain provider --all | |
# Restore keys to hermes relayer | |
hermes keys add --key-file ${HERMES_PROV_NODE_DIR}/${HERMES_KEY}.json --chain provider | |
hermes keys add --key-file ${HERMES_CONS_NODE_DIR}/${HERMES_KEY}.json --chain consumer | |
sleep 5 | |
hermes create connection \ | |
--a-chain consumer \ | |
--a-client 07-tendermint-0 \ | |
--b-client 07-tendermint-0 | |
hermes create channel \ | |
--a-chain consumer \ | |
--a-port consumer \ | |
--b-port provider \ | |
--order ordered \ | |
--channel-version 1 \ | |
--a-connection connection-0 | |
sleep 5 | |
# Delegate tokens to validator bob and relay the resulting VSC packet to consumer | |
PROV_VAL_ADDR=$(interchain-security-pd q staking delegations $PROV_ACCOUNT_ADDR \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} \ | |
-o json | jq -r '.delegation_responses[0].delegation.validator_address') | |
interchain-security-pd tx staking delegate $PROV_VAL_ADDR 1000000stake \ | |
--from $PROV_KEY \ | |
--keyring-backend test \ | |
--chain-id provider \ | |
--home ${PROV_NODE_DIR} \ | |
--node tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} \ | |
-y | |
## wait enough for an epoch to elapse | |
sleep 15 | |
hermes clear packets --chain provider --port provider --channel channel-0 | |
sleep 3 | |
## provider and consumer should share the same valset | |
interchain-security-pd q comet-validator-set --node tcp://${NODE_IP}:${RPC_LADDR_BASEPORT} | |
interchain-security-cd q comet-validator-set --node tcp://${NODE_IP}:${CRPC_LADDR_PORT} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment