diff --git a/CHANGELOG.md b/CHANGELOG.md index a13b39ce..68dea4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,105 +2,60 @@ All notable changes to this project will be documented in this file. -## [1.1.0] - 2024-03-18 - -### Added - -- Support for cosmos chain -- Xcall contract support -- CallMessage event listener for all supported chains -- Fee related operations cmd. `getFee`, `setFee` and `claimFee` -- Structured events for easier event handling - -### Changed - -- Wallet encryption and decryption -- GO version to 1.22.1 +## [1.2.6] - 2024-05-26 ### Fixed -- Incorrect icon chain balance calculation. -- SetAdmin also checks for the admin address to avoid setting the admin address to the same address. -- Retries is less error prone now, only retries after set interval (5s) when failed. -- Fixed the issue when initilizing config file. - -### Migration from 1.0.0 to 1.1.0 - -We have added support for cosmos chains and xcall contract support. To migrate from 1.0.0 to 1.1.0, you need to update the configuration file and add the cosmos chain details. The configuration file is backward compatible, so you can add the cosmos chain details without affecting the existing configuration. - -Major changes in this release is the wallet encryption and decryption. Previously we only encrypted the keystore password, now we encrypt the entire keystore file adding an extra layer of security. The relay will automatically decrypt the keystore file and use it to sign the messages. - -We have also added the xcall execution contract support. The relay will now listen to the call message event and execute the xcall contract. - -Exection will respect the fees set on configuration. The relay will now calculate the fees and execute the contract. - -Migrate keystore files to the new format by running the following command: - -**important**: Before running the command, make sure you have the AWS KMS key id. You can get the KMS key id by running the `crly config show` command. - -```shell -aws kms encrypt --key-id --plaintext fileb://path/to/keystore.json --output text --query CiphertextBlob | base64 -d > path/to/keystore/address -``` +- Cosmos contracts subscriptions respects the configured contracts +- RPC failures are are handled more elegently, switches to the polling and back to the subscriptions +- Other improvements and bug fixes -Example when migrating the icon chain keystore file where its nid is `0x2.icon` and the wallet address is `0x0B958dd815195F73d6B9B91bFDF1639457678FEb`: +### Refactor -verify keystore exists: +- Icon `progressInterval` notification block is not incremented to handle rpc failures -```shell -ls $HOME/.centralized-relay/keystore/0x2.icon/0x0B958dd815195F73d6B9B91bFDF1639457678FEb.json -``` +## [1.2.5] - 2024-05-18 -Encrypt the keystore file: +### Fixed -```shell -aws kms encrypt --key-id --plaintext fileb://$HOME/.centralized-relay/keystore/0x2.icon/0x0B958dd815195F73d6B9B91bFDF1639457678FEb.json --output text --query CiphertextBlob | base64 -d > "$HOME/keystore/0x2.icon/0x0B958dd815195F73d6B9B91bFDF1639457678FEb" -``` +- Wrong params sent when estimating gas for the evm chain `executeCall` -Move the encrypted wallet passphrase to the new location: +## [1.2.4] - 2024-05-17 - ```shell - mv $HOME/keystore/0x2.icon/0x0B958dd815195F73d6B9B91bFDF1639457678FEb.password $HOME/.centralized relay/keystore/0x2.icon/0x0B958dd815195F73d6B9B91bFDF1639457678FEb.pass - ``` +### Added -### Additional Information +- Support for the injective chain -- All the keystore relayer files are located in the `keystore` directory. - `ls $HOME/.centralized-relay/keystore` +### Fixed -- The version `1.0.0` keystore files for chain are located in the inside the its `nid` directory in a following format: - `keystore//.json` +- Gas Estimation for the evm chain +- Cosmos sdk global config bech32 prefixes +- Other improvements and bug fixes -## [1.1.1] - 2024-03-21 +## [1.2.3] - 2024-05-14 ### Added -- Websocket support for evm chain - -### Fixed - -- AWS Region detection -- Static binary build +- Gas adjustment from config -## [1.1.2] - 2024-03-22 +## [1.2.2] - 2024-05-01 ### Fixed -- Region detection for AWS -- Priority 0 (high) for `start-height` evm -- Panic too many packets map access +- Avoid nonce increment when fixing the nonce error while sending the transaction -## [1.1.3] - 2024-03-27 +## [1.2.1] - 2024-04-30 -### Added +### Fixed -- Route manually from height (on chain) +- Websocket connection disconnect issue with icon chain +- Use `eth_gasPrice` for the gas price calculation all the time +- Other improvements and bug fixes +- Use block mined timeout instead of polling when waiting for transcation -### Fixed +### Removed -- Increase delivery failure by trying for per 15 seconds after initial failures. -- Panics when subscribing to the event result. -- AWS ec2 instance profile detection. -- Other improvements and bug fixes. +- Icon redunant polling code ## [1.2.0] - 2024-04-09 @@ -126,39 +81,70 @@ Move the encrypted wallet passphrase to the new location: - Height sync is no longer necessary. -## [1.2.1] - 2024-04-30 +## [1.1.3] - 2024-03-27 -### Fixed +### Added -- Websocket connection disconnect issue with icon chain -- Use `eth_gasPrice` for the gas price calculation all the time -- Other improvements and bug fixes -- Use block mined timeout instead of polling when waiting for transcation +- Route manually from height (on chain) -### Removed +### Fixed -- Icon redunant polling code +- Increase delivery failure by trying for per 15 seconds after initial failures. +- Panics when subscribing to the event result. +- AWS ec2 instance profile detection. +- Other improvements and bug fixes. -## [1.2.2] - 2024-05-01 +## [1.1.2] - 2024-03-22 ### Fixed -- Avoid nonce increment when fixing the nonce error while sending the transaction +- Region detection for AWS +- Priority 0 (high) for `start-height` evm +- Panic too many packets map access -# [1.2.3] - 2024-05-14 +## [1.1.1] - 2024-03-21 ### Added -- Gas adjustment from config +- Websocket support for evm chain -## [1.2.4] - 2024-05-17 +### Fixed + +- AWS Region detection +- Static binary build + +## [1.1.0] - 2024-03-18 ### Added -- Support for the injective chain +- Support for cosmos chain +- Xcall contract support +- CallMessage event listener for all supported chains +- Fee related operations cmd. `getFee`, `setFee` and `claimFee` +- Structured events for easier event handling + +### Changed + +- Wallet encryption and decryption +- GO version to 1.22.1 ### Fixed -- Gas Estimation for the evm chain -- Cosmos sdk global config bech32 prefixes -- Other improvements and bug fixes +- Incorrect icon chain balance calculation. +- SetAdmin also checks for the admin address to avoid setting the admin address to the same address. +- Retries is less error prone now, only retries after set interval (5s) when failed. +- Fixed the issue when initilizing config file. + +### Migration from 1.0.0 to 1.1.0 + +We have added support for cosmos chains and xcall contract support. To migrate from 1.0.0 to 1.1.0, you need to update the configuration file and add the cosmos chain details. The configuration file is backward compatible, so you can add the cosmos chain details without affecting the existing configuration. + +Major changes in this release is the wallet encryption and decryption. Previously we only encrypted the keystore password, now we encrypt the entire keystore file adding an extra layer of security. The relay will automatically decrypt the keystore file and use it to sign the messages. + +We have also added the xcall execution contract support. The relay will now listen to the call message event and execute the xcall contract. + +Exection will respect the fees set on configuration. The relay will now calculate the fees and execute the contract. + +Migrate keystore files to the new format by running the following command: + +**important**: Before running the command, make sure you have the AWS KMS key id. You can get the KMS key id by running the `crly config show` command. diff --git a/relayer/chains/evm/listener.go b/relayer/chains/evm/listener.go index af17d7dc..b4651b33 100644 --- a/relayer/chains/evm/listener.go +++ b/relayer/chains/evm/listener.go @@ -245,7 +245,7 @@ func (p *Provider) startFromHeight(ctx context.Context, lastSavedHeight uint64) } // Subscribe listens to new blocks and sends them to the channel -func (p *Provider) Subscribe(ctx context.Context, ticker *time.Ticker, blockInfoChan chan *relayertypes.BlockInfo) { +func (p *Provider) Subscribe(ctx context.Context, ticker *time.Ticker, blockInfoChan chan *relayertypes.BlockInfo) error { ch := make(chan ethTypes.Log) sub, err := p.client.Subscribe(ctx, ethereum.FilterQuery{ Addresses: p.blockReq.Addresses, @@ -254,18 +254,18 @@ func (p *Provider) Subscribe(ctx context.Context, ticker *time.Ticker, blockInfo if err != nil { p.log.Error("failed to subscribe", zap.Error(err)) ticker.Reset(time.Second * 3) - return + return err } defer sub.Unsubscribe() p.log.Info("Subscribed to new blocks", zap.Uint64("from", p.blockReq.FromBlock.Uint64()), zap.Any("address", p.blockReq.Addresses)) for { select { case <-ctx.Done(): - return + return nil case err := <-sub.Err(): p.log.Error("subscription error", zap.Error(err)) ticker.Reset(time.Second * 3) - return + return p.Listener(ctx, p.GetLastSavedBlockHeight(), blockInfoChan) case log := <-ch: message, err := p.getRelayMessageFromLog(log) if err != nil { diff --git a/relayer/chains/evm/provider.go b/relayer/chains/evm/provider.go index 2e8a614a..9befbfc4 100644 --- a/relayer/chains/evm/provider.go +++ b/relayer/chains/evm/provider.go @@ -57,15 +57,16 @@ type Config struct { } type Provider struct { - client IClient - log *zap.Logger - cfg *Config - StartHeight uint64 - blockReq ethereum.FilterQuery - wallet *keystore.Key - kms kms.KMS - contracts map[string]providerTypes.EventMap - NonceTracker types.NonceTrackerI + client IClient + log *zap.Logger + cfg *Config + StartHeight uint64 + blockReq ethereum.FilterQuery + wallet *keystore.Key + kms kms.KMS + contracts map[string]providerTypes.EventMap + NonceTracker types.NonceTrackerI + LastSavedHeightFunc func() uint64 } func (p *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath string, debug bool, chainName string) (provider.ChainProvider, error) { @@ -439,3 +440,13 @@ func (p *Provider) EstimateGas(ctx context.Context, message *providerTypes.Messa } return p.client.EstimateGas(ctx, msg) } + +// SetLastSavedBlockHeightFunc sets the function to save the last saved block height +func (p *Provider) SetLastSavedHeightFunc(f func() uint64) { + p.LastSavedHeightFunc = f +} + +// GetLastSavedBlockHeight returns the last saved block height +func (p *Provider) GetLastSavedBlockHeight() uint64 { + return p.LastSavedHeightFunc() +} diff --git a/relayer/chains/icon/listener.go b/relayer/chains/icon/listener.go index da3a0e7d..444708c3 100644 --- a/relayer/chains/icon/listener.go +++ b/relayer/chains/icon/listener.go @@ -53,7 +53,7 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, incomin Height: types.NewHexInt(processedheight), EventFilter: p.GetMonitorEventFilters(), Logs: types.NewHexInt(1), - ProgressInterval: types.NewHexInt(15), + ProgressInterval: types.NewHexInt(25), } for { @@ -76,7 +76,7 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, incomin return err } if height > 0 { - eventReq.Height = types.NewHexInt(height + 1) + eventReq.Height = types.NewHexInt(height) } return nil } @@ -104,7 +104,7 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, incomin if errors.Is(err, context.Canceled) { return } - time.Sleep(time.Second * 5) + time.Sleep(time.Second * 3) reconnect() p.log.Warn("error occured during monitor event", zap.Error(err)) } diff --git a/relayer/chains/icon/provider.go b/relayer/chains/icon/provider.go index 6ce35d66..d0a7d72b 100644 --- a/relayer/chains/icon/provider.go +++ b/relayer/chains/icon/provider.go @@ -87,12 +87,13 @@ func (c *Config) Enabled() bool { } type Provider struct { - log *zap.Logger - cfg *Config - wallet module.Wallet - client *Client - kms kms.KMS - contracts map[string]providerTypes.EventMap + log *zap.Logger + cfg *Config + wallet module.Wallet + client *Client + kms kms.KMS + contracts map[string]providerTypes.EventMap + LastSavedHeightFunc func() uint64 } func (p *Provider) NID() string { @@ -258,3 +259,13 @@ func (p *Provider) ExecuteRollback(ctx context.Context, sn uint64) error { } return nil } + +// SetLastSavedBlockHeightFunc sets the function to save the last saved block height +func (p *Provider) SetLastSavedHeightFunc(f func() uint64) { + p.LastSavedHeightFunc = f +} + +// GetLastSavedBlockHeight returns the last saved block height +func (p *Provider) GetLastSavedBlockHeight() uint64 { + return p.LastSavedHeightFunc() +} diff --git a/relayer/chains/wasm/provider.go b/relayer/chains/wasm/provider.go index 7bb542f8..218b6374 100644 --- a/relayer/chains/wasm/provider.go +++ b/relayer/chains/wasm/provider.go @@ -26,13 +26,14 @@ import ( var _ provider.ChainProvider = (*Provider)(nil) type Provider struct { - logger *zap.Logger - cfg *Config - client IClient - kms kms.KMS - wallet sdkTypes.AccountI - contracts map[string]relayTypes.EventMap - eventList []sdkTypes.Event + logger *zap.Logger + cfg *Config + client IClient + kms kms.KMS + wallet sdkTypes.AccountI + contracts map[string]relayTypes.EventMap + eventList []sdkTypes.Event + LastSavedHeightFunc func() uint64 } func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { @@ -119,16 +120,13 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn return ctx.Err() case <-subscribeStarter.C: subscribeStarter.Stop() - go p.SubscribeMessageEvents(ctx, blockInfoChan, &types.SubscribeOpts{ - Address: p.cfg.Contracts[relayTypes.ConnectionContract], - Method: EventTypeWasmMessage, - Height: latestHeight, - }) - go p.SubscribeMessageEvents(ctx, blockInfoChan, &types.SubscribeOpts{ - Address: p.cfg.Contracts[relayTypes.XcallContract], - Method: EventTypeWasmCallMessage, - Height: latestHeight, - }) + for _, event := range p.contracts { + go p.SubscribeMessageEvents(ctx, blockInfoChan, &types.SubscribeOpts{ + Address: event.Address, + Method: event.GetWasmMsgType(), + Height: latestHeight, + }) + } default: if startHeight < latestHeight { p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) @@ -781,9 +779,19 @@ func (p *Provider) SubscribeMessageEvents(ctx context.Context, blockInfoChan cha time.Sleep(time.Second * 1) continue } - p.logger.Debug("http client reconnected") - return p.SubscribeMessageEvents(ctx, blockInfoChan, opts) + p.logger.Info("http client reconnected") + return p.Listener(ctx, p.GetLastSavedHeight(), blockInfoChan) } } } } + +// SetLastSavedHeightFunc sets the function to save the last saved height +func (p *Provider) SetLastSavedHeightFunc(f func() uint64) { + p.LastSavedHeightFunc = f +} + +// GetLastSavedHeight returns the last saved height +func (p *Provider) GetLastSavedHeight() uint64 { + return p.LastSavedHeightFunc() +} diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index cd62d67f..a340248b 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -33,6 +33,7 @@ type ChainProvider interface { Route(ctx context.Context, message *types.Message, callback types.TxResponseFunc) error ShouldReceiveMessage(ctx context.Context, message *types.Message) (bool, error) ShouldSendMessage(ctx context.Context, message *types.Message) (bool, error) + SetLastSavedHeightFunc(func() uint64) MessageReceived(ctx context.Context, key *types.MessageKey) (bool, error) SetAdmin(context.Context, string) error diff --git a/relayer/relay.go b/relayer/relay.go index 756935ea..057c04c4 100644 --- a/relayer/relay.go +++ b/relayer/relay.go @@ -93,7 +93,9 @@ func NewRelayer(log *zap.Logger, db store.Store, chains map[string]*Chain, fresh chainRuntime.LastSavedHeight = lastSavedHeight } chainRuntimes[chain.NID()] = chainRuntime - + chainRuntime.Provider.SetLastSavedHeightFunc(func() uint64 { + return chainRuntime.LastSavedHeight + }) } return &Relayer{ diff --git a/relayer/types/types.go b/relayer/types/types.go index bb1ac6ee..6140844a 100644 --- a/relayer/types/types.go +++ b/relayer/types/types.go @@ -15,7 +15,7 @@ var ( XcallContract = "xcall" ConnectionContract = "connection" SupportedContracts = []string{XcallContract, ConnectionContract} - RetryInterval = 5 * time.Second + RetryInterval = 3 * time.Second ) type BlockInfo struct { @@ -54,6 +54,14 @@ func (c ContractConfigMap) Validate() error { return nil } +// GetWasmMsgType returns the wasm message type +func (m *EventMap) GetWasmMsgType() string { + for wasmType := range m.SigType { + return wasmType + } + return "" +} + func (m *Message) MessageKey() *MessageKey { return NewMessageKey(m.Sn, m.Src, m.Dst, m.EventType) }