diff --git a/.changeset/three-roses-matter.md b/.changeset/three-roses-matter.md new file mode 100644 index 00000000..3a3a6484 --- /dev/null +++ b/.changeset/three-roses-matter.md @@ -0,0 +1,5 @@ +--- +'@confio/relayer': minor +--- + +Added the ability to specify custom gas limits for each chain diff --git a/README.md b/README.md index f35a1fc1..7591ee7a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,16 @@ You can see an example of embedding the relayer in a [webapp below](#Web-App). - RPC addresses of 2 full nodes on compatible, IBC-enabled chains - See [Chain Requirements below](#Chain-Requirements) for details of what chains are supported +## Important Note + +Versions until `v0.1.6` support Cosmos SDK `v0.41.1+`. +From `v0.2.0` on we require Tendermint `v0.34.9+` (which is used in SDK `v0.42.4+`). +If you are connecting to a v0.41 chain, please use the `v0.1.x` relayer. + +With `v0.2.0` we add support for relaying packets in BeginBlock and EndBlock. However, this requires +an extra rpc endpoint in Tendermint that is not available in `v0.41.1`. We therefore increase the +minimum compatible version of the SDK. + ## Installation ### NPM diff --git a/demo/registry.yaml b/demo/registry.yaml index b01cd6e3..705742ff 100644 --- a/demo/registry.yaml +++ b/demo/registry.yaml @@ -19,6 +19,30 @@ chains: # one is down (TODO) rpc: - http://rpc.oysternet.cosmwasm.com:80 + # you can optionally override the gas limits for this chain + # the most important ones here are `receive_packet` and `ack_packet` for custom protocols + # this can be deprecated after https://github.com/confio/ts-relayer/issues/198 is closed + gas_limits: + # max amount of gas to be used when performing client init transactions + init_client: 150000 + # # max amount of gas to be used when performing client update transactions + update_client: 600000 + # max amount of gas to be used when performing connection init transactions + init_connection: 150000 + # max amount of gas to be used when performing connection handshakes transactions + connection_handshake: 300000 + # max amount of gas to be used when performing channel init transactions + init_channel: 150000 + # max amount of gas to be used when performing channel handshakes transactions + channel_handshake: 300000 + # max amount of gas to be used when receiving packets + receive_packet: 300000 + # max amount of gas to be used when receiving acknowledgments + ack_packet: 300000 + # max amount of gas to be used when receiving timeout packets + timeout_packet: 300000 + # max amount of gas to be used when performing transfer transactions + transfer: 180000 local_wasm: chain_id: testing prefix: wasm diff --git a/package.json b/package.json index 28452607..05bc8a13 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "test:lint": "eslint src --ext .ts", "test:prettier": "prettier \"**/*.{ts,md}\" \"scripts/wasmd/*.js\" --list-different", "test:unit": "nyc --silent ava --serial", - "focused-test": "yarn test:unit ./src/lib/cosmwasm.spec.ts", + "focused-test": "yarn test:unit ./src/binary/ibc-setup/commands/connect.spec.ts", "watch:build": "tsc -p tsconfig.json -w", "watch:test": "nyc --silent ava --watch --serial", "cov": "run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html", diff --git a/spec/config.md b/spec/config.md index 0ea435bb..73b237c9 100644 --- a/spec/config.md +++ b/spec/config.md @@ -26,22 +26,52 @@ in a future version (thus all files are versioned as 1). version: 1 chains: - - musselnet: - - chain_id: musselnet-2 - # bech32 prefix for addresses - - prefix: wasm - # this determines the gas payments we make (and defines the fee token) - - gas_price: 0.1umayo - # the path we use to derive the private key from the mnemonic - - hd_path: 44'/108'/0'/1' - # if you include an optional faucet, it will load the relayer with tokens in `ibc-setup init` - - faucet: https://faucet.musselnet.cosmwasm.com - # you can include multiple RPC endpoints and it will rotate through them if - # one is down - - rpc: - - https://rpc.musselnet.cosmwasm.com:443 - - https://rpc.musselnet.aneka.com:443 - - bifrost: + oysternet: + chain_id: oysternet-1 + # Bech32 prefix for addresses + prefix: wasm + # This determines the gas payments we make (and defines the fee token) + gas_price: 0.025usponge + # this defines the gas limits we are going to use + gas_limits: + # max amount of gas to be used when performing client init transactions + init_client: 150000 + # # max amount of gas to be used when performing client update transactions + update_client: + 600000 + # max amount of gas to be used when performing connection init transactions + init_connection: + 150000 + # max amount of gas to be used when performing connection handshakes transactions + connection_handshake: + 300000 + # max amount of gas to be used when performing channel init transactions + init_channel: + 150000 + # max amount of gas to be used when performing channel handshakes transactions + channel_handshake: + 300000 + # max amount of gas to be used when receiving packets + receive_packet: + 300000 + # max amount of gas to be used when receiving acknowledgments + ack_packet: + 300000 + # max amount of gas to be used when receiving timeout packets + timeout_packet: + 300000 + # max amount of gas to be used when performing transfer transactions + transfer: 180000 + # the path we use to derive the private key from the mnemonic + hd_path: 44'/108'/0'/1' + # if you include an optional faucet, it will load the relayer with tokens in `ibc-setup init` + faucet: https://faucet.musselnet.cosmwasm.com + # you can include multiple RPC endpoints and it will rotate through them if + # one is down + rpc: + - https://rpc.musselnet.cosmwasm.com:443 + - https://rpc.musselnet.aneka.com:443 + bifrost: # ... ``` diff --git a/src/binary/ibc-setup/commands/connect.spec.ts b/src/binary/ibc-setup/commands/connect.spec.ts index 2bf09f2a..f8f4a1a1 100644 --- a/src/binary/ibc-setup/commands/connect.spec.ts +++ b/src/binary/ibc-setup/commands/connect.spec.ts @@ -37,6 +37,46 @@ chains: rpc: - http://localhost:26658`; +const registryYamlTooLowGas = ` +version: 1 + +chains: + local_wasm: + chain_id: testing + prefix: wasm + gas_price: 0.025ucosm + rpc: + - http://localhost:26659 + local_simapp: + chain_id: simd-testing + prefix: cosmos + gas_price: 0.025umuon + gas_limits: + # this will fail + init_connection: 40000 + rpc: + - http://localhost:26658`; + +const registryYamlHigherGas = ` +version: 1 + +chains: + local_wasm: + chain_id: testing + prefix: wasm + gas_price: 0.025ucosm + rpc: + - http://localhost:26659 + local_simapp: + chain_id: simd-testing + prefix: cosmos + gas_price: 0.025umuon + gas_limits: + # this will succeed + init_connection: 808000 + rpc: + - http://localhost:26658`; + const app = { src: 'local_wasm', dest: 'local_simapp', @@ -112,3 +152,77 @@ destConnection: .+ t.assert(nextConnectionWasm.connection); t.assert(nextConnectionSimapp.connection); }); + +test.serial('connects two chains fails with too low gas', async (t) => { + const logger = new TestLogger(); + + const ibcClientSimapp = await signingClient(simappChain, mnemonic); + const ibcClientWasm = await signingClient(wasmdChain, mnemonic); + + const allConnectionsWasm = await ibcClientWasm.query.ibc.connection.allConnections(); + const allConnectionsSimapp = await ibcClientSimapp.query.ibc.connection.allConnections(); + + const options: Options = { + home: '/home/user', + mnemonic, + src: 'local_simapp', + dest: 'local_wasm', + srcTrust: null, + destTrust: null, + }; + + fsReadFileSync.returns(registryYamlTooLowGas); + fsWriteFileSync.returns(); + + // this should throw an error when trying to set up the connection + await t.throwsAsync(() => run(options, app, (logger as unknown) as Logger)); + + const nextAllConnectionsWasm = await ibcClientWasm.query.ibc.connection.allConnections(); + const nextAllConnectionsSimapp = await ibcClientSimapp.query.ibc.connection.allConnections(); + // no connection can be made + t.is( + nextAllConnectionsWasm.connections.length, + allConnectionsWasm.connections.length + ); + t.is( + nextAllConnectionsSimapp.connections.length, + allConnectionsSimapp.connections.length + ); +}); + +test.serial('connects two chains with explicit high gas works', async (t) => { + const logger = new TestLogger(); + + const ibcClientSimapp = await signingClient(simappChain, mnemonic); + const ibcClientWasm = await signingClient(wasmdChain, mnemonic); + + const allConnectionsWasm = await ibcClientWasm.query.ibc.connection.allConnections(); + const allConnectionsSimapp = await ibcClientSimapp.query.ibc.connection.allConnections(); + + const options: Options = { + home: '/home/user', + mnemonic, + src: 'local_simapp', + dest: 'local_wasm', + srcTrust: null, + destTrust: null, + }; + + fsReadFileSync.returns(registryYamlHigherGas); + fsWriteFileSync.returns(); + + // this will NOT fail + await run(options, app, (logger as unknown) as Logger); + + const nextAllConnectionsWasm = await ibcClientWasm.query.ibc.connection.allConnections(); + const nextAllConnectionsSimapp = await ibcClientSimapp.query.ibc.connection.allConnections(); + // one connection is made + t.is( + nextAllConnectionsWasm.connections.length, + allConnectionsWasm.connections.length + 1 + ); + t.is( + nextAllConnectionsSimapp.connections.length, + allConnectionsSimapp.connections.length + 1 + ); +}); diff --git a/src/binary/types.ts b/src/binary/types.ts index 3d34aa4c..b7251ea3 100644 --- a/src/binary/types.ts +++ b/src/binary/types.ts @@ -1,9 +1,23 @@ import { GasPrice } from '@cosmjs/stargate'; +export type GasLimits = { + init_client?: number; + update_client?: number; + init_connection?: number; + connection_handshake?: number; + init_channel?: number; + channel_handshake?: number; + receive_packet?: number; + ack_packet?: number; + timeout_packet?: number; + transfer?: number; +}; + export type Chain = { chain_id: string; prefix: string; gas_price: string; + gas_limits?: GasLimits; faucet?: string; hd_path?: string; ics20_port?: string; diff --git a/src/binary/utils/load-and-validate-registry.ts b/src/binary/utils/load-and-validate-registry.ts index f18e6a63..bb0c64a1 100644 --- a/src/binary/utils/load-and-validate-registry.ts +++ b/src/binary/utils/load-and-validate-registry.ts @@ -33,6 +33,24 @@ export function loadAndValidateRegistry(filepath: string): Registry { chain_id: { type: 'string' }, prefix: { type: 'string' }, gas_price: { type: 'string' }, + gas_limits: { + type: 'object', + required: [], + additionalProperties: false, + properties: { + init_client: { type: 'number', nullable: true }, + update_client: { type: 'number', nullable: true }, + init_connection: { type: 'number', nullable: true }, + connection_handshake: { type: 'number', nullable: true }, + init_channel: { type: 'number', nullable: true }, + channel_handshake: { type: 'number', nullable: true }, + receive_packet: { type: 'number', nullable: true }, + ack_packet: { type: 'number', nullable: true }, + timeout_packet: { type: 'number', nullable: true }, + transfer: { type: 'number', nullable: true }, + }, + nullable: true, + }, faucet: { type: 'string', nullable: true }, hd_path: { type: 'string', nullable: true }, ics20_port: { type: 'string', nullable: true }, diff --git a/src/binary/utils/signing-client.ts b/src/binary/utils/signing-client.ts index d1a533f7..87b379b9 100644 --- a/src/binary/utils/signing-client.ts +++ b/src/binary/utils/signing-client.ts @@ -30,6 +30,18 @@ export async function signingClient( const options: IbcClientOptions = { prefix: chain.prefix, gasPrice: GasPrice.fromString(chain.gas_price), + gasLimits: { + initClient: chain.gas_limits?.init_client, + updateClient: chain.gas_limits?.update_client, + initConnection: chain.gas_limits?.init_connection, + connectionHandshake: chain.gas_limits?.connection_handshake, + initChannel: chain.gas_limits?.init_channel, + channelHandshake: chain.gas_limits?.channel_handshake, + receivePacket: chain.gas_limits?.receive_packet, + ackPacket: chain.gas_limits?.ack_packet, + timeoutPacket: chain.gas_limits?.ack_packet, + transfer: chain.gas_limits?.transfer, + }, logger, ...extras, };