diff --git a/.circleci/config.yml b/.circleci/config.yml index 97666303..ceb95006 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ orbs: jobs: build_lint_test: machine: - image: ubuntu-2204:2022.10.1 + image: ubuntu-2204:2024.01.1 resource_class: large steps: - go/install: @@ -41,7 +41,7 @@ jobs: build_docker: machine: - image: ubuntu-2204:2022.10.1 + image: ubuntu-2204:2024.01.1 resource_class: large steps: - checkout @@ -63,7 +63,7 @@ jobs: push_docker: machine: - image: ubuntu-2204:2022.10.1 + image: ubuntu-2204:2024.01.1 resource_class: large steps: - attach_workspace: diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..7d083cff --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,276 @@ +# Changelog + +## [v0.2.0](https://github.com/babylonchain/finality-provider/tree/v0.2.0) (2024-05-14) + +[Full Changelog](https://github.com/babylonchain/finality-provider/compare/euphrates-0.1.0-rc.0...v0.2.0) + +**Closed issues:** + +- eotsd verify signature command from input file, pub key [\#311](https://github.com/babylonchain/finality-provider/issues/311) +- Generate EOTS key [\#306](https://github.com/babylonchain/finality-provider/issues/306) +- Finality Provider issues [\#302](https://github.com/babylonchain/finality-provider/issues/302) +- Requires DATA Prune solutions [\#297](https://github.com/babylonchain/finality-provider/issues/297) +- Suggest Add Delete Provider Instance [\#295](https://github.com/babylonchain/finality-provider/issues/295) +- Add e2e test using CLI `export-finality-provider` and importing the result on genesis [\#289](https://github.com/babylonchain/finality-provider/issues/289) +- failed to register finality-provider \(not found: key not found\) [\#279](https://github.com/babylonchain/finality-provider/issues/279) +- "unauthorized" error with fpcli register-finality-provider [\#273](https://github.com/babylonchain/finality-provider/issues/273) + +## [euphrates-0.1.0-rc.0](https://github.com/babylonchain/finality-provider/tree/euphrates-0.1.0-rc.0) (2024-03-26) + +[Full Changelog](https://github.com/babylonchain/finality-provider/compare/v0.1.0...euphrates-0.1.0-rc.0) + +**Fixed bugs:** + +- Finality provider status `CREATED` is not changed to `REGISTERED` in some cases [\#253](https://github.com/babylonchain/finality-provider/issues/253) + +**Closed issues:** + +- eotsd init panics [\#266](https://github.com/babylonchain/finality-provider/issues/266) +- DB needs refactoring [\#252](https://github.com/babylonchain/finality-provider/issues/252) +- failed to register the finality-provider to Babylon: error in json rpc client [\#249](https://github.com/babylonchain/finality-provider/issues/249) +- `fpcli ls` should return all the managed fps with different status [\#244](https://github.com/babylonchain/finality-provider/issues/244) +- Change the default parameters to ones used in a stable devnet [\#230](https://github.com/babylonchain/finality-provider/issues/230) +- Crash recovery potentially causes inconsistent state [\#196](https://github.com/babylonchain/finality-provider/issues/196) +- Command for collecting finality provider rewards [\#176](https://github.com/babylonchain/finality-provider/issues/176) +- Drop blocks when a block channel of a validator gets full [\#72](https://github.com/babylonchain/finality-provider/issues/72) + +## [v0.1.0](https://github.com/babylonchain/finality-provider/tree/v0.1.0) (2024-02-08) + +[Full Changelog](https://github.com/babylonchain/finality-provider/compare/v0.1.0-rc.0...v0.1.0) + +**Fixed bugs:** + +- Fast-sync inconsistent with poller [\#234](https://github.com/babylonchain/finality-provider/issues/234) +- Fast-sync fails upon `ErrDuplicatedFinalitySig` [\#233](https://github.com/babylonchain/finality-provider/issues/233) +- Zero voting power when querying for the best block [\#223](https://github.com/babylonchain/finality-provider/issues/223) +- Data inconsistency leads to Validator termination [\#113](https://github.com/babylonchain/finality-provider/issues/113) + +**Closed issues:** + +- Existing retry loops to safely proceed but the error still exists [\#229](https://github.com/babylonchain/finality-provider/issues/229) +- bug: `LastProcessedHeight` leads to blocks never being voted if previously skipped [\#227](https://github.com/babylonchain/finality-provider/issues/227) +- bug: shouldSubmitFinalitySignature does not check whether randomness is committed [\#226](https://github.com/babylonchain/finality-provider/issues/226) +- Inconsistent LastVotedHeight with Babylon would cause loss of liveness [\#222](https://github.com/babylonchain/finality-provider/issues/222) +- Finality provider crashes over duplicated finality signature submission [\#220](https://github.com/babylonchain/finality-provider/issues/220) +- Finality Providers stop sending Finality sigs [\#219](https://github.com/babylonchain/finality-provider/issues/219) +- Cycle dependency issue with covenant-emulator [\#206](https://github.com/babylonchain/finality-provider/issues/206) +- EOTS manager still asks passphrase from terminal in `file` KeyringBackend [\#145](https://github.com/babylonchain/finality-provider/issues/145) +- Mnemonic for created keyrings should not be stored in the logs [\#78](https://github.com/babylonchain/finality-provider/issues/78) + +**Merged pull requests:** + +- chore: Bump Babylon to v0.8.0 [\#239](https://github.com/babylonchain/finality-provider/pull/239) ([gitferry](https://github.com/gitferry)) +- chore: Change default config value [\#238](https://github.com/babylonchain/finality-provider/pull/238) ([gitferry](https://github.com/gitferry)) +- Bumps babylon to latest version [\#236](https://github.com/babylonchain/finality-provider/pull/236) ([KonradStaniec](https://github.com/KonradStaniec)) +- fix\(poller\): Next height should not be set with a lower value [\#235](https://github.com/babylonchain/finality-provider/pull/235) ([gitferry](https://github.com/gitferry)) +- chore: Change default ports to 12581 and 12582 [\#232](https://github.com/babylonchain/finality-provider/pull/232) ([vitsalis](https://github.com/vitsalis)) +- fix: Query best block causing flaky voting power result [\#231](https://github.com/babylonchain/finality-provider/pull/231) ([gitferry](https://github.com/gitferry)) +- fix: `LastProcessedHeight` should be set ensuring public randomness committed [\#228](https://github.com/babylonchain/finality-provider/pull/228) ([gitferry](https://github.com/gitferry)) +- fix: Only clean up blocks buffer up to the fast-synced height [\#225](https://github.com/babylonchain/finality-provider/pull/225) ([vitsalis](https://github.com/vitsalis)) +- chore: Fix panicking upon expected error during retrying [\#221](https://github.com/babylonchain/finality-provider/pull/221) ([gitferry](https://github.com/gitferry)) +- CI: Remove redundant SSH key logic [\#218](https://github.com/babylonchain/finality-provider/pull/218) ([filippos47](https://github.com/filippos47)) +- chore: Remove `--all` flag when starting `fpd` daemon [\#216](https://github.com/babylonchain/finality-provider/pull/216) ([gitferry](https://github.com/gitferry)) +- fix\(doc\): Inconsistency of keyringbackend in doc [\#214](https://github.com/babylonchain/finality-provider/pull/214) ([gitferry](https://github.com/gitferry)) +- docs: Add note regarding randomness commitments [\#213](https://github.com/babylonchain/finality-provider/pull/213) ([filippos47](https://github.com/filippos47)) + +## [v0.1.0-rc.0](https://github.com/babylonchain/finality-provider/tree/v0.1.0-rc.0) (2024-01-22) + +[Full Changelog](https://github.com/babylonchain/finality-provider/compare/f88f8884fd415300ac85c24384652df8ef744f36...v0.1.0-rc.0) + +**Fixed bugs:** + +- Panicking when querying for public randomness [\#199](https://github.com/babylonchain/finality-provider/issues/199) +- `fpcli --daemon-address` flag inconsistencies [\#197](https://github.com/babylonchain/finality-provider/issues/197) +- Cannot manually submit finality signature [\#187](https://github.com/babylonchain/finality-provider/issues/187) +- `fpcli ls`: Finality provider description is base64 encoded [\#186](https://github.com/babylonchain/finality-provider/issues/186) +- Finality providers don't start after daemon restart [\#183](https://github.com/babylonchain/finality-provider/issues/183) +- btc-validator doesn't report errors when connected to non-existent remote EOTS manager [\#169](https://github.com/babylonchain/finality-provider/issues/169) +- Indirect dependency on `cosmossdk.io/tools/confix/cmd` [\#158](https://github.com/babylonchain/finality-provider/issues/158) +- BTC Validator daemon freezes after attack execution [\#131](https://github.com/babylonchain/finality-provider/issues/131) +- BTC Validator skipped voting for a block [\#114](https://github.com/babylonchain/finality-provider/issues/114) +- btc-validator freezes after creating additional BTC Validators [\#106](https://github.com/babylonchain/finality-provider/issues/106) +- Slashed validators' status not shifting to `3` on `valcli dn ls` output [\#98](https://github.com/babylonchain/finality-provider/issues/98) +- Account sequence mismatch error [\#84](https://github.com/babylonchain/finality-provider/issues/84) +- Create validator: BTC PKs always have prefix 02 in logs [\#77](https://github.com/babylonchain/finality-provider/issues/77) + +**Closed issues:** + +- Inconsistency between the local LastCommittedHeight and Babylon [\#193](https://github.com/babylonchain/finality-provider/issues/193) +- LastCommittedHeight inconsistancy [\#191](https://github.com/babylonchain/finality-provider/issues/191) +- `fpcli cfp`: `--key-name` flag removed [\#184](https://github.com/babylonchain/finality-provider/issues/184) +- Show descriptive validator statuses [\#177](https://github.com/babylonchain/finality-provider/issues/177) +- Split covenant into a different repository [\#175](https://github.com/babylonchain/finality-provider/issues/175) +- Ensure the check of delegation/undelegation is consistent with Babylon [\#173](https://github.com/babylonchain/finality-provider/issues/173) +- Key Management Commands [\#170](https://github.com/babylonchain/finality-provider/issues/170) +- Configuration option specifying max number of validators concurrently running [\#165](https://github.com/babylonchain/finality-provider/issues/165) +- Rename btc-validator to finality-provider [\#163](https://github.com/babylonchain/finality-provider/issues/163) +- Use common Dockerfile for covenant, eots-manager, and finality provider [\#162](https://github.com/babylonchain/finality-provider/issues/162) +- btc-validator: Wrong config file path [\#160](https://github.com/babylonchain/finality-provider/issues/160) +- Use `zap` logger to replace `logrus` logger [\#157](https://github.com/babylonchain/finality-provider/issues/157) +- `vald` and `eotsd` can start even if there is no config file present. [\#155](https://github.com/babylonchain/finality-provider/issues/155) +- `KeyDirectory` in `vald.conf` creates another subdirectory to store keys [\#154](https://github.com/babylonchain/finality-provider/issues/154) +- `vald` shows successfully connected to EOTS manager even when `eotsd` is not running [\#153](https://github.com/babylonchain/finality-provider/issues/153) +- `eotsd` provides `--rpclistener` flag requiring full address but `vald` provides `--rpclisten` flag which accepts port or full address [\#151](https://github.com/babylonchain/finality-provider/issues/151) +- Have an `init` command that initializes the home directory instead of `dump-config`. [\#150](https://github.com/babylonchain/finality-provider/issues/150) +- Show more information about babylon account of the validator using cmd [\#148](https://github.com/babylonchain/finality-provider/issues/148) +- Check chaining before sending finality signature [\#143](https://github.com/babylonchain/finality-provider/issues/143) +- Specify validator instance when starting a daemon [\#142](https://github.com/babylonchain/finality-provider/issues/142) +- Remove global Babylon account [\#141](https://github.com/babylonchain/finality-provider/issues/141) +- Separate Covenant functionalities from Validator [\#140](https://github.com/babylonchain/finality-provider/issues/140) +- Anti-slashing mechanism [\#136](https://github.com/babylonchain/finality-provider/issues/136) +- Enable passphrase to encrypt keys [\#135](https://github.com/babylonchain/finality-provider/issues/135) +- Rename Jury to Covenant [\#134](https://github.com/babylonchain/finality-provider/issues/134) +- Jury does not check slashing address of delegations [\#133](https://github.com/babylonchain/finality-provider/issues/133) +- BTC Validator daemon stability issues [\#132](https://github.com/babylonchain/finality-provider/issues/132) +- Should remove chain-id in keymanagement [\#122](https://github.com/babylonchain/finality-provider/issues/122) +- Delegations stuck in pending state [\#120](https://github.com/babylonchain/finality-provider/issues/120) +- BTC Validator registration crushes the daemon [\#118](https://github.com/babylonchain/finality-provider/issues/118) +- `valcli dn cv`: Add commission as CLI argument [\#107](https://github.com/babylonchain/finality-provider/issues/107) +- Jury keeps trying to sign unbonding transaction [\#105](https://github.com/babylonchain/finality-provider/issues/105) +- Use BTC PK as the unique ID of a validator instead of Babylon PK [\#104](https://github.com/babylonchain/finality-provider/issues/104) +- Flaky tests results [\#99](https://github.com/babylonchain/finality-provider/issues/99) +- Proper termination of validator instances [\#96](https://github.com/babylonchain/finality-provider/issues/96) +- Concurrent sending of finality signatures [\#95](https://github.com/babylonchain/finality-provider/issues/95) +- Add description CLI flag to `valcli dn cv` [\#94](https://github.com/babylonchain/finality-provider/issues/94) +- Bump Babylon version [\#73](https://github.com/babylonchain/finality-provider/issues/73) +- Contention for rpc-client lock [\#71](https://github.com/babylonchain/finality-provider/issues/71) +- Manage validator instances within `ValidatorManager` [\#69](https://github.com/babylonchain/finality-provider/issues/69) +- add-finality-signature: Return decoded transaction hash [\#68](https://github.com/babylonchain/finality-provider/issues/68) +- Handle validators in separate Goroutines [\#64](https://github.com/babylonchain/finality-provider/issues/64) +- Refactor DB [\#63](https://github.com/babylonchain/finality-provider/issues/63) +- The chain poller may infinitely retry to get initial latest height [\#62](https://github.com/babylonchain/finality-provider/issues/62) +- The chain poller will not work when there is more than one consumer [\#61](https://github.com/babylonchain/finality-provider/issues/61) +- Validators should use their own Babylon account to submit txs to Babylon [\#58](https://github.com/babylonchain/finality-provider/issues/58) +- Catchup mechanism [\#56](https://github.com/babylonchain/finality-provider/issues/56) +- Finality sig lagging due to sequential sending of public randomness [\#54](https://github.com/babylonchain/finality-provider/issues/54) +- Follow Babylon's height instead of maintaining relative height [\#47](https://github.com/babylonchain/finality-provider/issues/47) +- Replace lens client with a rpc client that supports async broadcast mode [\#37](https://github.com/babylonchain/finality-provider/issues/37) +- Poller starts from a higher height [\#36](https://github.com/babylonchain/finality-provider/issues/36) +- Batching voting messages [\#35](https://github.com/babylonchain/finality-provider/issues/35) +- Improvement of error handling [\#34](https://github.com/babylonchain/finality-provider/issues/34) + +**Merged pull requests:** + +- chore: Remove dependency on covenant-emulator [\#212](https://github.com/babylonchain/finality-provider/pull/212) ([gitferry](https://github.com/gitferry)) +- chore: Upgrade bbn to 0.8.0-rc.0 [\#211](https://github.com/babylonchain/finality-provider/pull/211) ([vitsalis](https://github.com/vitsalis)) +- chore: Remove private repo thingy [\#210](https://github.com/babylonchain/finality-provider/pull/210) ([gitferry](https://github.com/gitferry)) +- chore: Add account address in the output of `keys add` [\#205](https://github.com/babylonchain/finality-provider/pull/205) ([gitferry](https://github.com/gitferry)) +- chore: Bump public dependency [\#204](https://github.com/babylonchain/finality-provider/pull/204) ([gitferry](https://github.com/gitferry)) +- chore: Ensure all the Babylon queries are using rpc-client [\#203](https://github.com/babylonchain/finality-provider/pull/203) ([gitferry](https://github.com/gitferry)) +- fix: Add BLS flags in make [\#202](https://github.com/babylonchain/finality-provider/pull/202) ([gusin13](https://github.com/gusin13)) +- fix: Slashing finality-provider caused program panicking [\#201](https://github.com/babylonchain/finality-provider/pull/201) ([gitferry](https://github.com/gitferry)) +- chore: Remove global flag [\#198](https://github.com/babylonchain/finality-provider/pull/198) ([gitferry](https://github.com/gitferry)) +- chore: Remove covenant legacy [\#195](https://github.com/babylonchain/finality-provider/pull/195) ([gitferry](https://github.com/gitferry)) +- chore: Clean up cli usage [\#194](https://github.com/babylonchain/finality-provider/pull/194) ([gitferry](https://github.com/gitferry)) +- chore: replace local last committed height with remote query [\#192](https://github.com/babylonchain/finality-provider/pull/192) ([gitferry](https://github.com/gitferry)) +- chore: Bump Babylon version and add unbonding time validation [\#190](https://github.com/babylonchain/finality-provider/pull/190) ([gitferry](https://github.com/gitferry)) +- chore: Improve output of finality provider [\#189](https://github.com/babylonchain/finality-provider/pull/189) ([gitferry](https://github.com/gitferry)) +- chore: Add `start --all` for `fpd` [\#188](https://github.com/babylonchain/finality-provider/pull/188) ([gitferry](https://github.com/gitferry)) +- chore: Add `key-name` flag back to `create-finality-provider` cmd [\#185](https://github.com/babylonchain/finality-provider/pull/185) ([gitferry](https://github.com/gitferry)) +- chore: fix minor issues in the documentation [\#182](https://github.com/babylonchain/finality-provider/pull/182) ([yangl1996](https://github.com/yangl1996)) +- feat: Add key management [\#181](https://github.com/babylonchain/finality-provider/pull/181) ([gitferry](https://github.com/gitferry)) +- feat: Covenant handles pre-signed unbonding txs [\#180](https://github.com/babylonchain/finality-provider/pull/180) ([vitsalis](https://github.com/vitsalis)) +- chore: Rename btc-validator to finality-provider [\#179](https://github.com/babylonchain/finality-provider/pull/179) ([vitsalis](https://github.com/vitsalis)) +- docs: Combine docs into less pages, update overview, and finality renaming [\#178](https://github.com/babylonchain/finality-provider/pull/178) ([vitsalis](https://github.com/vitsalis)) +- chore: Add configurable limit on running multiple validators [\#172](https://github.com/babylonchain/finality-provider/pull/172) ([gitferry](https://github.com/gitferry)) +- feat: Refactor configuration and cli of programs [\#168](https://github.com/babylonchain/finality-provider/pull/168) ([vitsalis](https://github.com/vitsalis)) +- feat: Use a single docker file [\#167](https://github.com/babylonchain/finality-provider/pull/167) ([vitsalis](https://github.com/vitsalis)) +- fix: Do not perform conversions on the commission [\#166](https://github.com/babylonchain/finality-provider/pull/166) ([vitsalis](https://github.com/vitsalis)) +- chore: Replace logrus with zap as logger [\#164](https://github.com/babylonchain/finality-provider/pull/164) ([gitferry](https://github.com/gitferry)) +- feat: Refactor to separate validator operation to separate directory [\#161](https://github.com/babylonchain/finality-provider/pull/161) ([vitsalis](https://github.com/vitsalis)) +- Fix make file [\#159](https://github.com/babylonchain/finality-provider/pull/159) ([KonradStaniec](https://github.com/KonradStaniec)) +- CI: Push images for covenant [\#156](https://github.com/babylonchain/finality-provider/pull/156) ([filippos47](https://github.com/filippos47)) +- docs: Improvements [\#152](https://github.com/babylonchain/finality-provider/pull/152) ([gusin13](https://github.com/gusin13)) +- Chore: Bump Babylon version and use rpc-client to replace cosmos provider [\#149](https://github.com/babylonchain/finality-provider/pull/149) ([gitferry](https://github.com/gitferry)) +- docs: Add documentation for EOTS and Validator daemons [\#147](https://github.com/babylonchain/finality-provider/pull/147) ([gusin13](https://github.com/gusin13)) +- chore: Refactor validator app [\#146](https://github.com/babylonchain/finality-provider/pull/146) ([gitferry](https://github.com/gitferry)) +- chore: Separate covenant functionalities into a different binary [\#144](https://github.com/babylonchain/finality-provider/pull/144) ([gitferry](https://github.com/gitferry)) +- feat: Add support for file backend for keyrings [\#139](https://github.com/babylonchain/finality-provider/pull/139) ([gitferry](https://github.com/gitferry)) +- chore: Add slashing address validation and rename Jury to Covenant [\#137](https://github.com/babylonchain/finality-provider/pull/137) ([gitferry](https://github.com/gitferry)) +- chore: Generalize client controller [\#130](https://github.com/babylonchain/finality-provider/pull/130) ([gitferry](https://github.com/gitferry)) +- chore: Bump babylon version to fix flaky issue in e2e tests [\#129](https://github.com/babylonchain/finality-provider/pull/129) ([gitferry](https://github.com/gitferry)) +- Improve randomness management in the EOTS manager [\#128](https://github.com/babylonchain/finality-provider/pull/128) ([gitferry](https://github.com/gitferry)) +- CI: Build/push images for eotsmanager [\#127](https://github.com/babylonchain/finality-provider/pull/127) ([filippos47](https://github.com/filippos47)) +- chore: Remove chain-id in creating key [\#125](https://github.com/babylonchain/finality-provider/pull/125) ([gitferry](https://github.com/gitferry)) +- chore: Add docker file to EOTS manager [\#124](https://github.com/babylonchain/finality-provider/pull/124) ([gitferry](https://github.com/gitferry)) +- chore: Add e2e tests for EOTS manager server [\#123](https://github.com/babylonchain/finality-provider/pull/123) ([gitferry](https://github.com/gitferry)) +- Fix: bug when a validator is registered using rpc [\#119](https://github.com/babylonchain/finality-provider/pull/119) ([gitferry](https://github.com/gitferry)) +- chore: Bump babylon version [\#117](https://github.com/babylonchain/finality-provider/pull/117) ([gitferry](https://github.com/gitferry)) +- feat: Add remote eots manager [\#116](https://github.com/babylonchain/finality-provider/pull/116) ([gitferry](https://github.com/gitferry)) +- Integrate EOTS manager [\#115](https://github.com/babylonchain/finality-provider/pull/115) ([gitferry](https://github.com/gitferry)) +- chore: Modularize EOTS manager [\#112](https://github.com/babylonchain/finality-provider/pull/112) ([gitferry](https://github.com/gitferry)) +- feat: Add periodic status update to managed validators [\#110](https://github.com/babylonchain/finality-provider/pull/110) ([gitferry](https://github.com/gitferry)) +- feat: Add commission as cli flag [\#109](https://github.com/babylonchain/finality-provider/pull/109) ([gitferry](https://github.com/gitferry)) +- chore: Fix indefinite loop bug while fast sync [\#108](https://github.com/babylonchain/finality-provider/pull/108) ([gitferry](https://github.com/gitferry)) +- chore: Add proper termination upon critical error [\#103](https://github.com/babylonchain/finality-provider/pull/103) ([gitferry](https://github.com/gitferry)) +- chore: Fix issues before panicking and after restart [\#102](https://github.com/babylonchain/finality-provider/pull/102) ([gitferry](https://github.com/gitferry)) +- chore: Fix panic situation when the latest block is not queried [\#101](https://github.com/babylonchain/finality-provider/pull/101) ([gitferry](https://github.com/gitferry)) +- feat: Add cli flags for description [\#100](https://github.com/babylonchain/finality-provider/pull/100) ([gitferry](https://github.com/gitferry)) +- chore: Update BBN version [\#97](https://github.com/babylonchain/finality-provider/pull/97) ([vitsalis](https://github.com/vitsalis)) +- chore: Separate submission loop [\#93](https://github.com/babylonchain/finality-provider/pull/93) ([gitferry](https://github.com/gitferry)) +- chore: Replace retriable error list with unrecoverable one [\#92](https://github.com/babylonchain/finality-provider/pull/92) ([gitferry](https://github.com/gitferry)) +- Jury unbonding sigs submission [\#91](https://github.com/babylonchain/finality-provider/pull/91) ([KonradStaniec](https://github.com/KonradStaniec)) +- feat: Add fast sync mechanism [\#90](https://github.com/babylonchain/finality-provider/pull/90) ([gitferry](https://github.com/gitferry)) +- Validator ubtx sig [\#89](https://github.com/babylonchain/finality-provider/pull/89) ([KonradStaniec](https://github.com/KonradStaniec)) +- Bump babylon version and update methods [\#88](https://github.com/babylonchain/finality-provider/pull/88) ([KonradStaniec](https://github.com/KonradStaniec)) +- chore: Add client support to arbitrary consumer chain [\#87](https://github.com/babylonchain/finality-provider/pull/87) ([gitferry](https://github.com/gitferry)) +- fix: Add key file lock to fix the concurrency issue in submission [\#86](https://github.com/babylonchain/finality-provider/pull/86) ([gitferry](https://github.com/gitferry)) +- chore: terminate goroutine with err instead of crashing the entire program [\#85](https://github.com/babylonchain/finality-provider/pull/85) ([gitferry](https://github.com/gitferry)) +- chore: Bump Cosmos relayer version [\#82](https://github.com/babylonchain/finality-provider/pull/82) ([gitferry](https://github.com/gitferry)) +- fix: `uint64` type error when checking commitment gap [\#81](https://github.com/babylonchain/finality-provider/pull/81) ([gitferry](https://github.com/gitferry)) +- chore: Adds `reliableSendMsg` with retriable error list and expected error list [\#80](https://github.com/babylonchain/finality-provider/pull/80) ([gitferry](https://github.com/gitferry)) +- chore: Proper handling err in submitting finality signature [\#79](https://github.com/babylonchain/finality-provider/pull/79) ([gitferry](https://github.com/gitferry)) +- chore: Bump Babylon version and fixed bugs in performing the double-signing attack [\#76](https://github.com/babylonchain/finality-provider/pull/76) ([gitferry](https://github.com/gitferry)) +- chore: Fix tx hash format [\#75](https://github.com/babylonchain/finality-provider/pull/75) ([gitferry](https://github.com/gitferry)) +- chore: Refactor managing of validators [\#74](https://github.com/babylonchain/finality-provider/pull/74) ([gitferry](https://github.com/gitferry)) +- feat: Handle validators different goroutines [\#67](https://github.com/babylonchain/finality-provider/pull/67) ([gitferry](https://github.com/gitferry)) +- chore: Fix error handling of committing public randomness [\#66](https://github.com/babylonchain/finality-provider/pull/66) ([gitferry](https://github.com/gitferry)) +- chore: fixing the handling equivocated votes [\#65](https://github.com/babylonchain/finality-provider/pull/65) ([SebastianElvis](https://github.com/SebastianElvis)) +- feat: Concurrent commitment of public randomness [\#55](https://github.com/babylonchain/finality-provider/pull/55) ([gitferry](https://github.com/gitferry)) +- nit: Bump Babylon and update corresponding requests [\#53](https://github.com/babylonchain/finality-provider/pull/53) ([vitsalis](https://github.com/vitsalis)) +- feat: Add `validator-info` daemon cmd to show the information of a validator [\#52](https://github.com/babylonchain/finality-provider/pull/52) ([gitferry](https://github.com/gitferry)) +- fix: Remove pointer from StaticChainScanningStartHeight [\#50](https://github.com/babylonchain/finality-provider/pull/50) ([vitsalis](https://github.com/vitsalis)) +- feat: Add option to automatically calculate the starting height [\#48](https://github.com/babylonchain/finality-provider/pull/48) ([vitsalis](https://github.com/vitsalis)) +- nit: Add error message for failed queries [\#46](https://github.com/babylonchain/finality-provider/pull/46) ([vitsalis](https://github.com/vitsalis)) +- Add add-finality-sig cmd [\#45](https://github.com/babylonchain/finality-provider/pull/45) ([gitferry](https://github.com/gitferry)) +- Add concurrent sends of finality sigs [\#44](https://github.com/babylonchain/finality-provider/pull/44) ([KonradStaniec](https://github.com/KonradStaniec)) +- Fix closing of validator App [\#43](https://github.com/babylonchain/finality-provider/pull/43) ([KonradStaniec](https://github.com/KonradStaniec)) +- chore: Add e2e tests about finality sig [\#42](https://github.com/babylonchain/finality-provider/pull/42) ([gitferry](https://github.com/gitferry)) +- CI: Build and push images to ECR [\#41](https://github.com/babylonchain/finality-provider/pull/41) ([filippos47](https://github.com/filippos47)) +- Change rpc client [\#40](https://github.com/babylonchain/finality-provider/pull/40) ([KonradStaniec](https://github.com/KonradStaniec)) +- chore: Refactor e2e tests and add tests about jury sig [\#39](https://github.com/babylonchain/finality-provider/pull/39) ([gitferry](https://github.com/gitferry)) +- Add finality signature signing and submission [\#33](https://github.com/babylonchain/finality-provider/pull/33) ([gitferry](https://github.com/gitferry)) +- nit: Output jury PK hex of Babylon BIP340Pk type [\#32](https://github.com/babylonchain/finality-provider/pull/32) ([vitsalis](https://github.com/vitsalis)) +- Add Jury sig submission into the main event loop [\#31](https://github.com/babylonchain/finality-provider/pull/31) ([gitferry](https://github.com/gitferry)) +- Add CommitPubRand into event loop [\#30](https://github.com/babylonchain/finality-provider/pull/30) ([gitferry](https://github.com/gitferry)) +- chore: fix typo in create validator cmd [\#29](https://github.com/babylonchain/finality-provider/pull/29) ([SebastianElvis](https://github.com/SebastianElvis)) +- Work on registration [\#28](https://github.com/babylonchain/finality-provider/pull/28) ([KonradStaniec](https://github.com/KonradStaniec)) +- feat: register-validator command accepts key name instead of pk [\#27](https://github.com/babylonchain/finality-provider/pull/27) ([vitsalis](https://github.com/vitsalis)) +- nit: Move daemon commands under dn subcommand [\#26](https://github.com/babylonchain/finality-provider/pull/26) ([vitsalis](https://github.com/vitsalis)) +- fix: Proper usage message for daemon create-validator [\#25](https://github.com/babylonchain/finality-provider/pull/25) ([vitsalis](https://github.com/vitsalis)) +- fix: Use the keyring directory from the Babylon configuration [\#24](https://github.com/babylonchain/finality-provider/pull/24) ([vitsalis](https://github.com/vitsalis)) +- Add Jury mode and Jury sig submission [\#23](https://github.com/babylonchain/finality-provider/pull/23) ([gitferry](https://github.com/gitferry)) +- chore: fix codec for new modules [\#22](https://github.com/babylonchain/finality-provider/pull/22) ([SebastianElvis](https://github.com/SebastianElvis)) +- chore: moving the db functionality in valcli to daemon subcommand [\#21](https://github.com/babylonchain/finality-provider/pull/21) ([SebastianElvis](https://github.com/SebastianElvis)) +- chore: Change pkbytes to hex in register-validator cmd [\#20](https://github.com/babylonchain/finality-provider/pull/20) ([gitferry](https://github.com/gitferry)) +- chore: Capitalize cmd and flag usage sentences and change BTC to Bitcoin in text [\#19](https://github.com/babylonchain/finality-provider/pull/19) ([gitferry](https://github.com/gitferry)) +- Initial event loop [\#18](https://github.com/babylonchain/finality-provider/pull/18) ([KonradStaniec](https://github.com/KonradStaniec)) +- feat: Add dump config command and use `vald` everywhere [\#15](https://github.com/babylonchain/finality-provider/pull/15) ([vitsalis](https://github.com/vitsalis)) +- feat: Proto generation with buf, Babylon config file, and minor nitpicks [\#14](https://github.com/babylonchain/finality-provider/pull/14) ([vitsalis](https://github.com/vitsalis)) +- Add initial poller implementation [\#13](https://github.com/babylonchain/finality-provider/pull/13) ([KonradStaniec](https://github.com/KonradStaniec)) +- chore: fix typo in cli arguments [\#12](https://github.com/babylonchain/finality-provider/pull/12) ([SebastianElvis](https://github.com/SebastianElvis)) +- Add commit randomness [\#11](https://github.com/babylonchain/finality-provider/pull/11) ([gitferry](https://github.com/gitferry)) +- Add integration test setup [\#10](https://github.com/babylonchain/finality-provider/pull/10) ([KonradStaniec](https://github.com/KonradStaniec)) +- Add docker file [\#9](https://github.com/babylonchain/finality-provider/pull/9) ([gitferry](https://github.com/gitferry)) +- Add babylon client controller [\#8](https://github.com/babylonchain/finality-provider/pull/8) ([gitferry](https://github.com/gitferry)) +- Add register validator rpc [\#7](https://github.com/babylonchain/finality-provider/pull/7) ([gitferry](https://github.com/gitferry)) +- Add babylon client interfaces [\#6](https://github.com/babylonchain/finality-provider/pull/6) ([gitferry](https://github.com/gitferry)) +- Add keyring [\#5](https://github.com/babylonchain/finality-provider/pull/5) ([gitferry](https://github.com/gitferry)) +- Setup validator daemon [\#4](https://github.com/babylonchain/finality-provider/pull/4) ([gitferry](https://github.com/gitferry)) +- Add save validator to db and list validators from db [\#3](https://github.com/babylonchain/finality-provider/pull/3) ([gitferry](https://github.com/gitferry)) +- Add create-validator command and KV store [\#2](https://github.com/babylonchain/finality-provider/pull/2) ([gitferry](https://github.com/gitferry)) +- Add project skeleton [\#1](https://github.com/babylonchain/finality-provider/pull/1) ([gitferry](https://github.com/gitferry)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/Makefile b/Makefile index 857a26a5..c8d6b32c 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,14 @@ endif BUILD_TARGETS := build install BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' +# Update changelog vars +ifneq (,$(SINCE_TAG)) + sinceTag := --since-tag $(SINCE_TAG) +endif +ifneq (,$(UPCOMING_TAG)) + upcomingTag := --future-release $(UPCOMING_TAG) +endif + all: build install build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) @@ -68,3 +76,11 @@ proto-gen: mock-gen: mkdir -p $(MOCKS_DIR) $(MOCKGEN_CMD) -source=clientcontroller/interface.go -package mocks -destination $(MOCKS_DIR)/babylon.go + +.PHONY: mock-gen + +update-changelog: + @echo ./scripts/update_changelog.sh $(sinceTag) $(upcomingTag) + ./scripts/update_changelog.sh $(sinceTag) $(upcomingTag) + +.PHONY: update-changelog diff --git a/README.md b/README.md index 7fbdd11b..5403c0f8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ any special hardware requirements and can operate on standard mid-sized machines running a UNIX-flavored operating system. It consists of the following programs: + - *Babylon full node*: An instance of a Babylon node connecting to the Babylon network. Running one is not a strict requirement, but it is recommended for security compared to trusting a third-party RPC node. @@ -31,22 +32,21 @@ The following graphic demonstrates the interconnections between the above progra ![Finality Provider Interconnections](./docs/finality-toolset.png) - ## 2. Installation -#### Prerequisites +### Prerequisites This project requires Go version 1.21 or later. Install Go by following the instructions on the [official Go installation guide](https://golang.org/doc/install). -#### Downloading the code +### Downloading the code To get started, clone the repository to your local machine from Github: ```bash -git clone git@github.com:babylonchain/finality-provider.git +git clone https://github.com/babylonchain/finality-provider.git ``` You can choose a specific version from @@ -57,7 +57,7 @@ cd finality-provider # cd into the project directory git checkout ``` -#### Building and installing the binary +### Building and installing the binary At the top-level directory of the project @@ -80,48 +80,18 @@ export PATH=$HOME/go/bin:$PATH echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.profile ``` -To build without installing, - -```bash -make build -``` - -The above command will put the built binaries in a build directory with the -following structure: -```bash -ls build - ├── eotsd - ├── fpcli - └── fpd -``` - -Another common issue with compiling is that some of the dependencies have -components written in C. If a C toolchain is absent, the Go compiler will throw -errors. (Most likely it will complain about undefined names/types.) Make sure a -C toolchain (for example, GCC or Clang) is available. On Ubuntu, this can be -installed by running - -```bash -sudo apt install build-essential -``` - ## 3. Setting up a finality provider -#### 3.1. Setting up a Babylon Full Node +### 3.1. Setting up a Babylon Full Node Before setting up the finality provider toolset, an operator must ensure a working connection with a Babylon full node. It is highly recommended that operators run their own node to avoid trusting third parties. Instructions on how to set up a full Babylon node -can be found in -[the Babylon documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/setup-node). - -The finality provider requires a Babylon keyring with loaded funds to be attached to it -in order to be able to send transactions to Babylon. -To setup such a keyring, follow the instructions in -[the Babylon documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds). +can be found in +[the Babylon documentation](https://docs.babylonchain.io/docs/user-guides/btc-staking-testnet/setup-node). -#### 3.2. Setting up the EOTS Manager +### 3.2. Setting up the EOTS Manager After a node and a keyring have been set up, the operator can set up and run the @@ -130,7 +100,7 @@ A complete overview of the EOTS manager, its operation, and its configuration options can be found in the [EOTS Manager page](docs/eots.md) -#### 3.3. Setting up a Finality Provider +### 3.3. Setting up a Finality Provider The last step is to set up and run the finality daemon. diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 77cf2e16..a2396c59 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -10,12 +10,13 @@ import ( "github.com/btcsuite/btcd/btcutil" "cosmossdk.io/math" + bbnclient "github.com/babylonchain/babylon/client/client" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + ckpttypes "github.com/babylonchain/babylon/x/checkpointing/types" finalitytypes "github.com/babylonchain/babylon/x/finality/types" - bbnclient "github.com/babylonchain/rpc-client/client" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -25,7 +26,7 @@ import ( "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" - "github.com/babylonchain/finality-provider/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/types" ) @@ -35,18 +36,18 @@ var emptyErrs = []*sdkErr.Error{} type BabylonController struct { bbnClient *bbnclient.Client - cfg *config.BBNConfig + cfg *fpcfg.BBNConfig btcParams *chaincfg.Params logger *zap.Logger } func NewBabylonController( - cfg *config.BBNConfig, + cfg *fpcfg.BBNConfig, btcParams *chaincfg.Params, logger *zap.Logger, ) (*BabylonController, error) { - bbnConfig := config.BBNConfigToBabylonConfig(cfg) + bbnConfig := fpcfg.BBNConfigToBabylonConfig(cfg) if err := bbnConfig.Validate(); err != nil { return nil, fmt.Errorf("invalid config for Babylon client: %w", err) @@ -109,78 +110,46 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg, expectedErrs []*sd } // RegisterFinalityProvider registers a finality provider via a MsgCreateFinalityProvider to Babylon -// it returns tx hash and error +// it returns tx hash, registered epoch, and error func (bc *BabylonController) RegisterFinalityProvider( chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte, -) (*types.TxResponse, error) { + masterPubRand string, +) (*types.TxResponse, uint64, error) { var bbnPop btcstakingtypes.ProofOfPossession if err := bbnPop.Unmarshal(pop); err != nil { - return nil, fmt.Errorf("invalid proof-of-possession: %w", err) + return nil, 0, fmt.Errorf("invalid proof-of-possession: %w", err) } var sdkDescription sttypes.Description if err := sdkDescription.Unmarshal(description); err != nil { - return nil, fmt.Errorf("invalid description: %w", err) + return nil, 0, fmt.Errorf("invalid description: %w", err) } msg := &btcstakingtypes.MsgCreateFinalityProvider{ - Signer: bc.mustGetTxSigner(), - BabylonPk: &secp256k1.PubKey{Key: chainPk}, - BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), - Pop: &bbnPop, - Commission: commission, - Description: &sdkDescription, + Signer: bc.mustGetTxSigner(), + BabylonPk: &secp256k1.PubKey{Key: chainPk}, + BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), + Pop: &bbnPop, + Commission: commission, + Description: &sdkDescription, + MasterPubRand: masterPubRand, } res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { - return nil, err - } - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil -} - -// CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon -// it returns tx hash and error -func (bc *BabylonController) CommitPubRandList( - fpPk *btcec.PublicKey, - startHeight uint64, - pubRandList []*btcec.FieldVal, - sig *schnorr.Signature, -) (*types.TxResponse, error) { - schnorrPubRandList := make([]bbntypes.SchnorrPubRand, 0, len(pubRandList)) - for _, r := range pubRandList { - schnorrPubRand := bbntypes.NewSchnorrPubRandFromFieldVal(r) - schnorrPubRandList = append(schnorrPubRandList, *schnorrPubRand) - } - - bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) - - msg := &finalitytypes.MsgCommitPubRandList{ - Signer: bc.mustGetTxSigner(), - FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), - StartHeight: startHeight, - PubRandList: schnorrPubRandList, - Sig: bip340Sig, + return nil, 0, err } - unrecoverableErrs := []*sdkErr.Error{ - finalitytypes.ErrInvalidPubRand, - finalitytypes.ErrTooFewPubRand, - finalitytypes.ErrNoPubRandYet, - btcstakingtypes.ErrFpNotFound, - } - - res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs) + registeredEpoch, err := bc.QueryFinalityProviderRegisteredEpoch(fpPk) if err != nil { - return nil, err + return nil, 0, err } - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, registeredEpoch, nil } // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon @@ -258,41 +227,34 @@ func (bc *BabylonController) QueryFinalityProviderVotingPower(fpPk *btcec.Public blockHeight, ) if err != nil { - return 0, fmt.Errorf("failed to query BTC delegations: %w", err) + return 0, fmt.Errorf("failed to query the finality provider's voting power at height %d: %w", blockHeight, err) } return res.VotingPower, nil } +// QueryFinalityProviderRegisteredEpoch queries the registered epoch of the finality provider +func (bc *BabylonController) QueryFinalityProviderRegisteredEpoch(fpPk *btcec.PublicKey) (uint64, error) { + res, err := bc.bbnClient.QueryClient.FinalityProvider( + bbntypes.NewBIP340PubKeyFromBTCPK(fpPk).MarshalHex(), + ) + if err != nil { + return 0, fmt.Errorf("failed to query finality provider registered epoch: %w", err) + } + + return res.FinalityProvider.RegisteredEpoch, nil +} + func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { return bc.queryLatestBlocks(nil, count, finalitytypes.QueriedBlockStatus_FINALIZED, true) } -// QueryLastCommittedPublicRand returns the last committed public randomness -// TODO update the implementation when rpc-client supports ListPublicRandomness -func (bc *BabylonController) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { - fpBtcPk := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk) - - pagination := &sdkquery.PageRequest{ - // NOTE: the count is limited by pagination queries - Limit: count, - Reverse: true, - } - - res, err := bc.bbnClient.QueryClient.ListPublicRandomness(fpBtcPk.MarshalHex(), pagination) +func (bc *BabylonController) QueryLastFinalizedEpoch() (uint64, error) { + resp, err := bc.bbnClient.LatestEpochFromStatus(ckpttypes.Finalized) if err != nil { - return nil, fmt.Errorf("failed to query committed public randomness: %w", err) - } - - committedPubRand := make(map[uint64]*btcec.FieldVal, len(res.PubRandMap)) - for k, v := range res.PubRandMap { - if v == nil { - return nil, fmt.Errorf("invalid committed public randomness") - } - committedPubRand[k] = v.ToFieldVal() + return 0, err } - - return committedPubRand, nil + return resp.RawCheckpoint.EpochNum, nil } func (bc *BabylonController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { @@ -397,6 +359,10 @@ func (bc *BabylonController) Close() error { Implementations for e2e tests only */ +func (bc *BabylonController) GetBBNClient() *bbnclient.Client { + return bc.bbnClient +} + func (bc *BabylonController) CreateBTCDelegation( delBabylonPk *secp256k1.PubKey, delBtcPk *bbntypes.BIP340PubKey, @@ -457,8 +423,8 @@ func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderB return res, nil } -func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.FinalityProvider, error) { - var fps []*btcstakingtypes.FinalityProvider +func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.FinalityProviderResponse, error) { + var fps []*btcstakingtypes.FinalityProviderResponse pagination := &sdkquery.PageRequest{ Limit: 100, } @@ -479,7 +445,7 @@ func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.Finali return fps, nil } -func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { +func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfoResponse, error) { res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip() if err != nil { return nil, fmt.Errorf("failed to query BTC tip: %v", err) @@ -497,18 +463,18 @@ func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP34 return res.BtcPks, nil } -func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegationResponse, error) { return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } -func (bc *BabylonController) QueryActiveDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) QueryActiveDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegationResponse, error) { return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_ACTIVE, limit) } // queryDelegationsWithStatus queries BTC delegations // with the given status (either pending or unbonding) // it is only used when the program is running in Covenant mode -func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegationResponse, error) { pagination := &sdkquery.PageRequest{ Limit: limit, } @@ -584,3 +550,17 @@ func (bc *BabylonController) SubmitCovenantSigs( return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } + +func (bc *BabylonController) InsertSpvProofs(submitter string, proofs []*btcctypes.BTCSpvProof) (*provider.RelayerTxResponse, error) { + msg := &btcctypes.MsgInsertBTCSpvProof{ + Submitter: submitter, + Proofs: proofs, + } + + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) + if err != nil { + return nil, err + } + + return res, nil +} diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 10d7fb2e..f6597c21 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -5,11 +5,10 @@ import ( "cosmossdk.io/math" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg" "go.uber.org/zap" - "github.com/babylonchain/finality-provider/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/types" ) @@ -27,11 +26,8 @@ type ClientController interface { pop []byte, commission *math.LegacyDec, description []byte, - ) (*types.TxResponse, error) - - // CommitPubRandList commits a list of EOTS public randomness the consumer chain - // it returns tx hash and error - CommitPubRandList(fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) + masterPubRand string, + ) (*types.TxResponse, uint64, error) // SubmitFinalitySig submits the finality signature to the consumer chain SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) @@ -50,9 +46,6 @@ type ClientController interface { // QueryLatestFinalizedBlocks returns the latest finalized blocks QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) - // QueryLastCommittedPublicRand returns the last committed public randomness - QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) - // QueryBlock queries the block at the given height QueryBlock(height uint64) (*types.BlockInfo, error) @@ -66,10 +59,13 @@ type ClientController interface { // error will be returned if the consumer chain has not been activated QueryActivatedHeight() (uint64, error) + // QueryLastFinalizedEpoch returns the last finalised epoch of Babylon + QueryLastFinalizedEpoch() (uint64, error) + Close() error } -func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { +func NewClientController(chainName string, bbnConfig *fpcfg.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { var ( cc ClientController err error diff --git a/clientcontroller/retry_utils.go b/clientcontroller/retry_utils.go index d216dabb..fb64590b 100644 --- a/clientcontroller/retry_utils.go +++ b/clientcontroller/retry_utils.go @@ -2,6 +2,7 @@ package clientcontroller import ( "errors" + "strings" sdkErr "cosmossdk.io/errors" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" @@ -22,7 +23,9 @@ var unrecoverableErrors = []*sdkErr.Error{ // IsUnrecoverable returns true when the error is in the unrecoverableErrors list func IsUnrecoverable(err error) bool { for _, e := range unrecoverableErrors { - if errors.Is(err, e) { + // cannot use error.Is because the unwrapped error + // is not the expected error type + if strings.Contains(err.Error(), e.Error()) { return true } } diff --git a/config/db.go b/config/db.go deleted file mode 100644 index e19be729..00000000 --- a/config/db.go +++ /dev/null @@ -1,36 +0,0 @@ -package config - -import "fmt" - -const ( - DefaultBackend = "bbolt" - DefaultDBName = "default" -) - -type DatabaseConfig struct { - Backend string `long:"backend" description:"Possible database to choose as backend"` - Name string `long:"name" description:"The name of the database"` -} - -func NewDatabaseConfig(backend string, name string) (*DatabaseConfig, error) { - // TODO: add more supported DB types, currently we only support bbolt - if backend != DefaultBackend { - return nil, fmt.Errorf("unsupported DB backend") - } - - if name == "" { - return nil, fmt.Errorf("bucket name should not be empty") - } - - return &DatabaseConfig{ - Backend: backend, - Name: name, - }, nil -} - -func DefaultDatabaseConfig() DatabaseConfig { - return DatabaseConfig{ - Backend: DefaultBackend, - Name: DefaultDBName, - } -} diff --git a/docs/eots.md b/docs/eots.md index b7f14dd3..36fa324c 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -2,43 +2,43 @@ ## 1. Overview -The EOTS daemon is responsible for managing EOTS keys, -producing EOTS randomness, and using them to produce EOTS signatures. +The EOTS daemon is responsible for managing EOTS keys, producing EOTS randomness, and +using them to produce EOTS signatures. **Note:** EOTS stands for Extractable One Time Signature. You can read more about it in the [Babylon BTC Staking Litepaper](https://docs.babylonchain.io/assets/files/btc_staking_litepaper-32bfea0c243773f0bfac63e148387aef.pdf). -In short, the EOTS manager produces EOTS public/private randomness pairs. -The finality provider commits the public part of this pairs to Babylon for -every future block height that they intend to provide a finality signature for. -If the finality provider votes for two different blocks on the same height, -they will have to reuse the same private randomness which will lead to their -underlying private key being exposed, leading to the slashing of them and all their delegators. +In short, the EOTS manager produces EOTS public/private randomness pairs. The +finality provider commits the public part of this pairs to Babylon for every future +block height that they intend to provide a finality signature for. If the finality +provider votes for two different blocks on the same height, they will have to reuse +the same private randomness which will lead to their underlying private key being +exposed, leading to the slashing of them and all their delegators. The EOTS manager is responsible for the following operations: + 1. **EOTS Key Management:** - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs for a given finality provider using the [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) standard. - - Persists generated key pairs in the - internal Cosmos keyring. + - Persists generated key pairs in the internal Cosmos keyring. 2. **Randomness Generation:** - Generates lists of EOTS randomness pairs based on the EOTS key, chainID, and block height. - The randomness is deterministically generated and tied to specific parameters. 3. **Signature Generation:** - - Signs EOTS using the private key of the finality provider and the corresponding secret - randomness for a given chain at a specified height. + - Signs EOTS using the private key of the finality provider and the corresponding + secret randomness for a given chain at a specified height. - Signs Schnorr signatures using the private key of the finality provider. The EOTS manager functions as a daemon controlled by the `eotsd` tool. ## 2. Configuration -The `eotsd init` command initializes a home directory for the EOTS -manager. This directory is created in the default home location or in a location -specified by the `--home` flag. +The `eotsd init` command initializes a home directory for the EOTS manager. This +directory is created in the default home location or in a location specified by +the `--home` flag. ```bash eotsd init --home /path/to/eotsd/home/ @@ -52,33 +52,110 @@ ls /path/to/eotsd/home/ ├── logs # Eotsd logs ``` -If the `--home` flag is not specified, then the default home location will -be used. For different operating systems, those are: +If the `--home` flag is not specified, then the default home location will be used. +For different operating systems, those are: - **MacOS** `~/Users//Library/Application Support/Eotsd` - **Linux** `~/.Eotsd` - **Windows** `C:\Users\\AppData\Local\Eotsd` -Below are the `eotsd.conf` file contents: +## 3. Keys Management -```bash -# Default address to listen for RPC connections -RpcListener = 127.0.0.1:12582 +Handles the keys for EOTS. + +### 3.1. Create EOTS Keys + +The binary `eotsd` has the option to add a new key to the keyring for +later usage with signing EOTS and Schnorr signatures. Keep in mind +that new keys can be created on demand by the GRPC call from `fpd`. +But, if you would like to add a new EOTS keys manually, run `eotsd keys add`. + +This command has several flag options: + +- `--home` specifies the home directory of the `eotsd` in which +the new key will be stored. +- `--key-name` mandatory flag and identifies the name of the key to be generated. +- `--passphrase` specifies the password used to encrypt the key, if such a +passphrase is required. +- `--hd-path` the hd derivation path of the private key. +- `--keyring-backend` specifies the keyring backend, any of `[file, os, kwallet, test, pass, memory]` +are available, by default `test` is used. +- `--recover` indicates whether the user wants to provide a seed phrase to recover +the existing key instead of randomly creating. + +```shell +eotsd keys add --home /path/to/eotsd/home/ --key-name my-key-name --keyring-backend file + +Enter keyring passphrase (attempt 1/3): +... + +2024-04-25T17:11:09.369163Z info successfully created an EOTS key {"key name": "my-key-name", "pk": "50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383"} +New key for the BTC chain is created (mnemonic should be kept in a safe place for recovery): +{ + "name": "my-key-name", + "pub_key_hex": "50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383", + "mnemonic": "bad mnemonic private tilt wish bulb miss plate achieve manage feel word safe dash vanish little miss hockey connect tail certain spread urban series" +} +``` + +> Store the mnemonic in a safe place. With the mnemonic only it is possible to +recover the generated keys by using the `--recover` flag. -# Type of keyring to use -KeyringBackend = test +### 3.2. Recover Keys -# Possible database to choose as backend -Backend = bbolt +To recover the keys from a mnemonic, run: -# Path to the database -Path = bbolt-eots.db +```shell +eotsd keys add --home /path/to/eotsd/home/ --key-name my-key-name --keyring-backend file --recover -# Name of the database -Name = default +> Enter your mnemonic +bad mnemonic private tilt wish bulb miss plate achieve manage feel word safe dash vanish little miss hockey connect tail certain spread urban series +2024-04-25T17:13:29.681324Z info successfully created an EOTS key {"key name": "my-key-name", "pk": "50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383"} +New key for the BTC chain is created (mnemonic should be kept in a safe place for recovery): +{ + "name": "my-key-name", + "pub_key_hex": "50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383", + "mnemonic": "noise measure tuition inform battle swallow slender bundle horn pigeon wage mule average bicycle claim solve home swamp banner idle chapter surround edit gossip" +} ``` -## 3. Starting the EOTS Daemon +You will be prompted to provide the mnemonic on key creation. + +### 3.3. Sign Schnorr Signatures + +You can use your key to create a Schnorr signature over arbitrary data +through the `eotsd sign-schnorr` command. +The command takes as an argument the file path, hashes the file content using +sha256, and signs the hash with the EOTS private key in Schnorr format by the +given `key-name` or `btc-pk`. If both flags `--key-name` and `--btc-pk` are +provided, `btc-pk` takes priority. + +```shell +eotsd sign-schnorr /path/to/data/file --home /path/to/eotsd/home/ --key-name my-key-name +{ + "key_name": "my-key-name", + "pub_key_hex": "50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383", + "signed_data_hash_hex": "b123ef5f69545cd07ad505c6d3b4931aa87b6adb361fb492275bb81374d98953", + "schnorr_signature_hex": "b91fc06b30b78c0ca66a7e033184d89b61cd6ab572329b20f6052411ab83502effb5c9a1173ed69f20f6502a741eeb5105519bb3f67d37612bc2bcce411f8d72" +} +``` + +### 3.4. Verify Schnorr Signatures + +You can verify the Schnorr signature signed in the previous step through +the `eptsd veify-schnorr-sig` command. +The command takes as an argument the file path, hashes the file content using +sha256 to generate the signed data, and verifies the signature from the `--signature` +flag using the given public key from the `--btc-pk` flag. +If the signature is valid, you will see `Verification is successful!` in the output. +Otherwise, an error message will be printed out. + +```shell +eotsd verify-schnorr-sig /path/to/data/file --btc-pk 50b106208c921b5e8a1c45494306fe1fc2cf68f33b8996420867dc7667fde383 \ +--signature b91fc06b30b78c0ca66a7e033184d89b61cd6ab572329b20f6052411ab83502effb5c9a1173ed69f20f6502a741eeb5105519bb3f67d37612bc2bcce411f8d72 +``` + +## 4. Starting the EOTS Daemon You can start the EOTS daemon using the following command: @@ -86,15 +163,18 @@ You can start the EOTS daemon using the following command: eotsd start --home /path/to/eotsd/home ``` -This will start the rpc server at the address specified in the configuration under -the `RpcListener` field, which has a default value of `127.0.0.1:12582`. -You can also specify a custom address using the `--rpc-listener` flag. +If the `--home` flag is not specified, then the default home location will be used. + +This will start the EOTS rpc server at the address specified in `eotsd.conf` under +the `RpcListener` field, which is by default set to `127.0.0.1:12582`. You can change +this value in the configuration file or override this value and specify a custom +address using the `--rpc-listener` flag. ```bash eotsd start -time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:12582"}" -time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager Daemon is fully active!" +2024-02-08T17:59:11.467212Z info RPC server listening {"address": "127.0.0.1:12582"} +2024-02-08T17:59:11.467660Z info EOTS Manager Daemon is fully active! ``` All the available cli options can be viewed using the `--help` flag. These options @@ -103,5 +183,5 @@ can also be set in the configuration file. **Note**: It is recommended to run the `eotsd` daemon on a separate machine or network segment to enhance security. This helps isolate the key management functionality and reduces the potential attack surface. You can edit the -`EOTSManagerAddress` in the configuration file of the finality provider -to reference the address of the machine where `eotsd` is running. +`EOTSManagerAddress` in the configuration file of the finality provider to reference +the address of the machine where `eotsd` is running. diff --git a/docs/finality-provider.md b/docs/finality-provider.md index ecd4949c..b2c6c410 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -2,35 +2,32 @@ ## 1. Overview -The Finality Provider Daemon is responsible for -monitoring for new Babylon blocks, -committing public randomness for the blocks it -intends to provide finality signatures for, and -submitting finality signatures. - -The daemon can manage and perform the following operations for multiple -finality providers: -1. **Creation and Registration**: Creates and registers finality - providers to Babylon. -2. **EOTS Randomness Commitment**: The daemon monitors the Babylon chain and - commits EOTS public randomness for every Babylon block each - finality provider intends to vote for. The commit intervals can be specified - in the configuration. - The EOTS public randomness is retrieved through the finality provider daemon's - connection with the [EOTS daemon](eots.md). -3. **Finality Votes Submission**: The daemon monitors the Babylon chain - and produces finality votes for each block each maintained finality provider - has committed to vote for. - -The daemon is controlled by the `fpd` tool. -The `fpcli` tool implements commands for interacting with the daemon. +The Finality Provider Daemon is responsible for monitoring for new Babylon blocks, +committing public randomness for the blocks it intends to provide finality signatures +for, and submitting finality signatures. + +The daemon can manage and perform the following operations for multiple finality +providers: + +1. **Creation and Registration**: Creates and registers finality providers to + Babylon. +2. **EOTS Randomness Commitment**: The daemon monitors the Babylon chain and commits + EOTS public randomness for every Babylon block each finality provider intends to + vote for. The commit intervals can be specified in the configuration. The EOTS + public randomness is retrieved through the finality provider daemon's connection + with the [EOTS daemon](eots.md). +3. **Finality Votes Submission**: The daemon monitors the Babylon chain and produces + finality votes for each block each maintained finality provider has committed to + vote for. + +The daemon is controlled by the `fpd` tool. The `fpcli` tool implements commands for +interacting with the daemon. ## 2. Configuration -The `fpd init` command initializes a home directory for the -finality provider daemon. -This directory is created in the default home location or in a -location specified by the `--home` flag. +The `fpd init` command initializes a home directory for the finality provider daemon. +This directory is created in the default home location or in a location specified by +the `--home` flag. ```bash fpd init --home /path/to/fpd/home/ @@ -44,8 +41,8 @@ ls /path/to/fpd/home/ ├── logs # Fpd logs ``` -If the `--home` flag is not specified, then the default home directory -will be used. For different operating systems, those are: +If the `--home` flag is not specified, then the default home directory will be used. +For different operating systems, those are: - **MacOS** `~/Users//Library/Application Support/Fpd` - **Linux** `~/.Fpd` @@ -55,33 +52,34 @@ Below are some important parameters of the `fpd.conf` file. **Note**: The configuration below requires to point to the path where this keyring is -stored `KeyDirectory`. This `Key` field stores the key name used for -interacting with the consumer chain and will be specified along with the -`KeyringBackend` field in the next [step](#3-add-key-for-the-consumer-chain). -So we can ignore the setting of the two fields in this step. +stored `KeyDirectory`. This `Key` field stores the key name used for interacting with +the consumer chain and will be specified along with the +`KeyringBackend` field in the next [step](#3-add-key-for-the-consumer-chain). So we +can ignore the setting of the two fields in this step. ```bash +[Application Options] # RPC Address of the EOTS Daemon EOTSManagerAddress = 127.0.0.1:12582 -# Babylon specific parameters +# RPC Address of the Finality Provider Daemon +RpcListener = 127.0.0.1:12581 -# Babylon chain ID -ChainID = chain-test +[babylon] +# Name of the key to sign transactions with +Key = + +# Chain id of the chain to connect to +# Please verify the `ChainID` from the Babylon RPC node https://rpc.testnet3.babylonchain.io/status +ChainID = bbn-test-3 -# Babylon node RPC endpoint +# RPC Address of Babylon node RPCAddr = http://127.0.0.1:26657 -# Babylon node gRPC endpoint +# GRPC Address of Babylon node GRPCAddr = https://127.0.0.1:9090 -# Name of the key in the keyring to use for signing transactions -Key = - -# Type of keyring to use -KeyringBackend = test - -# Directory where keys will be retrieved from and stored +# Directory to store keys in KeyDirectory = /path/to/fpd/home ``` @@ -89,38 +87,29 @@ To see the complete list of configuration options, check the `fpd.conf` file. **Additional Notes:** -1. We strongly recommend that EOTS randomness commitments are limited to 500 - blocks (default value: 100 blocks) - - ```bash - ; The number of Schnorr public randomness for each commitment - NumPubRand = 100 +If you encounter any gas-related errors while performing staking operations, consider +adjusting the `GasAdjustment` and `GasPrices` parameters. For example, you can set: - ; The upper bound of the number of Schnorr public randomness for each commitment - NumPubRandMax = 100 - ``` - -2. If you encounter any gas-related errors while performing staking operations, - consider adjusting the `GasAdjustment` and `GasPrices` parameters. For example, - you can set: - - ```bash - GasAdjustment = 1.5 - GasPrices = 0.01ubbn - ``` +```bash +GasAdjustment = 1.5 +GasPrices = 0.002ubbn +``` ## 3. Add key for the consumer chain -The finality provider daemon requires the existence of a keyring that contains -an account with Babylon token funds to pay for transactions. -This key will be also used to pay for fees of transactions to the consumer chain. +The finality provider daemon requires the existence of a keyring that contains an +account with Babylon token funds to pay for transactions. This key will be also used +to pay for fees of transactions to the consumer chain. Use the following command to add the key: ```bash -fpd keys add --key-name my-finality-provider --chain-id chain-test +fpd keys add --key-name my-finality-provider --chain-id bbn-test-3 ``` +**Note**: Please verify the `chain-id` from the Babylon RPC +node https://rpc.testnet3.babylonchain.io/status + After executing the above command, the key name will be saved in the config file created in [step](#2-configuration). @@ -132,42 +121,44 @@ You can start the finality provider daemon using the following command: fpd start --home /path/to/fpd/home ``` -This will start the RPC server at the address specified in the configuration -under the `RpcListener` field, which has a default value of `127.0.0.1:12581`. -You can also specify a custom address using the `--rpc-listener` flag. +If the `--home` flag is not specified, then the default home location will be used. + +This will start the Finality provider RPC server at the address specified +in `fpd.conf` under the `RpcListener` field, which has a default value +of `127.0.0.1:12581`. You can change this value in the configuration file or override +this value and specify a custom address using the `--rpc-listener` flag. This will also start all the registered finality provider instances except for -slashed ones added in [step](#5-create-and-register-a-finality-provider). -To start the daemon with a specific finality provider instance, use the -`--btc-pk` flag followed by the hex string of the BTC public key of the -finality provider (`btc_pk_hex`) obtained in [step](#5-create-and-register-a-finality-provider). +slashed ones added in [step](#5-create-and-register-a-finality-provider). To start +the daemon with a specific finality provider instance, use the +`--btc-pk` flag followed by the hex string of the BTC public key of the finality +provider (`btc_pk_hex`) obtained +in [step](#5-create-and-register-a-finality-provider). ```bash -fpd start --rpc-listener '127.0.0.1:8088' +fpd start -time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager {"address": "127.0.0.1:12582"}" -time="2023-11-26T16:37:00-05:00" level=info msg="Starting FinalityProviderApp" -time="2023-11-26T16:37:00-05:00" level=info msg="Starting RPC Server" -time="2023-11-26T16:37:00-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:12581"}" -time="2023-11-26T16:37:00-05:00" level=info msg="Finality Provider Daemon is fully active!" +2024-02-08T18:43:00.705008Z info successfully connected to a remote EOTS manager {"address": "127.0.0.1:12582"} +2024-02-08T18:43:00.712995Z info Starting FinalityProviderApp +2024-02-08T18:43:00.716682Z info RPC server listening {"address": "127.0.0.1:12581"} +2024-02-08T18:43:00.716979Z info Finality Provider Daemon is fully active! ``` -All the available CLI options can be viewed using the `--help` flag. -These options can also be set in the configuration file. +All the available CLI options can be viewed using the `--help` flag. These options +can also be set in the configuration file. ## 5. Create and Register a Finality Provider We create a finality provider instance through the -`fpcli create-finality-provider` or `fpcli cfp` command. -The created instance is associated with a BTC public key which -serves as its unique identifier and -a Babylon account to which staking rewards will be directed. -Note that if the `--key-name` flag is not specified, the `Key` field of -config specified in [step](#3-add-key-for-the-consumer-chain) will be used. +`fpcli create-finality-provider` or `fpcli cfp` command. The created instance is +associated with a BTC public key which serves as its unique identifier and a Babylon +account to which staking rewards will be directed. Note that if the `--key-name` flag +is not specified, the `Key` field of config specified +in [step](#3-add-key-for-the-consumer-chain) will be used. ```bash fpcli create-finality-provider --key-name my-finality-provider \ - --chain-id chain-test --moniker my-name + --chain-id bbn-test-3 --moniker my-name { "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", "btc_pk_hex": "d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63", @@ -179,34 +170,34 @@ fpcli create-finality-provider --key-name my-finality-provider \ ``` We register a created finality provider in Babylon through -the `fpcli register-finality-provider` or `fpcli rfp` command. -The output contains the hash of the Babylon finality provider registration -transaction. +the `fpcli register-finality-provider` or `fpcli rfp` command. The output contains +the hash of the Babylon finality provider registration transaction. ```bash fpcli register-finality-provider \ - --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 + --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 { - "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" + "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" } + ``` -A finality provider instance will be initiated and start running right after -the finality provider is successfully registered in Babylon. +A finality provider instance will be initiated and start running right after the +finality provider is successfully registered in Babylon. We can view the status of all the running finality providers through -the `fpcli list-finality-providers` or `fpcli ls` command. -The `status` field can receive the following values: +the `fpcli list-finality-providers` or `fpcli ls` command. The `status` field can +receive the following values: - `CREATED`: The finality provider is created but not registered yet -- `REGISTERED`: The finality provider is registered but has not received any - active delegations yet -- `ACTIVE`: The finality provider has active delegations and is empowered to - send finality signatures -- `INACTIVE`: The finality provider used to be ACTIVE but the voting power is - reduced to zero +- `REGISTERED`: The finality provider is registered but has not received any active + delegations yet +- `ACTIVE`: The finality provider has active delegations and is empowered to send + finality signatures +- `INACTIVE`: The finality provider used to be ACTIVE but the voting power is reduced + to zero - `SLASHED`: The finality provider is slashed due to malicious behavior - + ```bash fpcli list-finality-providers { @@ -224,3 +215,51 @@ fpcli list-finality-providers ] } ``` + +After the creation of the finality provider in the local db, it is possible +to export the finality provider information through the `fpcli export-finality-provider` command. +This command connects with the `fpd` daemon to retrieve the finality +provider previously created using the flag `--btc-pk` as key. + +This command also has several flag options: + +- `--btc-pk` the hex string of the BTC public key. +- `--daemon-address` the RPC server address of `fpd` daemon. +- `--signed` signs the finality provider with the chain key of the PoS +chain secured as a proof of untempered exported data. +- `--key-name` identifies the name of the key to use to sign the finality provider. +- `--home` specifies the home directory of the finality provider daemon in which +the finality provider db is stored. +- `--passphrase` specifies the password used to encrypt the key, if such a +passphrase is required. +- `--hd-path` the hd derivation path of the private key. + +```shell +$ fpcli export-finality-provider --btc-pk 02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077 \ +--home ./export-fp/fpd --key-name finality-provider --signed +``` + +The expected result is a JSON object corresponding to the finality provider information. + +```json +{ + "description": { + "moniker": "my-fp-nickname", + "identity": "anyIdentity", + "website": "www.my-public-available-website.com", + "security_contact": "your.email@gmail.com", + "details": "other overall info" + }, + "commission": "0.050000000000000000", + "babylon_pk": { + "key": "AtPEagBqVQUL6og0qH+H44pFf9p3WcHAva+zC2+74X8p" + }, + "btc_pk": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", + "pop": { + "babylon_sig": "sAg34vImQTFVlZYsziw9PCCKDuRyZv38V2MX8Ij9fQhyOdpxCUZ1VEgpSlwV/dbnpDs1UOez8Ni9EcbADkmnBA==", + "btc_sig": "sHLpEHVTyTp9K55oeHxnPlkV4unc/r1obqzKn5S1gq95oXA3AgL1jyCzd/mGb23RfKbEyABjYUdcIBtZ02l5jg==" + }, + "master_pub_rand": "xpub661MyMwAqRbcFLhUq9uPM7GncSytVZvoNg4w7LLx1Y74GeeAZerkpV1amvGBTcw4ECmrwFsTNMNf1LFBKkA2pmd8aJ5Jmp8uKD5xgVSezBq", + "fp_sig_hex": "8ded8158bf65d492c5c6d1ff61c04a2176da9c55ea92dcce5638d11a177b999732a094db186964ab1b73c6a69aaa664672a36620dedb9da41c05e88ad981edda" +} +``` diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 585e9daf..d35f9fc6 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -60,27 +60,18 @@ func (c *EOTSManagerGRpcClient) CreateKey(name, passphrase, hdPath string) ([]by return res.Pk, nil } -func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { - req := &proto.CreateRandomnessPairListRequest{ - Uid: uid, - ChainId: chainID, - StartHeight: startHeight, - Num: num, - Passphrase: passphrase, +func (c *EOTSManagerGRpcClient) CreateMasterRandPair(uid, chainID []byte, passphrase string) (string, error) { + req := &proto.CreateMasterRandPairRequest{ + Uid: uid, + ChainId: chainID, + Passphrase: passphrase, } - res, err := c.client.CreateRandomnessPairList(context.Background(), req) + res, err := c.client.CreateMasterRandPair(context.Background(), req) if err != nil { - return nil, err - } - - pubRandFieldValList := make([]*btcec.FieldVal, 0, len(res.PubRandList)) - for _, r := range res.PubRandList { - var fieldVal btcec.FieldVal - fieldVal.SetByteSlice(r) - pubRandFieldValList = append(pubRandFieldValList, &fieldVal) + return "", err } - return pubRandFieldValList, nil + return res.MasterPubRand, nil } func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) { diff --git a/eotsmanager/cmd/eotsd/daemon/flags.go b/eotsmanager/cmd/eotsd/daemon/flags.go new file mode 100644 index 00000000..c4679a5b --- /dev/null +++ b/eotsmanager/cmd/eotsd/daemon/flags.go @@ -0,0 +1,22 @@ +package daemon + +import "github.com/cosmos/cosmos-sdk/crypto/keyring" + +const ( + homeFlag = "home" + forceFlag = "force" + rpcListenerFlag = "rpc-listener" + fpPkFlag = "btc-pk" + signatureFlag = "signature" + + // flags for keys + keyNameFlag = "key-name" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + keyringBackendFlag = "keyring-backend" + recoverFlag = "recover" + + defaultKeyringBackend = keyring.BackendTest + defaultHdPath = "" + defaultPassphrase = "" +) diff --git a/eotsmanager/cmd/eotsd/init.go b/eotsmanager/cmd/eotsd/daemon/init.go similarity index 90% rename from eotsmanager/cmd/eotsd/init.go rename to eotsmanager/cmd/eotsd/daemon/init.go index faf0389a..9855ab31 100644 --- a/eotsmanager/cmd/eotsd/init.go +++ b/eotsmanager/cmd/eotsd/daemon/init.go @@ -1,4 +1,4 @@ -package main +package daemon import ( "fmt" @@ -11,7 +11,7 @@ import ( "github.com/babylonchain/finality-provider/util" ) -var initCommand = cli.Command{ +var InitCommand = cli.Command{ Name: "init", Usage: "Initialize the eotsd home directory.", Flags: []cli.Flag{ @@ -57,7 +57,8 @@ func initHome(c *cli.Context) error { } defaultConfig := eotscfg.DefaultConfig() - fileParser := flags.NewParser(&defaultConfig, flags.Default) + defaultConfig.DatabaseConfig.DBPath = dataDir + fileParser := flags.NewParser(defaultConfig, flags.Default) return flags.NewIniParser(fileParser).WriteFile(eotscfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) } diff --git a/eotsmanager/cmd/eotsd/daemon/keys.go b/eotsmanager/cmd/eotsd/daemon/keys.go new file mode 100644 index 00000000..f6efa4ca --- /dev/null +++ b/eotsmanager/cmd/eotsd/daemon/keys.go @@ -0,0 +1,167 @@ +package daemon + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/go-bip39" + "github.com/urfave/cli" + + bbntypes "github.com/babylonchain/babylon/types" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/log" +) + +type KeyOutput struct { + Name string `json:"name" yaml:"name"` + PubKeyHex string `json:"pub_key_hex" yaml:"pub_key_hex"` + Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"` +} + +var KeysCommands = []cli.Command{ + { + Name: "keys", + Usage: "Command sets of managing keys for interacting with BTC eots keys.", + Category: "Key management", + Subcommands: []cli.Command{ + AddKeyCmd, + }, + }, +} + +var AddKeyCmd = cli.Command{ + Name: "add", + Usage: "Add a key to the EOTS manager keyring.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to the keyring directory", + Value: config.DefaultEOTSDir, + }, + cli.StringFlag{ + Name: keyNameFlag, + Usage: "The name of the key to be created", + Required: true, + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: hdPathFlag, + Usage: "The hd path used to derive the private key", + Value: defaultHdPath, + }, + cli.StringFlag{ + Name: keyringBackendFlag, + Usage: "The backend of the keyring", + Value: defaultKeyringBackend, + }, + cli.BoolFlag{ + Name: recoverFlag, + Usage: `Will need to provide a seed phrase to recover + the existing key instead of creating`, + }, + }, + Action: addKey, +} + +func addKey(ctx *cli.Context) error { + keyName := ctx.String(keyNameFlag) + keyringBackend := ctx.String(keyringBackendFlag) + + homePath, err := getHomeFlag(ctx) + if err != nil { + return fmt.Errorf("failed to load home flag: %w", err) + } + + cfg, err := config.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load config at %s: %w", homePath, err) + } + + logger, err := log.NewRootLoggerWithFile(config.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to load the logger") + } + + dbBackend, err := cfg.DatabaseConfig.GetDbBackend() + if err != nil { + return fmt.Errorf("failed to create db backend: %w", err) + } + defer dbBackend.Close() + + eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, keyringBackend, dbBackend, logger) + if err != nil { + return fmt.Errorf("failed to create EOTS manager: %w", err) + } + + eotsPk, mnemonic, err := createKey(ctx, eotsManager, keyName) + if err != nil { + return fmt.Errorf("failed to create key: %w", err) + } + + printRespJSONKeys( + KeyOutput{ + Name: keyName, + PubKeyHex: eotsPk.MarshalHex(), + Mnemonic: mnemonic, + }, + ) + return nil +} + +// createKey checks if recover flag is set to create a key from mnemonic or if not set, randomly creates it. +func createKey( + ctx *cli.Context, + eotsManager *eotsmanager.LocalEOTSManager, + keyName string, +) (eotsPk *bbntypes.BIP340PubKey, mnemonic string, err error) { + passphrase := ctx.String(passphraseFlag) + hdPath := ctx.String(hdPathFlag) + + mnemonic, err = getMnemonic(ctx) + if err != nil { + return nil, "", err + } + + eotsPk, err = eotsManager.CreateKeyWithMnemonic(keyName, passphrase, hdPath, mnemonic) + if err != nil { + return nil, "", err + } + return eotsPk, mnemonic, nil +} + +func getMnemonic(ctx *cli.Context) (string, error) { + if ctx.Bool(recoverFlag) { + reader := bufio.NewReader(os.Stdin) + mnemonic, err := input.GetString("Enter your mnemonic", reader) + if err != nil { + return "", fmt.Errorf("failed to read mnemonic from stdin: %w", err) + } + if !bip39.IsMnemonicValid(mnemonic) { + return "", errors.New("invalid mnemonic") + } + + return mnemonic, nil + } + + return eotsmanager.NewMnemonic() +} + +func printRespJSONKeys(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("New key for the BTC chain is created "+ + "(mnemonic should be kept in a safe place for recovery):\n%s\n", jsonBytes) +} diff --git a/eotsmanager/cmd/eotsd/daemon/sign.go b/eotsmanager/cmd/eotsd/daemon/sign.go new file mode 100644 index 00000000..abfa14d1 --- /dev/null +++ b/eotsmanager/cmd/eotsd/daemon/sign.go @@ -0,0 +1,230 @@ +package daemon + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "os" + + bbntypes "github.com/babylonchain/babylon/types" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/log" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/urfave/cli" +) + +type DataSigned struct { + KeyName string `json:"key_name"` + PubKeyHex string `json:"pub_key_hex"` + SignedDataHashHex string `json:"signed_data_hash_hex"` + SchnorrSignatureHex string `json:"schnorr_signature_hex"` +} + +var SignSchnorrSig = cli.Command{ + Name: "sign-schnorr", + Usage: "Signs a Schnorr signature over arbitrary data with the EOTS private key.", + UsageText: "sign-schnorr [file-path]", + Description: `Read the file received as argument, hash it with + sha256 and sign based on the Schnorr key associated with the key-name or btc-pk flag. + If the both flags are supplied, btc-pk takes priority`, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to the keyring directory", + Value: config.DefaultEOTSDir, + }, + cli.StringFlag{ + Name: keyNameFlag, + Usage: "The name of the key to load private key for signing", + }, + cli.StringFlag{ + Name: fpPkFlag, + Usage: "The public key of the finality-provider to load private key for signing", + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The passphrase used to decrypt the keyring", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: keyringBackendFlag, + Usage: "The backend of the keyring", + Value: defaultKeyringBackend, + }, + }, + Action: SignSchnorr, +} + +var VerifySchnorrSig = cli.Command{ + Name: "verify-schnorr-sig", + Usage: "Verify a Schnorr signature over arbitrary data with the given public key.", + UsageText: "verify-schnorr-sig [file-path]", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpPkFlag, + Usage: "The EOTS public key that will be used to verify the signature", + Required: true, + }, + cli.StringFlag{ + Name: signatureFlag, + Usage: "The hex signature to verify", + Required: true, + }, + }, + Action: SignSchnorrVerify, +} + +func SignSchnorrVerify(ctx *cli.Context) error { + fpPkStr := ctx.String(fpPkFlag) + signatureHex := ctx.String(signatureFlag) + + args := ctx.Args() + inputFilePath := args.First() + if len(inputFilePath) == 0 { + return errors.New("invalid argument, please provide a valid file path as input argument") + } + + hashOfMsgToSign, err := hashFromFile(inputFilePath) + if err != nil { + return fmt.Errorf("failed to generate hash from file %s: %w", inputFilePath, err) + } + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return fmt.Errorf("invalid finality-provider public key %s: %w", fpPkStr, err) + } + + pubKey, err := schnorr.ParsePubKey(*fpPk) + if err != nil { + return fmt.Errorf("unable to parse public key %s: %w", fpPkStr, err) + } + + signatureBz, err := hex.DecodeString(signatureHex) + if err != nil { + return fmt.Errorf("unable to decode signature %s: %w", signatureHex, err) + } + + signature, err := schnorr.ParseSignature(signatureBz) + if err != nil { + return fmt.Errorf("unable to parse schnorr signature %s: %w", signatureBz, err) + } + + if !signature.Verify(hashOfMsgToSign, pubKey) { + return errors.New("invalid signature") + } + + fmt.Print("Verification is successful!") + return nil +} + +func SignSchnorr(ctx *cli.Context) error { + keyName := ctx.String(keyNameFlag) + fpPkStr := ctx.String(fpPkFlag) + passphrase := ctx.String(passphraseFlag) + keyringBackend := ctx.String(keyringBackendFlag) + + args := ctx.Args() + inputFilePath := args.First() + if len(inputFilePath) == 0 { + return errors.New("invalid argument, please provide a valid file path as input argument") + } + + if len(fpPkStr) == 0 && len(keyName) == 0 { + return fmt.Errorf("at least one of the flags: %s, %s needs to be informed", keyNameFlag, fpPkFlag) + } + + homePath, err := getHomeFlag(ctx) + if err != nil { + return fmt.Errorf("failed to load home flag: %w", err) + } + + cfg, err := config.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load config at %s: %w", homePath, err) + } + + logger, err := log.NewRootLoggerWithFile(config.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to load the logger") + } + + dbBackend, err := cfg.DatabaseConfig.GetDbBackend() + if err != nil { + return fmt.Errorf("failed to create db backend: %w", err) + } + defer dbBackend.Close() + + eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, keyringBackend, dbBackend, logger) + if err != nil { + return fmt.Errorf("failed to create EOTS manager: %w", err) + } + + hashOfMsgToSign, err := hashFromFile(inputFilePath) + if err != nil { + return fmt.Errorf("failed to generate hash from file %s: %w", inputFilePath, err) + } + + signature, pubKey, err := singMsg(eotsManager, keyName, fpPkStr, passphrase, hashOfMsgToSign) + if err != nil { + return fmt.Errorf("failed to sign msg: %w", err) + } + + printRespJSON(DataSigned{ + KeyName: keyName, + PubKeyHex: pubKey.MarshalHex(), + SignedDataHashHex: hex.EncodeToString(hashOfMsgToSign), + SchnorrSignatureHex: hex.EncodeToString(signature.Serialize()), + }) + + return nil +} + +func hashFromFile(inputFilePath string) ([]byte, error) { + h := sha256.New() + + f, err := os.Open(inputFilePath) + if err != nil { + return nil, fmt.Errorf("failed to open the file %s: %w", inputFilePath, err) + } + defer f.Close() + + if _, err := io.Copy(h, f); err != nil { + return nil, err + } + + return h.Sum(nil), nil +} + +func singMsg( + eotsManager *eotsmanager.LocalEOTSManager, + keyName, fpPkStr, passphrase string, + hashOfMsgToSign []byte, +) (*schnorr.Signature, *bbntypes.BIP340PubKey, error) { + if len(fpPkStr) > 0 { + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return nil, nil, fmt.Errorf("invalid finality-provider public key %s: %w", fpPkStr, err) + } + signature, err := eotsManager.SignSchnorrSig(*fpPk, hashOfMsgToSign, passphrase) + if err != nil { + return nil, nil, fmt.Errorf("unable to sign msg with pk %s: %w", fpPkStr, err) + } + return signature, fpPk, nil + } + + return eotsManager.SignSchnorrSigFromKeyname(keyName, passphrase, hashOfMsgToSign) +} + +func printRespJSON(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("%s\n", jsonBytes) +} diff --git a/eotsmanager/cmd/eotsd/daemon/sign_test.go b/eotsmanager/cmd/eotsd/daemon/sign_test.go new file mode 100644 index 00000000..f0632c7f --- /dev/null +++ b/eotsmanager/cmd/eotsd/daemon/sign_test.go @@ -0,0 +1,155 @@ +package daemon_test + +import ( + "bytes" + "encoding/json" + "fmt" + "math/rand" + "os" + "path/filepath" + "strings" + "testing" + + sdkmath "cosmossdk.io/math" + dcli "github.com/babylonchain/finality-provider/eotsmanager/cmd/eotsd/daemon" + "github.com/babylonchain/finality-provider/testutil" + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + stktypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +type FpInfo struct { + Description stktypes.Description `json:"description"` + BtcPk string `json:"btc_pk"` + Commision sdkmath.LegacyDec `json:"commission"` +} + +func FuzzSignAndVerifySchnorrSig(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + tempDir := t.TempDir() + homeDir := filepath.Join(tempDir, "eots-home") + app := testApp() + + // init config in home folder + hFlag := fmt.Sprintf("--home=%s", homeDir) + err := app.Run([]string{"eotsd", "init", hFlag}) + require.NoError(t, err) + + keyName := testutil.GenRandomHexStr(r, 10) + keyNameFlag := fmt.Sprintf("--key-name=%s", keyName) + + outputKeysAdd := appRunWithOutput(r, t, app, []string{"eotsd", "keys", "add", hFlag, keyNameFlag}) + keyOutJson := searchInTxt(outputKeysAdd, "for recovery):") + + var keyOut dcli.KeyOutput + err = json.Unmarshal([]byte(keyOutJson), &keyOut) + require.NoError(t, err) + + fpInfoPath := filepath.Join(tempDir, "fpInfo.json") + writeFpInfoToFile(r, t, fpInfoPath, keyOut.PubKeyHex) + + btcPkFlag := fmt.Sprintf("--btc-pk=%s", keyOut.PubKeyHex) + dataSignedBtcPk := appRunSignSchnorr(r, t, app, []string{fpInfoPath, hFlag, btcPkFlag}) + err = app.Run([]string{"eotsd", "verify-schnorr-sig", fpInfoPath, btcPkFlag, fmt.Sprintf("--signature=%s", dataSignedBtcPk.SchnorrSignatureHex)}) + require.NoError(t, err) + + dataSignedKeyName := appRunSignSchnorr(r, t, app, []string{fpInfoPath, hFlag, keyNameFlag}) + err = app.Run([]string{"eotsd", "verify-schnorr-sig", fpInfoPath, btcPkFlag, fmt.Sprintf("--signature=%s", dataSignedKeyName.SchnorrSignatureHex)}) + require.NoError(t, err) + + // check if both generated signatures match + require.Equal(t, dataSignedBtcPk.PubKeyHex, dataSignedKeyName.PubKeyHex) + require.Equal(t, dataSignedBtcPk.SchnorrSignatureHex, dataSignedKeyName.SchnorrSignatureHex) + require.Equal(t, dataSignedBtcPk.SignedDataHashHex, dataSignedKeyName.SignedDataHashHex) + + // sign with both keys and btc-pk, should give btc-pk preference + dataSignedBoth := appRunSignSchnorr(r, t, app, []string{fpInfoPath, hFlag, btcPkFlag, keyNameFlag}) + require.Equal(t, dataSignedBoth, dataSignedKeyName) + + // the keyname can even be from a invalid keyname, since it gives btc-pk preference + badKeyname := "badKeyName" + dataSignedBothBadKeyName := appRunSignSchnorr(r, t, app, []string{fpInfoPath, hFlag, btcPkFlag, fmt.Sprintf("--key-name=%s", badKeyname)}) + require.Equal(t, badKeyname, dataSignedBothBadKeyName.KeyName) + require.Equal(t, dataSignedBtcPk.PubKeyHex, dataSignedBothBadKeyName.PubKeyHex) + require.Equal(t, dataSignedBtcPk.SchnorrSignatureHex, dataSignedBothBadKeyName.SchnorrSignatureHex) + require.Equal(t, dataSignedBtcPk.SignedDataHashHex, dataSignedBothBadKeyName.SignedDataHashHex) + }) +} + +func appRunSignSchnorr(r *rand.Rand, t *testing.T, app *cli.App, arguments []string) dcli.DataSigned { + args := []string{"eotsd", "sign-schnorr"} + args = append(args, arguments...) + outputSign := appRunWithOutput(r, t, app, args) + signatureStr := searchInTxt(outputSign, "") + + var dataSigned dcli.DataSigned + err := json.Unmarshal([]byte(signatureStr), &dataSigned) + require.NoError(t, err) + + return dataSigned +} + +func appRunWithOutput(r *rand.Rand, t *testing.T, app *cli.App, arguments []string) (output string) { + outPut := filepath.Join(t.TempDir(), fmt.Sprintf("%s-out.txt", testutil.GenRandomHexStr(r, 10))) + outPutFile, err := os.Create(outPut) + require.NoError(t, err) + defer outPutFile.Close() + + // set file to stdout to read. + oldStd := os.Stdout + os.Stdout = outPutFile + + err = app.Run(arguments) + require.NoError(t, err) + + // set to old stdout + os.Stdout = oldStd + return readFromFile(t, outPutFile) +} + +func searchInTxt(text, search string) string { + idxOfRecovery := strings.Index(text, search) + jsonKeyOutputOut := text[idxOfRecovery+len(search):] + return strings.ReplaceAll(jsonKeyOutputOut, "\n", "") +} + +func readFromFile(t *testing.T, f *os.File) string { + _, err := f.Seek(0, 0) + require.NoError(t, err) + + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(f) + require.NoError(t, err) + return buf.String() +} + +func writeFpInfoToFile(r *rand.Rand, t *testing.T, fpInfoPath, btcPk string) { + desc := testutil.RandomDescription(r) + fpInfo := FpInfo{ + BtcPk: btcPk, + Commision: sdkmath.LegacyMustNewDecFromStr("0.5"), + Description: *desc, + } + + bzFpInfo, err := json.Marshal(fpInfo) + require.NoError(t, err) + + fpInfoFile, err := os.Create(fpInfoPath) + require.NoError(t, err) + + _, err = fpInfoFile.Write(bzFpInfo) + require.NoError(t, err) + fpInfoFile.Close() +} + +func testApp() *cli.App { + app := cli.NewApp() + app.Name = "eotsd" + app.Commands = append(app.Commands, dcli.StartCommand, dcli.InitCommand, dcli.SignSchnorrSig, dcli.VerifySchnorrSig) + app.Commands = append(app.Commands, dcli.KeysCommands...) + return app +} diff --git a/eotsmanager/cmd/eotsd/start.go b/eotsmanager/cmd/eotsd/daemon/start.go similarity index 79% rename from eotsmanager/cmd/eotsd/start.go rename to eotsmanager/cmd/eotsd/daemon/start.go index b8abf061..8350d16b 100644 --- a/eotsmanager/cmd/eotsd/start.go +++ b/eotsmanager/cmd/eotsd/daemon/start.go @@ -1,4 +1,4 @@ -package main +package daemon import ( "fmt" @@ -15,7 +15,7 @@ import ( "github.com/babylonchain/finality-provider/util" ) -var startCommand = cli.Command{ +var StartCommand = cli.Command{ Name: "start", Usage: "Start the Extractable One Time Signature Daemon.", Description: "Start the Extractable One Time Signature Daemon.", @@ -34,11 +34,10 @@ var startCommand = cli.Command{ } func startFn(ctx *cli.Context) error { - homePath, err := filepath.Abs(ctx.String(homeFlag)) + homePath, err := getHomeFlag(ctx) if err != nil { - return err + return fmt.Errorf("failed to load home flag: %w", err) } - homePath = util.CleanAndExpandPath(homePath) cfg, err := config.LoadConfig(homePath) if err != nil { @@ -59,7 +58,12 @@ func startFn(ctx *cli.Context) error { return fmt.Errorf("failed to load the logger") } - eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, cfg, logger) + dbBackend, err := cfg.DatabaseConfig.GetDbBackend() + if err != nil { + return fmt.Errorf("failed to create db backend: %w", err) + } + + eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, cfg.KeyringBackend, dbBackend, logger) if err != nil { return fmt.Errorf("failed to create EOTS manager: %w", err) } @@ -70,7 +74,15 @@ func startFn(ctx *cli.Context) error { return err } - eotsServer := eotsservice.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + eotsServer := eotsservice.NewEOTSManagerServer(cfg, logger, eotsManager, dbBackend, shutdownInterceptor) return eotsServer.RunUntilShutdown() } + +func getHomeFlag(ctx *cli.Context) (string, error) { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return "", err + } + return util.CleanAndExpandPath(homePath), nil +} diff --git a/eotsmanager/cmd/eotsd/flags.go b/eotsmanager/cmd/eotsd/flags.go deleted file mode 100644 index 5f0b2033..00000000 --- a/eotsmanager/cmd/eotsd/flags.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -const ( - homeFlag = "home" - forceFlag = "force" - rpcListenerFlag = "rpc-listener" -) diff --git a/eotsmanager/cmd/eotsd/main.go b/eotsmanager/cmd/eotsd/main.go index e9380374..1b63d197 100644 --- a/eotsmanager/cmd/eotsd/main.go +++ b/eotsmanager/cmd/eotsd/main.go @@ -2,8 +2,11 @@ package main import ( "fmt" - "github.com/urfave/cli" "os" + + "github.com/urfave/cli" + + dcli "github.com/babylonchain/finality-provider/eotsmanager/cmd/eotsd/daemon" ) func fatal(err error) { @@ -15,7 +18,8 @@ func main() { app := cli.NewApp() app.Name = "eotsd" app.Usage = "Extractable One Time Signature Daemon (eotsd)." - app.Commands = append(app.Commands, startCommand, initCommand) + app.Commands = append(app.Commands, dcli.StartCommand, dcli.InitCommand, dcli.SignSchnorrSig, dcli.VerifySchnorrSig) + app.Commands = append(app.Commands, dcli.KeysCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index ca7161b8..0f664925 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/jessevdk/go-flags" - "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/util" ) @@ -19,7 +19,6 @@ const ( defaultDataDirname = "data" defaultLogDirname = "logs" defaultLogFilename = "eotsd.log" - defaultDBPath = "bbolt-eots.db" defaultConfigFileName = "eotsd.conf" DefaultRPCPort = 12582 defaultKeyringBackend = keyring.BackendTest @@ -36,12 +35,12 @@ var ( ) type Config struct { - LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` - KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` + LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` + KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` + Metrics *metrics.Config `group:"metrics" namespace:"metrics"` - DatabaseConfig *config.DatabaseConfig - - RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` + DatabaseConfig *DBConfig `group:"dbconfig" namespace:"dbconfig"` } // LoadConfig initializes and parses the config using a config file and command @@ -90,6 +89,14 @@ func (cfg *Config) Validate() error { return fmt.Errorf("the keyring backend should not be empty") } + if cfg.Metrics == nil { + return fmt.Errorf("empty metrics config") + } + + if err := cfg.Metrics.Validate(); err != nil { + return fmt.Errorf("invalid metrics config") + } + return nil } @@ -109,17 +116,17 @@ func DataDir(homePath string) string { return filepath.Join(homePath, defaultDataDirname) } -func DBPath(homePath string) string { - return filepath.Join(DataDir(homePath), defaultDBPath) +func DefaultConfig() *Config { + return DefaultConfigWithHomePath(DefaultEOTSDir) } -func DefaultConfig() Config { - dbCfg := config.DefaultDatabaseConfig() - cfg := Config{ +func DefaultConfigWithHomePath(homePath string) *Config { + cfg := &Config{ LogLevel: defaultLogLevel, KeyringBackend: defaultKeyringBackend, - DatabaseConfig: &dbCfg, + DatabaseConfig: DefaultDBConfigWithHomePath(homePath), RpcListener: defaultRpcListener, + Metrics: metrics.DefaultEotsConfig(), } if err := cfg.Validate(); err != nil { panic(err) diff --git a/eotsmanager/config/db.go b/eotsmanager/config/db.go new file mode 100644 index 00000000..08e7f965 --- /dev/null +++ b/eotsmanager/config/db.go @@ -0,0 +1,71 @@ +package config + +import ( + "time" + + "github.com/lightningnetwork/lnd/kvdb" +) + +const ( + defaultDbName = "eots.db" +) + +type DBConfig struct { + // DBPath is the directory path in which the database file should be + // stored. + DBPath string `long:"dbpath" description:"The directory path in which the database file should be stored."` + + // DBFileName is the name of the database file. + DBFileName string `long:"dbfilename" description:"The name of the database file."` + + // NoFreelistSync, if true, prevents the database from syncing its + // freelist to disk, resulting in improved performance at the expense of + // increased startup time. + NoFreelistSync bool `long:"nofreelistsync" description:"Prevents the database from syncing its freelist to disk, resulting in improved performance at the expense of increased startup time."` + + // AutoCompact specifies if a Bolt based database backend should be + // automatically compacted on startup (if the minimum age of the + // database file is reached). This will require additional disk space + // for the compacted copy of the database but will result in an overall + // lower database size after the compaction. + AutoCompact bool `long:"autocompact" description:"Specifies if a Bolt based database backend should be automatically compacted on startup (if the minimum age of the database file is reached). This will require additional disk space for the compacted copy of the database but will result in an overall lower database size after the compaction."` + + // AutoCompactMinAge specifies the minimum time that must have passed + // since a bolt database file was last compacted for the compaction to + // be considered again. + AutoCompactMinAge time.Duration `long:"autocompactminage" description:"Specifies the minimum time that must have passed since a bolt database file was last compacted for the compaction to be considered again."` + + // DBTimeout specifies the timeout value to use when opening the wallet + // database. + DBTimeout time.Duration `long:"dbtimeout" description:"Specifies the timeout value to use when opening the wallet database."` +} + +func DefaultDBConfig() *DBConfig { + return DefaultDBConfigWithHomePath(DefaultEOTSDir) +} + +func DefaultDBConfigWithHomePath(homePath string) *DBConfig { + return &DBConfig{ + DBPath: DataDir(homePath), + DBFileName: defaultDbName, + NoFreelistSync: true, + AutoCompact: false, + AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge, + DBTimeout: kvdb.DefaultDBTimeout, + } +} + +func (db *DBConfig) DBConfigToBoltBackendConfig() *kvdb.BoltBackendConfig { + return &kvdb.BoltBackendConfig{ + DBPath: db.DBPath, + DBFileName: db.DBFileName, + NoFreelistSync: db.NoFreelistSync, + AutoCompact: db.AutoCompact, + AutoCompactMinAge: db.AutoCompactMinAge, + DBTimeout: db.DBTimeout, + } +} + +func (db *DBConfig) GetDbBackend() (kvdb.Backend, error) { + return kvdb.GetBoltBackend(db.DBConfigToBoltBackendConfig()) +} diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index 2e8e1619..57db75ce 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -13,13 +13,10 @@ type EOTSManager interface { // It fails if there is an existing key Info with the same name or public key. CreateKey(name, passphrase, hdPath string) ([]byte, error) - // CreateRandomnessPairList generates a list of Schnorr randomness pairs from - // startHeight to startHeight+(num-1) where num means the number of public randomness - // It fails if the finality provider does not exist or a randomness pair has been created before - // or passPhrase is incorrect - // NOTE: the randomness is deterministically generated based on the EOTS key, chainID and - // block height - CreateRandomnessPairList(uid []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) + // CreateMasterRandPair generates a pair of master secret/public randomness + // It fails if the finality provider does not exist or passPhrase is incorrect + // NOTE: the master randomness pair is deterministically generated based on the EOTS key and chainID + CreateMasterRandPair(uid []byte, chainID []byte, passphrase string) (string, error) // KeyRecord returns the finality provider record // It fails if the finality provider does not exist or passPhrase is incorrect diff --git a/eotsmanager/eotsstore.go b/eotsmanager/eotsstore.go deleted file mode 100644 index 40cf8401..00000000 --- a/eotsmanager/eotsstore.go +++ /dev/null @@ -1,70 +0,0 @@ -package eotsmanager - -import ( - "fmt" - - "github.com/babylonchain/finality-provider/eotsmanager/types" - "github.com/babylonchain/finality-provider/store" -) - -const ( - finalityProviderKeyNamePrefix = "fp-key" -) - -type EOTSStore struct { - s store.Store -} - -func NewEOTSStore(dbPath string, dbName string, dbBackend string) (*EOTSStore, error) { - s, err := openStore(dbPath, dbName, dbBackend) - if err != nil { - return nil, err - } - - return &EOTSStore{s: s}, nil -} - -func (es *EOTSStore) Close() error { - if err := es.s.Close(); err != nil { - return err - } - - return nil -} - -func (es *EOTSStore) saveFinalityProviderKey(pk []byte, keyName string) error { - k := getFinalityProviderKeyNameKey(pk) - - exists, err := es.s.Exists(k) - if err != nil { - return nil - } - if exists { - return types.ErrFinalityProviderAlreadyExisted - } - - return es.s.Put(k, []byte(keyName)) -} - -func (es *EOTSStore) getFinalityProviderKeyName(pk []byte) (string, error) { - k := getFinalityProviderKeyNameKey(pk) - v, err := es.s.Get(k) - if err != nil { - return "", err - } - - return string(v), nil -} - -func getFinalityProviderKeyNameKey(pk []byte) []byte { - return append([]byte(finalityProviderKeyNamePrefix), pk...) -} - -func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { - switch dbBackend { - case "bbolt": - return store.NewBboltStore(dbPath, dbName) - default: - return nil, fmt.Errorf("unsupported database type") - } -} diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index 4d07a980..4362c690 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -1,10 +1,12 @@ package eotsmanager import ( + "encoding/hex" "fmt" - "github.com/babylonchain/finality-provider/util" "strings" + "github.com/babylonchain/finality-provider/metrics" + "github.com/babylonchain/babylon/crypto/eots" bbntypes "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/btcec/v2" @@ -12,63 +14,59 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" + "github.com/lightningnetwork/lnd/kvdb" "go.uber.org/zap" "github.com/babylonchain/finality-provider/codec" - "github.com/babylonchain/finality-provider/eotsmanager/config" - "github.com/babylonchain/finality-provider/eotsmanager/randgenerator" + "github.com/babylonchain/finality-provider/eotsmanager/store" eotstypes "github.com/babylonchain/finality-provider/eotsmanager/types" + fpkeyring "github.com/babylonchain/finality-provider/keyring" ) const ( secp256k1Type = "secp256k1" - mnemonicEntropySize = 256 + MnemonicEntropySize = 256 ) var _ EOTSManager = &LocalEOTSManager{} type LocalEOTSManager struct { kr keyring.Keyring - es *EOTSStore + es *store.EOTSStore logger *zap.Logger // input is to send passphrase to kr - input *strings.Reader + input *strings.Reader + metrics *metrics.EotsMetrics } -func NewLocalEOTSManager(homeDir string, eotsCfg *config.Config, logger *zap.Logger) (*LocalEOTSManager, error) { +func NewLocalEOTSManager(homeDir, keyringBackend string, dbbackend kvdb.Backend, logger *zap.Logger) (*LocalEOTSManager, error) { inputReader := strings.NewReader("") - store, err := initEotsStore(homeDir, eotsCfg) + es, err := store.NewEOTSStore(dbbackend) if err != nil { return nil, fmt.Errorf("failed to initialize store: %w", err) } - kr, err := initKeyring(homeDir, eotsCfg, inputReader) + kr, err := initKeyring(homeDir, keyringBackend, inputReader) if err != nil { return nil, fmt.Errorf("failed to initialize keyring: %w", err) } + eotsMetrics := metrics.NewEotsMetrics() + return &LocalEOTSManager{ - kr: kr, - es: store, - logger: logger, - input: inputReader, + kr: kr, + es: es, + logger: logger, + input: inputReader, + metrics: eotsMetrics, }, nil } -func initEotsStore(homeDir string, eotsCfg *config.Config) (*EOTSStore, error) { - // Create the directory that will store the data - if err := util.MakeDirectory(config.DataDir(homeDir)); err != nil { - return nil, err - } - - return NewEOTSStore(config.DBPath(homeDir), eotsCfg.DatabaseConfig.Name, eotsCfg.DatabaseConfig.Backend) -} - -func initKeyring(homeDir string, eotsCfg *config.Config, inputReader *strings.Reader) (keyring.Keyring, error) { +func initKeyring(homeDir, keyringBackend string, inputReader *strings.Reader) (keyring.Keyring, error) { return keyring.New( "eots-manager", - eotsCfg.KeyringBackend, + keyringBackend, homeDir, inputReader, codec.MakeCodec(), @@ -76,23 +74,41 @@ func initKeyring(homeDir string, eotsCfg *config.Config, inputReader *strings.Re } func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, error) { - if lm.keyExists(name) { - return nil, eotstypes.ErrFinalityProviderAlreadyExisted + mnemonic, err := NewMnemonic() + if err != nil { + return nil, err } - keyringAlgos, _ := lm.kr.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) + eotsPk, err := lm.CreateKeyWithMnemonic(name, passphrase, hdPath, mnemonic) if err != nil { return nil, err } + return eotsPk.MustMarshal(), nil +} + +func NewMnemonic() (string, error) { // read entropy seed straight from tmcrypto.Rand and convert to mnemonic - entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + entropySeed, err := bip39.NewEntropy(MnemonicEntropySize) if err != nil { - return nil, err + return "", err } mnemonic, err := bip39.NewMnemonic(entropySeed) + if err != nil { + return "", err + } + + return mnemonic, nil +} + +func (lm *LocalEOTSManager) CreateKeyWithMnemonic(name, passphrase, hdPath, mnemonic string) (*bbntypes.BIP340PubKey, error) { + if lm.keyExists(name) { + return nil, eotstypes.ErrFinalityProviderAlreadyExisted + } + + keyringAlgos, _ := lm.kr.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { return nil, err } @@ -106,24 +122,12 @@ func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, return nil, err } - pubKey, err := record.GetPubKey() + eotsPk, err := loadBIP340PubKeyFromKeyringRecord(record) if err != nil { return nil, err } - var eotsPk *bbntypes.BIP340PubKey - switch v := pubKey.(type) { - case *secp256k1.PubKey: - pk, err := btcec.ParsePubKey(v.Key) - if err != nil { - return nil, err - } - eotsPk = bbntypes.NewBIP340PubKeyFromBTCPK(pk) - default: - return nil, fmt.Errorf("unsupported key type in keyring") - } - - if err := lm.es.saveFinalityProviderKey(eotsPk.MustMarshal(), name); err != nil { + if err := lm.es.AddEOTSKeyName(eotsPk.MustToBTCPK(), name); err != nil { return nil, err } @@ -132,34 +136,55 @@ func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, zap.String("key name", name), zap.String("pk", eotsPk.MarshalHex()), ) + lm.metrics.IncrementEotsCreatedKeysCounter() - return eotsPk.MustMarshal(), nil + return eotsPk, nil } -// TODO the current implementation is a PoC, which does not contain any anti-slasher mechanism -// -// a simple anti-slasher mechanism could be that the manager remembers the tuple (fpPk, chainID, height) or -// the hash of each generated randomness and return error if the same randomness is requested tweice -func (lm *LocalEOTSManager) CreateRandomnessPairList(fpPk []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { - prList := make([]*btcec.FieldVal, 0, num) +func loadBIP340PubKeyFromKeyringRecord(record *keyring.Record) (*bbntypes.BIP340PubKey, error) { + pubKey, err := record.GetPubKey() + if err != nil { + return nil, err + } - for i := uint32(0); i < num; i++ { - height := startHeight + uint64(i) - _, pubRand, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) + var eotsPk *bbntypes.BIP340PubKey + switch v := pubKey.(type) { + case *secp256k1.PubKey: + pk, err := btcec.ParsePubKey(v.Key) if err != nil { return nil, err } + eotsPk = bbntypes.NewBIP340PubKeyFromBTCPK(pk) + return eotsPk, nil + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } +} - prList = append(prList, pubRand) +// CreateMasterRandPair creates a pair of master secret/public randomness deterministically +// from the finality provider's secret key and chain ID +func (lm *LocalEOTSManager) CreateMasterRandPair(fpPk []byte, chainID []byte, passphrase string) (string, error) { + _, mpr, err := lm.getMasterRandPair(fpPk, chainID, passphrase) + if err != nil { + return "", err } - return prList, nil + return mpr.MarshalBase58(), nil } func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { - privRand, _, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) + // get master secret randomness + // TODO: instead of calculating master secret randomness everytime, is it possible + // to manage it in the keyring? + msr, _, err := lm.getMasterRandPair(fpPk, chainID, passphrase) if err != nil { - return nil, fmt.Errorf("failed to get private randomness: %w", err) + return nil, fmt.Errorf("failed to get master secret randomness: %w", err) + } + + // derive secret randomness + sr, _, err := msr.DeriveRandPair(uint32(height)) // TODO: generalise to uint64 + if err != nil { + return nil, fmt.Errorf("failed to get secret randomness: %w", err) } privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) @@ -167,7 +192,11 @@ func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, he return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } - return eots.Sign(privKey, privRand, msg) + // Update metrics + lm.metrics.IncrementEotsFpTotalEotsSignCounter(hex.EncodeToString(fpPk)) + lm.metrics.SetEotsFpLastEotsSignHeight(hex.EncodeToString(fpPk), float64(height)) + + return eots.Sign(privKey, sr, msg) } func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { @@ -176,26 +205,56 @@ func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase s return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } + return lm.signSchnorrSigFromPrivKey(privKey, fpPk, msg) +} + +// signSchnorrSigFromPrivKey signs a Schnorr signature using the private key and updates metrics by the fpPk +func (lm *LocalEOTSManager) signSchnorrSigFromPrivKey(privKey *btcec.PrivateKey, fpPk []byte, msg []byte) (*schnorr.Signature, error) { + // Update metrics + lm.metrics.IncrementEotsFpTotalSchnorrSignCounter(hex.EncodeToString(fpPk)) return schnorr.Sign(privKey, msg) } +func (lm *LocalEOTSManager) SignSchnorrSigFromKeyname(keyName, passphrase string, msg []byte) (*schnorr.Signature, *bbntypes.BIP340PubKey, error) { + lm.input.Reset(passphrase) + k, err := lm.kr.Key(keyName) + if err != nil { + return nil, nil, fmt.Errorf("failed to load keyring record for key %s: %w", keyName, err) + } + + eotsPk, err := loadBIP340PubKeyFromKeyringRecord(k) + if err != nil { + return nil, nil, err + } + + privKey, err := eotsPrivKeyFromRecord(k) + if err != nil { + return nil, nil, err + } + + signature, err := lm.signSchnorrSigFromPrivKey(privKey, *eotsPk, msg) + if err != nil { + return nil, nil, fmt.Errorf("failed to schnorr sign: %w", err) + } + return signature, eotsPk, nil +} + func (lm *LocalEOTSManager) Close() error { - return lm.es.Close() + return nil } -// getRandomnessPair returns a randomness pair generated based on the given finality provider key, chainID and height -func (lm *LocalEOTSManager) getRandomnessPair(fpPk []byte, chainID []byte, height uint64, passphrase string) (*eots.PrivateRand, *eots.PublicRand, error) { +// getMasterRandPair returns a randomness pair generated based on the given finality provider key, chainID and height +func (lm *LocalEOTSManager) getMasterRandPair(fpPk []byte, chainID []byte, passphrase string) (*eots.MasterSecretRand, *eots.MasterPublicRand, error) { record, err := lm.KeyRecord(fpPk, passphrase) if err != nil { return nil, nil, err } - privRand, pubRand := randgenerator.GenerateRandomness(record.PrivKey.Serialize(), chainID, height) - return privRand, pubRand, nil + return fpkeyring.GenerateMasterRandPair(record.PrivKey.Serialize(), chainID) } // TODO: we ignore passPhrase in local implementation for now func (lm *LocalEOTSManager) KeyRecord(fpPk []byte, passphrase string) (*eotstypes.KeyRecord, error) { - name, err := lm.es.getFinalityProviderKeyName(fpPk) + name, err := lm.es.GetEOTSKeyName(fpPk) if err != nil { return nil, err } @@ -211,7 +270,7 @@ func (lm *LocalEOTSManager) KeyRecord(fpPk []byte, passphrase string) (*eotstype } func (lm *LocalEOTSManager) getEOTSPrivKey(fpPk []byte, passphrase string) (*btcec.PrivateKey, error) { - keyName, err := lm.es.getFinalityProviderKeyName(fpPk) + keyName, err := lm.es.GetEOTSKeyName(fpPk) if err != nil { return nil, err } @@ -222,6 +281,10 @@ func (lm *LocalEOTSManager) getEOTSPrivKey(fpPk []byte, passphrase string) (*btc return nil, err } + return eotsPrivKeyFromRecord(k) +} + +func eotsPrivKeyFromRecord(k *keyring.Record) (*btcec.PrivateKey, error) { privKeyCached := k.GetLocal().PrivKey.GetCachedValue() var privKey *btcec.PrivateKey diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go index 29f5d43f..5696fe92 100644 --- a/eotsmanager/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -1,17 +1,20 @@ package eotsmanager_test import ( - "go.uber.org/zap" "math/rand" "os" "path/filepath" "testing" + "github.com/babylonchain/babylon/crypto/eots" "github.com/babylonchain/babylon/testutil/datagen" + bbn "github.com/babylonchain/babylon/types" "github.com/babylonchain/finality-provider/eotsmanager" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" "github.com/babylonchain/finality-provider/eotsmanager/types" "github.com/babylonchain/finality-provider/testutil" "github.com/stretchr/testify/require" + "go.uber.org/zap" ) var ( @@ -27,13 +30,16 @@ func FuzzCreateKey(f *testing.F) { fpName := testutil.GenRandomHexStr(r, 4) homeDir := filepath.Join(t.TempDir(), "eots-home") - eotsCfg := testutil.GenEOTSConfig(r, t) + eotsCfg := eotscfg.DefaultConfigWithHomePath(homeDir) + dbBackend, err := eotsCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) defer func() { + dbBackend.Close() err := os.RemoveAll(homeDir) require.NoError(t, err) }() - lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg.KeyringBackend, dbBackend, zap.NewNop()) require.NoError(t, err) fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) @@ -52,36 +58,53 @@ func FuzzCreateKey(f *testing.F) { }) } -func FuzzCreateRandomnessPairList(f *testing.F) { +func FuzzCreateMasterRandPair(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) fpName := testutil.GenRandomHexStr(r, 4) homeDir := filepath.Join(t.TempDir(), "eots-home") - eotsCfg := testutil.GenEOTSConfig(r, t) + eotsCfg := eotscfg.DefaultConfigWithHomePath(homeDir) + dbBackend, err := eotsCfg.DatabaseConfig.GetDbBackend() defer func() { + dbBackend.Close() err := os.RemoveAll(homeDir) require.NoError(t, err) }() - - lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) + require.NoError(t, err) + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg.KeyringBackend, dbBackend, zap.NewNop()) require.NoError(t, err) fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) require.NoError(t, err) + fpBTCPK, err := bbn.NewBIP340PubKey(fpPk) + require.NoError(t, err) chainID := datagen.GenRandomByteArray(r, 10) + + mprStr, err := lm.CreateMasterRandPair(fpPk, chainID, passphrase) + require.NoError(t, err) + mpr, err := eots.NewMasterPublicRandFromBase58(mprStr) + require.NoError(t, err) + startHeight := datagen.RandomInt(r, 100) num := r.Intn(10) + 1 - pubRandList, err := lm.CreateRandomnessPairList(fpPk, chainID, startHeight, uint32(num), passphrase) - require.NoError(t, err) - require.Len(t, pubRandList, num) for i := 0; i < num; i++ { - sig, err := lm.SignEOTS(fpPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i), passphrase) + height := startHeight + uint64(i) + msg := datagen.GenRandomByteArray(r, 32) + + // sign EOTS signature at each height + sig, err := lm.SignEOTS(fpPk, chainID, msg, height, passphrase) require.NoError(t, err) require.NotNil(t, sig) + + // verify using the master public randomness and height + pr, err := mpr.DerivePubRand(uint32(height)) + require.NoError(t, err) + err = eots.Verify(fpBTCPK.MustToBTCPK(), pr, msg, sig) + require.NoError(t, err) } }) } diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index 0be2f1d2..e1ea111d 100644 --- a/eotsmanager/proto/eotsmanager.pb.go +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: eotsmanager.proto @@ -210,7 +210,7 @@ func (x *CreateKeyResponse) GetPk() []byte { return nil } -type CreateRandomnessPairListRequest struct { +type CreateMasterRandPairRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -219,16 +219,12 @@ type CreateRandomnessPairListRequest struct { Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` // chain_id is the identifier of the consumer chain that the randomness is committed to ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - // start_height is the start height of the randomness pair list - StartHeight uint64 `protobuf:"varint,3,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"` - // num is the number of randomness pair list - Num uint32 `protobuf:"varint,4,opt,name=num,proto3" json:"num,omitempty"` // passphrase is used to decrypt the EOTS key - Passphrase string `protobuf:"bytes,5,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + Passphrase string `protobuf:"bytes,3,opt,name=passphrase,proto3" json:"passphrase,omitempty"` } -func (x *CreateRandomnessPairListRequest) Reset() { - *x = CreateRandomnessPairListRequest{} +func (x *CreateMasterRandPairRequest) Reset() { + *x = CreateMasterRandPairRequest{} if protoimpl.UnsafeEnabled { mi := &file_eotsmanager_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -236,13 +232,13 @@ func (x *CreateRandomnessPairListRequest) Reset() { } } -func (x *CreateRandomnessPairListRequest) String() string { +func (x *CreateMasterRandPairRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CreateRandomnessPairListRequest) ProtoMessage() {} +func (*CreateMasterRandPairRequest) ProtoMessage() {} -func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { +func (x *CreateMasterRandPairRequest) ProtoReflect() protoreflect.Message { mi := &file_eotsmanager_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -254,57 +250,43 @@ func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CreateRandomnessPairListRequest.ProtoReflect.Descriptor instead. -func (*CreateRandomnessPairListRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use CreateMasterRandPairRequest.ProtoReflect.Descriptor instead. +func (*CreateMasterRandPairRequest) Descriptor() ([]byte, []int) { return file_eotsmanager_proto_rawDescGZIP(), []int{4} } -func (x *CreateRandomnessPairListRequest) GetUid() []byte { +func (x *CreateMasterRandPairRequest) GetUid() []byte { if x != nil { return x.Uid } return nil } -func (x *CreateRandomnessPairListRequest) GetChainId() []byte { +func (x *CreateMasterRandPairRequest) GetChainId() []byte { if x != nil { return x.ChainId } return nil } -func (x *CreateRandomnessPairListRequest) GetStartHeight() uint64 { - if x != nil { - return x.StartHeight - } - return 0 -} - -func (x *CreateRandomnessPairListRequest) GetNum() uint32 { - if x != nil { - return x.Num - } - return 0 -} - -func (x *CreateRandomnessPairListRequest) GetPassphrase() string { +func (x *CreateMasterRandPairRequest) GetPassphrase() string { if x != nil { return x.Passphrase } return "" } -type CreateRandomnessPairListResponse struct { +type CreateMasterRandPairResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // pub_rand_list is a list of Schnorr public randomness - PubRandList [][]byte `protobuf:"bytes,1,rep,name=pub_rand_list,json=pubRandList,proto3" json:"pub_rand_list,omitempty"` + // master_pub_rand is a master public randomness in base58 format + MasterPubRand string `protobuf:"bytes,1,opt,name=master_pub_rand,json=masterPubRand,proto3" json:"master_pub_rand,omitempty"` } -func (x *CreateRandomnessPairListResponse) Reset() { - *x = CreateRandomnessPairListResponse{} +func (x *CreateMasterRandPairResponse) Reset() { + *x = CreateMasterRandPairResponse{} if protoimpl.UnsafeEnabled { mi := &file_eotsmanager_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -312,13 +294,13 @@ func (x *CreateRandomnessPairListResponse) Reset() { } } -func (x *CreateRandomnessPairListResponse) String() string { +func (x *CreateMasterRandPairResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*CreateRandomnessPairListResponse) ProtoMessage() {} +func (*CreateMasterRandPairResponse) ProtoMessage() {} -func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { +func (x *CreateMasterRandPairResponse) ProtoReflect() protoreflect.Message { mi := &file_eotsmanager_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -330,16 +312,16 @@ func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use CreateRandomnessPairListResponse.ProtoReflect.Descriptor instead. -func (*CreateRandomnessPairListResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use CreateMasterRandPairResponse.ProtoReflect.Descriptor instead. +func (*CreateMasterRandPairResponse) Descriptor() ([]byte, []int) { return file_eotsmanager_proto_rawDescGZIP(), []int{5} } -func (x *CreateRandomnessPairListResponse) GetPubRandList() [][]byte { +func (x *CreateMasterRandPairResponse) GetMasterPubRand() string { if x != nil { - return x.PubRandList + return x.MasterPubRand } - return nil + return "" } type KeyRecordRequest struct { @@ -717,82 +699,78 @@ var file_eotsmanager_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0x23, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x70, 0x6b, 0x22, - 0xa3, 0x01, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, - 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, - 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, - 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, - 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, - 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x0b, 0x70, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x44, 0x0a, - 0x10, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, - 0x61, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x11, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x88, 0x01, - 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x75, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x10, - 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, - 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, - 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, - 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x24, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, - 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, - 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x22, 0x5b, - 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x6a, 0x0a, 0x1b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x53, - 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x32, 0xb7, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, - 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, - 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, - 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, - 0x53, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, - 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, - 0x72, 0x53, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, - 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x62, 0x74, 0x63, - 0x2d, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x2f, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x1c, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x52, 0x61, 0x6e, 0x64, 0x50, + 0x61, 0x69, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x50, 0x75, 0x62, 0x52, + 0x61, 0x6e, 0x64, 0x22, 0x44, 0x0a, 0x10, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, + 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x11, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x22, 0x88, 0x01, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, + 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x24, + 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x03, 0x73, 0x69, 0x67, 0x22, 0x5b, 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, + 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, + 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, + 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, + 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x32, 0xab, 0x03, + 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2f, 0x0a, + 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, + 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x17, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, + 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x52, 0x61, + 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x52, 0x61, 0x6e, 0x64, 0x50, + 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x17, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3b, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x12, 0x16, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, + 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x12, 0x1c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, + 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, + 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, + 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x62, 0x74, 0x63, 0x2d, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x65, 0x6f, 0x74, + 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -809,29 +787,29 @@ func file_eotsmanager_proto_rawDescGZIP() []byte { var file_eotsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_eotsmanager_proto_goTypes = []interface{}{ - (*PingRequest)(nil), // 0: proto.PingRequest - (*PingResponse)(nil), // 1: proto.PingResponse - (*CreateKeyRequest)(nil), // 2: proto.CreateKeyRequest - (*CreateKeyResponse)(nil), // 3: proto.CreateKeyResponse - (*CreateRandomnessPairListRequest)(nil), // 4: proto.CreateRandomnessPairListRequest - (*CreateRandomnessPairListResponse)(nil), // 5: proto.CreateRandomnessPairListResponse - (*KeyRecordRequest)(nil), // 6: proto.KeyRecordRequest - (*KeyRecordResponse)(nil), // 7: proto.KeyRecordResponse - (*SignEOTSRequest)(nil), // 8: proto.SignEOTSRequest - (*SignEOTSResponse)(nil), // 9: proto.SignEOTSResponse - (*SignSchnorrSigRequest)(nil), // 10: proto.SignSchnorrSigRequest - (*SignSchnorrSigResponse)(nil), // 11: proto.SignSchnorrSigResponse + (*PingRequest)(nil), // 0: proto.PingRequest + (*PingResponse)(nil), // 1: proto.PingResponse + (*CreateKeyRequest)(nil), // 2: proto.CreateKeyRequest + (*CreateKeyResponse)(nil), // 3: proto.CreateKeyResponse + (*CreateMasterRandPairRequest)(nil), // 4: proto.CreateMasterRandPairRequest + (*CreateMasterRandPairResponse)(nil), // 5: proto.CreateMasterRandPairResponse + (*KeyRecordRequest)(nil), // 6: proto.KeyRecordRequest + (*KeyRecordResponse)(nil), // 7: proto.KeyRecordResponse + (*SignEOTSRequest)(nil), // 8: proto.SignEOTSRequest + (*SignEOTSResponse)(nil), // 9: proto.SignEOTSResponse + (*SignSchnorrSigRequest)(nil), // 10: proto.SignSchnorrSigRequest + (*SignSchnorrSigResponse)(nil), // 11: proto.SignSchnorrSigResponse } var file_eotsmanager_proto_depIdxs = []int32{ 0, // 0: proto.EOTSManager.Ping:input_type -> proto.PingRequest 2, // 1: proto.EOTSManager.CreateKey:input_type -> proto.CreateKeyRequest - 4, // 2: proto.EOTSManager.CreateRandomnessPairList:input_type -> proto.CreateRandomnessPairListRequest + 4, // 2: proto.EOTSManager.CreateMasterRandPair:input_type -> proto.CreateMasterRandPairRequest 6, // 3: proto.EOTSManager.KeyRecord:input_type -> proto.KeyRecordRequest 8, // 4: proto.EOTSManager.SignEOTS:input_type -> proto.SignEOTSRequest 10, // 5: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest 1, // 6: proto.EOTSManager.Ping:output_type -> proto.PingResponse 3, // 7: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse - 5, // 8: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse + 5, // 8: proto.EOTSManager.CreateMasterRandPair:output_type -> proto.CreateMasterRandPairResponse 7, // 9: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse 9, // 10: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse 11, // 11: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse @@ -897,7 +875,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateRandomnessPairListRequest); i { + switch v := v.(*CreateMasterRandPairRequest); i { case 0: return &v.state case 1: @@ -909,7 +887,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateRandomnessPairListResponse); i { + switch v := v.(*CreateMasterRandPairResponse); i { case 0: return &v.state case 1: diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto index 866a9de0..7997dc2a 100644 --- a/eotsmanager/proto/eotsmanager.proto +++ b/eotsmanager/proto/eotsmanager.proto @@ -11,9 +11,9 @@ service EOTSManager { rpc CreateKey (CreateKeyRequest) returns (CreateKeyResponse); - // CreateRandomnessPairList returns a list of Schnorr randomness pairs - rpc CreateRandomnessPairList (CreateRandomnessPairListRequest) - returns (CreateRandomnessPairListResponse); + // CreateMasterRandPair creates a pair of master secret/public randomness + rpc CreateMasterRandPair (CreateMasterRandPairRequest) + returns (CreateMasterRandPairResponse); // KeyRecord returns the key record rpc KeyRecord(KeyRecordRequest) @@ -46,22 +46,18 @@ message CreateKeyResponse { bytes pk = 1; } -message CreateRandomnessPairListRequest { +message CreateMasterRandPairRequest { // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec bytes uid = 1; // chain_id is the identifier of the consumer chain that the randomness is committed to bytes chain_id = 2; - // start_height is the start height of the randomness pair list - uint64 start_height = 3; - // num is the number of randomness pair list - uint32 num = 4; // passphrase is used to decrypt the EOTS key - string passphrase = 5; + string passphrase = 3; } -message CreateRandomnessPairListResponse { - // pub_rand_list is a list of Schnorr public randomness - repeated bytes pub_rand_list = 1; +message CreateMasterRandPairResponse { + // master_pub_rand is a master public randomness in base58 format + string master_pub_rand = 1; } message KeyRecordRequest { diff --git a/eotsmanager/proto/eotsmanager_grpc.pb.go b/eotsmanager/proto/eotsmanager_grpc.pb.go index 0a8814ad..9db90b12 100644 --- a/eotsmanager/proto/eotsmanager_grpc.pb.go +++ b/eotsmanager/proto/eotsmanager_grpc.pb.go @@ -19,12 +19,12 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - EOTSManager_Ping_FullMethodName = "/proto.EOTSManager/Ping" - EOTSManager_CreateKey_FullMethodName = "/proto.EOTSManager/CreateKey" - EOTSManager_CreateRandomnessPairList_FullMethodName = "/proto.EOTSManager/CreateRandomnessPairList" - EOTSManager_KeyRecord_FullMethodName = "/proto.EOTSManager/KeyRecord" - EOTSManager_SignEOTS_FullMethodName = "/proto.EOTSManager/SignEOTS" - EOTSManager_SignSchnorrSig_FullMethodName = "/proto.EOTSManager/SignSchnorrSig" + EOTSManager_Ping_FullMethodName = "/proto.EOTSManager/Ping" + EOTSManager_CreateKey_FullMethodName = "/proto.EOTSManager/CreateKey" + EOTSManager_CreateMasterRandPair_FullMethodName = "/proto.EOTSManager/CreateMasterRandPair" + EOTSManager_KeyRecord_FullMethodName = "/proto.EOTSManager/KeyRecord" + EOTSManager_SignEOTS_FullMethodName = "/proto.EOTSManager/SignEOTS" + EOTSManager_SignSchnorrSig_FullMethodName = "/proto.EOTSManager/SignSchnorrSig" ) // EOTSManagerClient is the client API for EOTSManager service. @@ -34,8 +34,8 @@ type EOTSManagerClient interface { Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) // CreateKey generates and saves an EOTS key CreateKey(ctx context.Context, in *CreateKeyRequest, opts ...grpc.CallOption) (*CreateKeyResponse, error) - // CreateRandomnessPairList returns a list of Schnorr randomness pairs - CreateRandomnessPairList(ctx context.Context, in *CreateRandomnessPairListRequest, opts ...grpc.CallOption) (*CreateRandomnessPairListResponse, error) + // CreateMasterRandPair creates a pair of master secret/public randomness + CreateMasterRandPair(ctx context.Context, in *CreateMasterRandPairRequest, opts ...grpc.CallOption) (*CreateMasterRandPairResponse, error) // KeyRecord returns the key record KeyRecord(ctx context.Context, in *KeyRecordRequest, opts ...grpc.CallOption) (*KeyRecordResponse, error) // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness @@ -70,9 +70,9 @@ func (c *eOTSManagerClient) CreateKey(ctx context.Context, in *CreateKeyRequest, return out, nil } -func (c *eOTSManagerClient) CreateRandomnessPairList(ctx context.Context, in *CreateRandomnessPairListRequest, opts ...grpc.CallOption) (*CreateRandomnessPairListResponse, error) { - out := new(CreateRandomnessPairListResponse) - err := c.cc.Invoke(ctx, EOTSManager_CreateRandomnessPairList_FullMethodName, in, out, opts...) +func (c *eOTSManagerClient) CreateMasterRandPair(ctx context.Context, in *CreateMasterRandPairRequest, opts ...grpc.CallOption) (*CreateMasterRandPairResponse, error) { + out := new(CreateMasterRandPairResponse) + err := c.cc.Invoke(ctx, EOTSManager_CreateMasterRandPair_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -113,8 +113,8 @@ type EOTSManagerServer interface { Ping(context.Context, *PingRequest) (*PingResponse, error) // CreateKey generates and saves an EOTS key CreateKey(context.Context, *CreateKeyRequest) (*CreateKeyResponse, error) - // CreateRandomnessPairList returns a list of Schnorr randomness pairs - CreateRandomnessPairList(context.Context, *CreateRandomnessPairListRequest) (*CreateRandomnessPairListResponse, error) + // CreateMasterRandPair creates a pair of master secret/public randomness + CreateMasterRandPair(context.Context, *CreateMasterRandPairRequest) (*CreateMasterRandPairResponse, error) // KeyRecord returns the key record KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness @@ -134,8 +134,8 @@ func (UnimplementedEOTSManagerServer) Ping(context.Context, *PingRequest) (*Ping func (UnimplementedEOTSManagerServer) CreateKey(context.Context, *CreateKeyRequest) (*CreateKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateKey not implemented") } -func (UnimplementedEOTSManagerServer) CreateRandomnessPairList(context.Context, *CreateRandomnessPairListRequest) (*CreateRandomnessPairListResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateRandomnessPairList not implemented") +func (UnimplementedEOTSManagerServer) CreateMasterRandPair(context.Context, *CreateMasterRandPairRequest) (*CreateMasterRandPairResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateMasterRandPair not implemented") } func (UnimplementedEOTSManagerServer) KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method KeyRecord not implemented") @@ -195,20 +195,20 @@ func _EOTSManager_CreateKey_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } -func _EOTSManager_CreateRandomnessPairList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateRandomnessPairListRequest) +func _EOTSManager_CreateMasterRandPair_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateMasterRandPairRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, in) + return srv.(EOTSManagerServer).CreateMasterRandPair(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: EOTSManager_CreateRandomnessPairList_FullMethodName, + FullMethod: EOTSManager_CreateMasterRandPair_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, req.(*CreateRandomnessPairListRequest)) + return srv.(EOTSManagerServer).CreateMasterRandPair(ctx, req.(*CreateMasterRandPairRequest)) } return interceptor(ctx, in, info, handler) } @@ -283,8 +283,8 @@ var EOTSManager_ServiceDesc = grpc.ServiceDesc{ Handler: _EOTSManager_CreateKey_Handler, }, { - MethodName: "CreateRandomnessPairList", - Handler: _EOTSManager_CreateRandomnessPairList_Handler, + MethodName: "CreateMasterRandPair", + Handler: _EOTSManager_CreateMasterRandPair_Handler, }, { MethodName: "KeyRecord", diff --git a/eotsmanager/randgenerator/randgenerator.go b/eotsmanager/randgenerator/randgenerator.go deleted file mode 100644 index 570031f0..00000000 --- a/eotsmanager/randgenerator/randgenerator.go +++ /dev/null @@ -1,29 +0,0 @@ -package randgenerator - -import ( - "crypto/hmac" - "crypto/sha256" - - "github.com/babylonchain/babylon/crypto/eots" - "github.com/btcsuite/btcd/btcec/v2" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/decred/dcrd/dcrec/secp256k1/v4" -) - -// GenerateRandomness generates a random scalar with the given key and src -// the result is deterministic with each given input -func GenerateRandomness(key []byte, chainID []byte, height uint64) (*eots.PrivateRand, *eots.PublicRand) { - // calculate the randomn hash of the key concatenated with chainID and height - digest := hmac.New(sha256.New, key) - digest.Write(append(sdk.Uint64ToBigEndian(height), chainID...)) - randPre := digest.Sum(nil) - - // convert the hash into private random - var randScalar btcec.ModNScalar - randScalar.SetByteSlice(randPre) - privRand := secp256k1.NewPrivateKey(&randScalar) - var j secp256k1.JacobianPoint - privRand.PubKey().AsJacobian(&j) - - return &privRand.Key, &j.X -} diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go index b8cc4990..13acb351 100644 --- a/eotsmanager/service/rpcserver.go +++ b/eotsmanager/service/rpcserver.go @@ -52,23 +52,16 @@ func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) return &proto.CreateKeyResponse{Pk: pk}, nil } -// CreateRandomnessPairList returns a list of Schnorr randomness pairs -func (r *rpcServer) CreateRandomnessPairList(ctx context.Context, req *proto.CreateRandomnessPairListRequest) ( - *proto.CreateRandomnessPairListResponse, error) { - - pubRandList, err := r.em.CreateRandomnessPairList(req.Uid, req.ChainId, req.StartHeight, req.Num, req.Passphrase) +// CreateMasterRandPair returns a list of Schnorr randomness pairs +func (r *rpcServer) CreateMasterRandPair(ctx context.Context, req *proto.CreateMasterRandPairRequest) (*proto.CreateMasterRandPairResponse, error) { + mpr, err := r.em.CreateMasterRandPair(req.Uid, req.ChainId, req.Passphrase) if err != nil { return nil, err } - pubRandBytesList := make([][]byte, 0, len(pubRandList)) - for _, p := range pubRandList { - pubRandBytesList = append(pubRandBytesList, p.Bytes()[:]) - } - - return &proto.CreateRandomnessPairListResponse{ - PubRandList: pubRandBytesList, + return &proto.CreateMasterRandPairResponse{ + MasterPubRand: mpr, }, nil } diff --git a/eotsmanager/service/server.go b/eotsmanager/service/server.go index f16008c8..d9e2f310 100644 --- a/eotsmanager/service/server.go +++ b/eotsmanager/service/server.go @@ -1,11 +1,15 @@ package service import ( + "context" "fmt" "net" "sync" "sync/atomic" + "github.com/babylonchain/finality-provider/metrics" + + "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/signal" "go.uber.org/zap" "google.golang.org/grpc" @@ -24,17 +28,19 @@ type Server struct { logger *zap.Logger rpcServer *rpcServer + db kvdb.Backend interceptor signal.Interceptor quit chan struct{} } // NewEOTSManagerServer creates a new server with the given config. -func NewEOTSManagerServer(cfg *config.Config, l *zap.Logger, em eotsmanager.EOTSManager, sig signal.Interceptor) *Server { +func NewEOTSManagerServer(cfg *config.Config, l *zap.Logger, em eotsmanager.EOTSManager, db kvdb.Backend, sig signal.Interceptor) *Server { return &Server{ cfg: cfg, logger: l, rpcServer: newRPCServer(em), + db: db, interceptor: sig, quit: make(chan struct{}, 1), } @@ -47,10 +53,25 @@ func (s *Server) RunUntilShutdown() error { return nil } + // Start the metrics server. + promAddr, err := s.cfg.Metrics.Address() + if err != nil { + return fmt.Errorf("failed to get prometheus address: %w", err) + } + metricsServer := metrics.Start(promAddr, s.logger) + defer func() { s.logger.Info("Shutdown complete") }() + defer func() { + s.logger.Info("Closing database...") + s.db.Close() + s.logger.Info("Database closed") + metricsServer.Stop(context.Background()) + s.logger.Info("Metrics server stopped") + }() + listenAddr := s.cfg.RpcListener // we create listeners from the RPCListeners defined // in the config. diff --git a/eotsmanager/store/eotsstore.go b/eotsmanager/store/eotsstore.go new file mode 100644 index 00000000..cc68691b --- /dev/null +++ b/eotsmanager/store/eotsstore.go @@ -0,0 +1,95 @@ +package store + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcwallet/walletdb" + "github.com/lightningnetwork/lnd/kvdb" +) + +var ( + eotsBucketName = []byte("fpKeyNames") +) + +type EOTSStore struct { + db kvdb.Backend +} + +func NewEOTSStore(db kvdb.Backend) (*EOTSStore, error) { + s := &EOTSStore{db} + if err := s.initBuckets(); err != nil { + return nil, err + } + + return s, nil +} + +func (s *EOTSStore) initBuckets() error { + return kvdb.Batch(s.db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(eotsBucketName) + if err != nil { + return err + } + + return nil + }) +} + +func (s *EOTSStore) AddEOTSKeyName( + btcPk *btcec.PublicKey, + keyName string, +) error { + pkBytes := schnorr.SerializePubKey(btcPk) + + return kvdb.Batch(s.db, func(tx kvdb.RwTx) error { + eotsBucket := tx.ReadWriteBucket(eotsBucketName) + if eotsBucket == nil { + return ErrCorruptedEOTSDb + } + + // check btc pk first to avoid duplicates + if eotsBucket.Get(pkBytes) != nil { + return ErrDuplicateEOTSKeyName + } + + return saveEOTSKeyName(eotsBucket, pkBytes, keyName) + }) +} + +func saveEOTSKeyName( + eotsBucket walletdb.ReadWriteBucket, + btcPk []byte, + keyName string, +) error { + if keyName == "" { + return fmt.Errorf("cannot save empty key name") + } + + return eotsBucket.Put(btcPk, []byte(keyName)) +} + +func (s *EOTSStore) GetEOTSKeyName(pk []byte) (string, error) { + var keyName string + err := s.db.View(func(tx kvdb.RTx) error { + eotsBucket := tx.ReadBucket(eotsBucketName) + if eotsBucket == nil { + return ErrCorruptedEOTSDb + } + + keyNameBytes := eotsBucket.Get(pk) + if keyNameBytes == nil { + return ErrEOTSKeyNameNotFound + } + + keyName = string(keyNameBytes) + return nil + }, func() {}) + + if err != nil { + return "", err + } + + return keyName, nil +} diff --git a/eotsmanager/store/eotsstore_test.go b/eotsmanager/store/eotsstore_test.go new file mode 100644 index 00000000..16d3d793 --- /dev/null +++ b/eotsmanager/store/eotsstore_test.go @@ -0,0 +1,65 @@ +package store_test + +import ( + "math/rand" + "os" + "testing" + + "github.com/babylonchain/babylon/testutil/datagen" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager/store" + "github.com/babylonchain/finality-provider/testutil" +) + +// FuzzEOTSStore tests save and show EOTS key names properly +func FuzzEOTSStore(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + homePath := t.TempDir() + cfg := config.DefaultDBConfigWithHomePath(homePath) + + dbBackend, err := cfg.GetDbBackend() + require.NoError(t, err) + + vs, err := store.NewEOTSStore(dbBackend) + require.NoError(t, err) + + defer func() { + dbBackend.Close() + err := os.RemoveAll(homePath) + require.NoError(t, err) + }() + + expectedKeyName := testutil.GenRandomHexStr(r, 10) + _, btcPk, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + + // add key name for the first time + err = vs.AddEOTSKeyName( + btcPk, + expectedKeyName, + ) + require.NoError(t, err) + + // add duplicate key name + err = vs.AddEOTSKeyName( + btcPk, + expectedKeyName, + ) + require.ErrorIs(t, err, store.ErrDuplicateEOTSKeyName) + + keyNameFromDb, err := vs.GetEOTSKeyName(schnorr.SerializePubKey(btcPk)) + require.NoError(t, err) + require.Equal(t, expectedKeyName, keyNameFromDb) + + _, randomBtcPk, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + _, err = vs.GetEOTSKeyName(schnorr.SerializePubKey(randomBtcPk)) + require.ErrorIs(t, err, store.ErrEOTSKeyNameNotFound) + }) +} diff --git a/eotsmanager/store/errors.go b/eotsmanager/store/errors.go new file mode 100644 index 00000000..21b89d71 --- /dev/null +++ b/eotsmanager/store/errors.go @@ -0,0 +1,14 @@ +package store + +import "errors" + +var ( + // ErrCorruptedEOTSDb For some reason, db on disk representation have changed + ErrCorruptedEOTSDb = errors.New("EOTS manager db is corrupted") + + // ErrDuplicateEOTSKeyName The EOTS key name we try to add already exists in db + ErrDuplicateEOTSKeyName = errors.New("EOTS key name already exists") + + // ErrEOTSKeyNameNotFound The EOTS key name we try to fetch is not found in db + ErrEOTSKeyNameNotFound = errors.New("EOTS key name not found") +) diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemon/daemoncmd.go similarity index 86% rename from finality-provider/cmd/fpcli/daemoncmd.go rename to finality-provider/cmd/fpcli/daemon/daemoncmd.go index f058764a..7d662094 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemon/daemoncmd.go @@ -1,9 +1,11 @@ -package main +package daemon import ( "context" "encoding/hex" + "encoding/json" "fmt" + "strconv" "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" @@ -15,10 +17,11 @@ import ( ) var ( - defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" + defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) + defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" ) -var getDaemonInfoCmd = cli.Command{ +var GetDaemonInfoCmd = cli.Command{ Name: "get-info", ShortName: "gi", Usage: "Get information of the running daemon.", @@ -51,7 +54,7 @@ func getInfo(ctx *cli.Context) error { return nil } -var createFpDaemonCmd = cli.Command{ +var CreateFpDaemonCmd = cli.Command{ Name: "create-finality-provider", ShortName: "cfp", Usage: "Create a finality provider object and save it in database.", @@ -106,7 +109,7 @@ var createFpDaemonCmd = cli.Command{ Value: "", }, cli.StringFlag{ - Name: securityContractFlag, + Name: securityContactFlag, Usage: "An optional email for security contact", Value: "", }, @@ -132,20 +135,9 @@ func createFpDaemon(ctx *cli.Context) error { return fmt.Errorf("invalid description: %w", err) } - // we add the following check to ensure that the chain key is created - // beforehand - cfg, err := fpcfg.LoadConfig(ctx.String(homeFlag)) + keyName, err := loadKeyName(ctx) if err != nil { - return fmt.Errorf("failed to load config from %s: %w", fpcfg.ConfigFile(ctx.String(homeFlag)), err) - } - - keyName := ctx.String(keyNameFlag) - // if key name is not specified, we use the key of the config - if keyName == "" { - keyName = cfg.BabylonConfig.Key - if keyName == "" { - return fmt.Errorf("the key in config is empty") - } + return fmt.Errorf("not able to load key name: %w", err) } client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) @@ -178,15 +170,15 @@ func getDescriptionFromContext(ctx *cli.Context) (stakingtypes.Description, erro monikerStr := ctx.String(monikerFlag) identityStr := ctx.String(identityFlag) websiteStr := ctx.String(websiteFlag) - securityContractStr := ctx.String(securityContractFlag) + securityContactStr := ctx.String(securityContactFlag) detailsStr := ctx.String(detailsFlag) - description := stakingtypes.NewDescription(monikerStr, identityStr, websiteStr, securityContractStr, detailsStr) + description := stakingtypes.NewDescription(monikerStr, identityStr, websiteStr, securityContactStr, detailsStr) return description.EnsureLength() } -var lsFpDaemonCmd = cli.Command{ +var LsFpDaemonCmd = cli.Command{ Name: "list-finality-providers", ShortName: "ls", Usage: "List finality providers stored in the database.", @@ -218,7 +210,7 @@ func lsFpDaemon(ctx *cli.Context) error { return nil } -var fpInfoDaemonCmd = cli.Command{ +var FpInfoDaemonCmd = cli.Command{ Name: "finality-provider-info", ShortName: "fpi", Usage: "Show the information of the finality provider.", @@ -260,7 +252,7 @@ func fpInfoDaemon(ctx *cli.Context) error { return nil } -var registerFpDaemonCmd = cli.Command{ +var RegisterFpDaemonCmd = cli.Command{ Name: "register-finality-provider", ShortName: "rfp", Usage: "Register a created finality provider to Babylon.", @@ -309,9 +301,9 @@ func registerFp(ctx *cli.Context) error { return nil } -// addFinalitySigDaemonCmd allows manual submission of finality signatures +// AddFinalitySigDaemonCmd allows manual submission of finality signatures // NOTE: should only be used for presentation/testing purposes -var addFinalitySigDaemonCmd = cli.Command{ +var AddFinalitySigDaemonCmd = cli.Command{ Name: "add-finality-sig", ShortName: "afs", Usage: "Send a finality signature to the consumer chain. This command should only be used for presentation/testing purposes", @@ -369,3 +361,34 @@ func addFinalitySig(ctx *cli.Context) error { return nil } + +func printRespJSON(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("%s\n", jsonBytes) +} + +func loadKeyName(ctx *cli.Context) (string, error) { + keyName := ctx.String(keyNameFlag) + // if key name is not specified, we use the key of the config + if keyName != "" { + return keyName, nil + } + + // we add the following check to ensure that the chain key is created + // beforehand + cfg, err := fpcfg.LoadConfig(ctx.String(homeFlag)) + if err != nil { + return "", fmt.Errorf("failed to load config from %s: %w", fpcfg.ConfigFile(ctx.String(homeFlag)), err) + } + + keyName = cfg.BabylonConfig.Key + if keyName == "" { + return "", fmt.Errorf("the key in config is empty") + } + return keyName, nil +} diff --git a/finality-provider/cmd/fpcli/daemon/export.go b/finality-provider/cmd/fpcli/daemon/export.go new file mode 100644 index 00000000..5a73b9ea --- /dev/null +++ b/finality-provider/cmd/fpcli/daemon/export.go @@ -0,0 +1,162 @@ +package daemon + +import ( + "context" + "encoding/hex" + "fmt" + + "cosmossdk.io/math" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + dc "github.com/babylonchain/finality-provider/finality-provider/service/client" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/x/staking/types" + + bbn "github.com/babylonchain/babylon/types" + btcstktypes "github.com/babylonchain/babylon/x/btcstaking/types" + + "github.com/urfave/cli" +) + +// FinalityProviderSigned wraps the finality provider by adding the +// signature signed by the finality provider's Babylon key in hex +type FinalityProviderSigned struct { + btcstktypes.FinalityProvider + // FpSigHex is the finality provider cosmos sdk chain key + // can be verified with the pub key in btcstktypes.FinalityProvider.BabylonPk + FpSigHex string `json:"fp_sig_hex"` +} + +var ExportFinalityProvider = cli.Command{ + Name: "export-finality-provider", + ShortName: "exfp", + Usage: "It exports the finality provider by the given BTC public key.", + Description: `Fetches the finality provider from the database and exports it + by printing the json structure on the stdout.`, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + cli.StringFlag{ + Name: fpBTCPkFlag, + Usage: "The hex string of the BTC public key", + Required: true, + }, + cli.BoolFlag{ + Name: signedFlag, + Usage: `Specify if the exported finality provider information should be signed, + if true, it will sign using the flag key-name, if not set it will load from the + babylon key on config.`, + }, + cli.StringFlag{ + Name: keyNameFlag, + Usage: "The unique name of the finality provider key", + }, + cli.StringFlag{ + Name: homeFlag, + Usage: "The home path of the finality provider daemon (fpd)", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: hdPathFlag, + Usage: "The hd path used to derive the private key", + Value: defaultHdPath, + }, + }, + Action: exportFp, +} + +func exportFp(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return fmt.Errorf("failled to connect to daemon addr %s: %w", daemonAddress, err) + } + defer cleanUp() + + fpBtcPkHex := ctx.String(fpBTCPkFlag) + fpPk, err := bbn.NewBIP340PubKeyFromHex(fpBtcPkHex) + if err != nil { + return fmt.Errorf("invalid fp btc pk hex %s: %w", fpBtcPkHex, err) + } + + fpInfoResp, err := client.QueryFinalityProviderInfo(context.Background(), fpPk) + if err != nil { + return fmt.Errorf("failed to query fp info from %s: %w", fpBtcPkHex, err) + } + + fpInfo := fpInfoResp.FinalityProvider + comm, err := math.LegacyNewDecFromStr(fpInfo.Commission) + if err != nil { + return fmt.Errorf("failed to parse fp commission %s: %w", fpInfo.Commission, err) + } + + cosmosRawPubKey, err := hex.DecodeString(fpInfo.ChainPkHex) + if err != nil { + return fmt.Errorf("failed to decode chain pk hex %s: %w", fpInfo.ChainPkHex, err) + } + + cosmosPubKey := &secp256k1.PubKey{ + Key: cosmosRawPubKey, + } + + desc := fpInfo.Description + fp := btcstktypes.FinalityProvider{ + BtcPk: fpPk, + MasterPubRand: fpInfo.MasterPubRand, + Pop: &btcstktypes.ProofOfPossession{ + BtcSigType: btcstktypes.BTCSigType_BIP340, + BabylonSig: fpInfo.Pop.ChainSig, + BtcSig: fpInfo.Pop.BtcSig, + }, + BabylonPk: cosmosPubKey, + Description: &types.Description{ + Moniker: desc.Moniker, + Identity: desc.Identity, + Website: desc.Website, + SecurityContact: desc.SecurityContact, + Details: desc.Details, + }, + Commission: &comm, + } + + if !ctx.Bool(signedFlag) { + printRespJSON(fp) + return nil + } + + keyName, err := loadKeyName(ctx) + if err != nil { + return fmt.Errorf("not able to load key name: %w", err) + } + + // sign the finality provider data. + fpbz, err := fp.Marshal() + if err != nil { + return fmt.Errorf("failed to marshal finality provider %+v: %w", fp, err) + } + + resp, err := client.SignMessageFromChainKey( + context.Background(), + keyName, + ctx.String(passphraseFlag), + ctx.String(hdPathFlag), + fpbz, + ) + if err != nil { + return fmt.Errorf("failed to sign finality provider: %w", err) + } + + printRespJSON(FinalityProviderSigned{ + FinalityProvider: fp, + FpSigHex: hex.EncodeToString(resp.Signature), + }) + + return nil +} diff --git a/finality-provider/cmd/fpcli/flags.go b/finality-provider/cmd/fpcli/daemon/flags.go similarity index 61% rename from finality-provider/cmd/fpcli/flags.go rename to finality-provider/cmd/fpcli/daemon/flags.go index 81170016..d2436abc 100644 --- a/finality-provider/cmd/fpcli/flags.go +++ b/finality-provider/cmd/fpcli/daemon/flags.go @@ -1,4 +1,4 @@ -package main +package daemon const ( fpdDaemonAddressFlag = "daemon-address" @@ -10,14 +10,15 @@ const ( passphraseFlag = "passphrase" hdPathFlag = "hd-path" chainIdFlag = "chain-id" + signedFlag = "signed" defaultPassphrase = "" defaultHdPath = "" // flags for description - monikerFlag = "moniker" - identityFlag = "identity" - websiteFlag = "website" - securityContractFlag = "security-contract" - detailsFlag = "details" - commissionRateFlag = "commission" + monikerFlag = "moniker" + identityFlag = "identity" + websiteFlag = "website" + securityContactFlag = "security-contact" + detailsFlag = "details" + commissionRateFlag = "commission" ) diff --git a/finality-provider/cmd/fpcli/main.go b/finality-provider/cmd/fpcli/main.go index a4d84e9c..21e96aab 100644 --- a/finality-provider/cmd/fpcli/main.go +++ b/finality-provider/cmd/fpcli/main.go @@ -1,18 +1,11 @@ package main import ( - "encoding/json" "fmt" "os" - "strconv" + dcli "github.com/babylonchain/finality-provider/finality-provider/cmd/fpcli/daemon" "github.com/urfave/cli" - - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" -) - -var ( - defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) ) func fatal(err error) { @@ -20,28 +13,19 @@ func fatal(err error) { os.Exit(1) } -func printRespJSON(resp interface{}) { - jsonBytes, err := json.MarshalIndent(resp, "", " ") - if err != nil { - fmt.Println("unable to decode response: ", err) - return - } - - fmt.Printf("%s\n", jsonBytes) -} - func main() { app := cli.NewApp() app.Name = "fpcli" app.Usage = "Control plane for the Finality Provider Daemon (fpd)." app.Commands = append(app.Commands, - getDaemonInfoCmd, - createFpDaemonCmd, - lsFpDaemonCmd, - fpInfoDaemonCmd, - registerFpDaemonCmd, - addFinalitySigDaemonCmd, + dcli.GetDaemonInfoCmd, + dcli.CreateFpDaemonCmd, + dcli.LsFpDaemonCmd, + dcli.FpInfoDaemonCmd, + dcli.RegisterFpDaemonCmd, + dcli.AddFinalitySigDaemonCmd, + dcli.ExportFinalityProvider, ) if err := app.Run(os.Args); err != nil { diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/daemon/flags.go similarity index 90% rename from finality-provider/cmd/fpd/flags.go rename to finality-provider/cmd/fpd/daemon/flags.go index 9d79f802..30e9fa4a 100644 --- a/finality-provider/cmd/fpd/flags.go +++ b/finality-provider/cmd/fpd/daemon/flags.go @@ -1,4 +1,4 @@ -package main +package daemon import "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -12,6 +12,7 @@ const ( chainIdFlag = "chain-id" keyringBackendFlag = "keyring-backend" rpcListenerFlag = "rpc-listener" + recoverFlag = "recover" defaultKeyringBackend = keyring.BackendTest defaultHdPath = "" diff --git a/finality-provider/cmd/fpd/init.go b/finality-provider/cmd/fpd/daemon/init.go similarity index 96% rename from finality-provider/cmd/fpd/init.go rename to finality-provider/cmd/fpd/daemon/init.go index 6216eef7..5c95330b 100644 --- a/finality-provider/cmd/fpd/init.go +++ b/finality-provider/cmd/fpd/daemon/init.go @@ -1,4 +1,4 @@ -package main +package daemon import ( "fmt" @@ -11,7 +11,7 @@ import ( "github.com/babylonchain/finality-provider/util" ) -var initCommand = cli.Command{ +var InitCommand = cli.Command{ Name: "init", Usage: "Initialize a finality-provider home directory.", Flags: []cli.Flag{ diff --git a/finality-provider/cmd/fpd/keys.go b/finality-provider/cmd/fpd/daemon/keys.go similarity index 79% rename from finality-provider/cmd/fpd/keys.go rename to finality-provider/cmd/fpd/daemon/keys.go index c39dacd3..3deb0850 100644 --- a/finality-provider/cmd/fpd/keys.go +++ b/finality-provider/cmd/fpd/daemon/keys.go @@ -1,9 +1,14 @@ -package main +package daemon import ( + "bufio" "encoding/json" + "errors" "fmt" + "os" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/go-bip39" "github.com/jessevdk/go-flags" "github.com/urfave/cli" @@ -17,18 +22,18 @@ type KeyOutput struct { Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"` } -var keysCommands = []cli.Command{ +var KeysCommands = []cli.Command{ { Name: "keys", Usage: "Command sets of managing keys for interacting with the consumer chain.", Category: "Key management", Subcommands: []cli.Command{ - addKeyCmd, + AddKeyCmd, }, }, } -var addKeyCmd = cli.Command{ +var AddKeyCmd = cli.Command{ Name: "add", Usage: "Add a key to the consumer chain's keyring. Note that this will change the config file in place.", Flags: []cli.Flag{ @@ -61,6 +66,10 @@ var addKeyCmd = cli.Command{ Usage: "The hd path used to derive the private key", Value: defaultHdPath, }, + cli.BoolFlag{ + Name: recoverFlag, + Usage: "Provide seed phrase to recover existing key instead of creating", + }, }, Action: addKey, } @@ -74,10 +83,20 @@ func addKey(ctx *cli.Context) error { hdPath := ctx.String(hdPathFlag) keyBackend := ctx.String(keyringBackendFlag) - // check the config file exists - cfg, err := fpcfg.LoadConfig(homePath) - if err != nil { - return fmt.Errorf("failed to load the config from %s: %w", fpcfg.ConfigFile(homePath), err) + var ( + mnemonic string + err error + ) + + if ctx.Bool(recoverFlag) { + reader := bufio.NewReader(os.Stdin) + mnemonic, err = input.GetString("Enter your mnemonic", reader) + if err != nil { + return fmt.Errorf("failed to read mnemonic from stdin: %w", err) + } + if !bip39.IsMnemonicValid(mnemonic) { + return errors.New("invalid mnemonic") + } } keyInfo, err := service.CreateChainKey( @@ -87,6 +106,7 @@ func addKey(ctx *cli.Context) error { backend, passphrase, hdPath, + mnemonic, ) if err != nil { return fmt.Errorf("failed to create the chain key: %w", err) @@ -100,6 +120,12 @@ func addKey(ctx *cli.Context) error { }, ) + // check the config file exists + cfg, err := fpcfg.LoadConfig(homePath) + if err != nil { + return nil // config does not exist, so does not update it + } + // write the updated config into the config file cfg.BabylonConfig.Key = keyName cfg.BabylonConfig.KeyringBackend = keyBackend diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/daemon/start.go similarity index 64% rename from finality-provider/cmd/fpd/start.go rename to finality-provider/cmd/fpd/daemon/start.go index 86868164..a2820571 100644 --- a/finality-provider/cmd/fpd/start.go +++ b/finality-provider/cmd/fpd/daemon/start.go @@ -1,4 +1,4 @@ -package main +package daemon import ( "fmt" @@ -6,8 +6,10 @@ import ( "path/filepath" "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcwallet/walletdb" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" + "go.uber.org/zap" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/service" @@ -15,7 +17,7 @@ import ( "github.com/babylonchain/finality-provider/util" ) -var startCommand = cli.Command{ +var StartCommand = cli.Command{ Name: "start", Usage: "Start the finality-provider app", Description: "Start the finality-provider app. Note that eotsd should be started beforehand", @@ -48,9 +50,6 @@ func start(ctx *cli.Context) error { return err } homePath = util.CleanAndExpandPath(homePath) - - passphrase := ctx.String(passphraseFlag) - fpPkStr := ctx.String(fpPkFlag) rpcListener := ctx.String(rpcListenerFlag) cfg, err := fpcfg.LoadConfig(homePath) @@ -68,42 +67,76 @@ func start(ctx *cli.Context) error { logger, err := log.NewRootLoggerWithFile(fpcfg.LogFile(homePath), cfg.LogLevel) if err != nil { - return fmt.Errorf("failed to initialize the logger") + return fmt.Errorf("failed to initialize the logger: %w", err) + } + + dbBackend, err := cfg.DatabaseConfig.GetDbBackend() + if err != nil { + return fmt.Errorf("failed to create db backend: %w", err) } - fpApp, err := service.NewFinalityProviderAppFromConfig(homePath, cfg, logger) + fpApp, err := loadApp(ctx, logger, cfg, dbBackend) + if err != nil { + return fmt.Errorf("failed to load app: %w", err) + } + + if err := startApp(ctx, fpApp); err != nil { + return fmt.Errorf("failed to start app: %w", err) + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + return err + } + + fpServer := service.NewFinalityProviderServer(cfg, logger, fpApp, dbBackend, shutdownInterceptor) + return fpServer.RunUntilShutdown() +} + +// loadApp initialize an finality provider app based on config and flags set. +func loadApp( + ctx *cli.Context, + logger *zap.Logger, + cfg *fpcfg.Config, + dbBackend walletdb.DB, +) (*service.FinalityProviderApp, error) { + fpApp, err := service.NewFinalityProviderAppFromConfig(cfg, dbBackend, logger) if err != nil { - return fmt.Errorf("failed to create finality-provider app: %v", err) + return nil, fmt.Errorf("failed to create finality-provider app: %v", err) } + // sync finality-provider status + if err := fpApp.SyncFinalityProviderStatus(); err != nil { + return nil, fmt.Errorf("failed to sync finality-provider status: %w", err) + } + + return fpApp, nil +} + +// startApp starts the app and the handle of finality providers if needed based on flags. +func startApp( + ctx *cli.Context, + fpApp *service.FinalityProviderApp, +) error { // only start the app without starting any finality-provider instance // as there might be no finality-provider registered yet if err := fpApp.Start(); err != nil { return fmt.Errorf("failed to start the finality-provider app: %w", err) } + fpPkStr := ctx.String(fpPkFlag) if fpPkStr != "" { // start the finality-provider instance with the given public key fpPk, err := types.NewBIP340PubKeyFromHex(fpPkStr) if err != nil { return fmt.Errorf("invalid finality-provider public key %s: %w", fpPkStr, err) } - if err := fpApp.StartHandlingFinalityProvider(fpPk, passphrase); err != nil { + + if err := fpApp.StartHandlingFinalityProvider(fpPk, ctx.String(passphraseFlag)); err != nil { return fmt.Errorf("failed to start the finality-provider instance %s: %w", fpPkStr, err) } - } else { - if err := fpApp.StartHandlingAll(); err != nil { - return err - } } - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - return err - } - - fpServer := service.NewFinalityProviderServer(cfg, logger, fpApp, shutdownInterceptor) - - return fpServer.RunUntilShutdown() + return fpApp.StartHandlingAll() } diff --git a/finality-provider/cmd/fpd/main.go b/finality-provider/cmd/fpd/main.go index 1594b07c..71d166da 100644 --- a/finality-provider/cmd/fpd/main.go +++ b/finality-provider/cmd/fpd/main.go @@ -4,6 +4,7 @@ import ( "fmt" "os" + dcli "github.com/babylonchain/finality-provider/finality-provider/cmd/fpd/daemon" "github.com/urfave/cli" ) @@ -16,8 +17,8 @@ func main() { app := cli.NewApp() app.Name = "fpd" app.Usage = "Finality Provider Daemon (fpd)." - app.Commands = append(app.Commands, startCommand, initCommand) - app.Commands = append(app.Commands, keysCommands...) + app.Commands = append(app.Commands, dcli.StartCommand, dcli.InitCommand) + app.Commands = append(app.Commands, dcli.KeysCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/config/babylon.go b/finality-provider/config/babylon.go similarity index 97% rename from config/babylon.go rename to finality-provider/config/babylon.go index ee97f80b..c6eeb69f 100644 --- a/config/babylon.go +++ b/finality-provider/config/babylon.go @@ -3,7 +3,7 @@ package config import ( "time" - bbncfg "github.com/babylonchain/rpc-client/config" + bbncfg "github.com/babylonchain/babylon/client/config" ) type BBNConfig struct { diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index 24bec710..de2e4b84 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -1,4 +1,4 @@ -package fpcfg +package config import ( "fmt" @@ -11,8 +11,8 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/babylonchain/finality-provider/config" eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/util" ) @@ -36,7 +36,6 @@ const ( defaultMaxSubmissionRetries = 20 defaultBitcoinNetwork = "signet" defaultDataDirname = "data" - defaultDBPath = "bbolt-fpd.db" defaultMaxNumFinalityProviders = 3 ) @@ -49,6 +48,7 @@ var ( defaultBTCNetParams = chaincfg.SigNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) DefaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) + DefaultDataDir = DataDir(DefaultFpdDir) ) // Config is the main config for the fpd cli command @@ -75,23 +75,24 @@ type Config struct { PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` - DatabaseConfig *config.DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` + DatabaseConfig *DBConfig `group:"dbconfig" namespace:"dbconfig"` - BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` + BabylonConfig *BBNConfig `group:"babylon" namespace:"babylon"` RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` + + Metrics *metrics.Config `group:"metrics" namespace:"metrics"` } func DefaultConfigWithHome(homePath string) Config { - bbnCfg := config.DefaultBBNConfig() + bbnCfg := DefaultBBNConfig() bbnCfg.Key = defaultFinalityProviderKeyName bbnCfg.KeyDirectory = homePath - dbCfg := config.DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() cfg := Config{ ChainName: defaultChainName, LogLevel: defaultLogLevel, - DatabaseConfig: &dbCfg, + DatabaseConfig: DefaultDBConfigWithHomePath(homePath), BabylonConfig: &bbnCfg, PollerConfig: &pollerCfg, NumPubRand: defaultNumPubRand, @@ -109,6 +110,7 @@ func DefaultConfigWithHome(homePath string) Config { EOTSManagerAddress: defaultEOTSManagerAddress, RpcListener: DefaultRpcListener, MaxNumFinalityProviders: defaultMaxNumFinalityProviders, + Metrics: metrics.DefaultFpConfig(), } if err := cfg.Validate(); err != nil { @@ -138,10 +140,6 @@ func DataDir(homePath string) string { return filepath.Join(homePath, defaultDataDirname) } -func DBPath(homePath string) string { - return filepath.Join(DataDir(homePath), defaultDBPath) -} - // LoadConfig initializes and parses the config using a config file and command // line options. // @@ -205,6 +203,14 @@ func (cfg *Config) Validate() error { return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) } + if cfg.Metrics == nil { + return fmt.Errorf("empty metrics config") + } + + if err := cfg.Metrics.Validate(); err != nil { + return fmt.Errorf("invalid metrics config") + } + // All good, return the sanitized result. return nil } diff --git a/finality-provider/config/db.go b/finality-provider/config/db.go new file mode 100644 index 00000000..171c2856 --- /dev/null +++ b/finality-provider/config/db.go @@ -0,0 +1,72 @@ +package config + +import ( + "time" + + "github.com/lightningnetwork/lnd/kvdb" +) + +const ( + defaultDbName = "finality-provider.db" +) + +type DBConfig struct { + // DBPath is the directory path in which the database file should be + // stored. + DBPath string `long:"dbpath" description:"The directory path in which the database file should be stored."` + + // DBFileName is the name of the database file. + DBFileName string `long:"dbfilename" description:"The name of the database file."` + + // NoFreelistSync, if true, prevents the database from syncing its + // freelist to disk, resulting in improved performance at the expense of + // increased startup time. + NoFreelistSync bool `long:"nofreelistsync" description:"Prevents the database from syncing its freelist to disk, resulting in improved performance at the expense of increased startup time."` + + // AutoCompact specifies if a Bolt based database backend should be + // automatically compacted on startup (if the minimum age of the + // database file is reached). This will require additional disk space + // for the compacted copy of the database but will result in an overall + // lower database size after the compaction. + AutoCompact bool `long:"autocompact" description:"Specifies if a Bolt based database backend should be automatically compacted on startup (if the minimum age of the database file is reached). This will require additional disk space for the compacted copy of the database but will result in an overall lower database size after the compaction."` + + // AutoCompactMinAge specifies the minimum time that must have passed + // since a bolt database file was last compacted for the compaction to + // be considered again. + AutoCompactMinAge time.Duration `long:"autocompactminage" description:"Specifies the minimum time that must have passed since a bolt database file was last compacted for the compaction to be considered again."` + + // DBTimeout specifies the timeout value to use when opening the wallet + // database. + DBTimeout time.Duration `long:"dbtimeout" description:"Specifies the timeout value to use when opening the wallet database."` +} + +func DefaultDBConfig() *DBConfig { + return DefaultDBConfigWithHomePath(DefaultFpdDir) +} + +func DefaultDBConfigWithHomePath(homePath string) *DBConfig { + return &DBConfig{ + DBPath: DataDir(homePath), + DBFileName: defaultDbName, + NoFreelistSync: true, + AutoCompact: false, + AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge, + DBTimeout: kvdb.DefaultDBTimeout, + } + +} + +func (db *DBConfig) DBConfigToBoltBackendConfig() *kvdb.BoltBackendConfig { + return &kvdb.BoltBackendConfig{ + DBPath: db.DBPath, + DBFileName: db.DBFileName, + NoFreelistSync: db.NoFreelistSync, + AutoCompact: db.AutoCompact, + AutoCompactMinAge: db.AutoCompactMinAge, + DBTimeout: db.DBTimeout, + } +} + +func (db *DBConfig) GetDbBackend() (kvdb.Backend, error) { + return kvdb.GetBoltBackend(db.DBConfigToBoltBackendConfig()) +} diff --git a/finality-provider/config/poller.go b/finality-provider/config/poller.go index 6184ccfc..71bdeb15 100644 --- a/finality-provider/config/poller.go +++ b/finality-provider/config/poller.go @@ -1,4 +1,4 @@ -package fpcfg +package config import "time" diff --git a/finality-provider/proto/finality_providers.go b/finality-provider/proto/finality_providers.go index 975535c0..86f69819 100644 --- a/finality-provider/proto/finality_providers.go +++ b/finality-provider/proto/finality_providers.go @@ -11,17 +11,17 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -func (sfp *StoreFinalityProvider) GetBabylonPK() *secp256k1.PubKey { +func (sfp *FinalityProvider) GetChainPK() *secp256k1.PubKey { return &secp256k1.PubKey{ - Key: sfp.BabylonPk, + Key: sfp.ChainPk, } } -func (sfp *StoreFinalityProvider) GetBabylonPkHexString() string { - return hex.EncodeToString(sfp.BabylonPk) +func (sfp *FinalityProvider) GetChainPkHexString() string { + return hex.EncodeToString(sfp.ChainPk) } -func (sfp *StoreFinalityProvider) MustGetBTCPK() *btcec.PublicKey { +func (sfp *FinalityProvider) MustGetBTCPK() *btcec.PublicKey { btcPubKey, err := schnorr.ParsePubKey(sfp.BtcPk) if err != nil { panic(fmt.Errorf("failed to parse BTC PK: %w", err)) @@ -29,19 +29,19 @@ func (sfp *StoreFinalityProvider) MustGetBTCPK() *btcec.PublicKey { return btcPubKey } -func (sfp *StoreFinalityProvider) MustGetBIP340BTCPK() *bbn.BIP340PubKey { +func (sfp *FinalityProvider) MustGetBIP340BTCPK() *bbn.BIP340PubKey { btcPK := sfp.MustGetBTCPK() return bbn.NewBIP340PubKeyFromBTCPK(btcPK) } -func NewFinalityProviderInfo(sfp *StoreFinalityProvider) (*FinalityProviderInfo, error) { +func NewFinalityProviderInfo(sfp *FinalityProvider) (*FinalityProviderInfo, error) { var des types.Description if err := des.Unmarshal(sfp.Description); err != nil { return nil, err } return &FinalityProviderInfo{ - BabylonPkHex: sfp.GetBabylonPkHexString(), - BtcPkHex: sfp.MustGetBIP340BTCPK().MarshalHex(), + ChainPkHex: sfp.GetChainPkHexString(), + BtcPkHex: sfp.MustGetBIP340BTCPK().MarshalHex(), Description: &Description{ Moniker: des.Moniker, Identity: des.Identity, @@ -49,6 +49,8 @@ func NewFinalityProviderInfo(sfp *StoreFinalityProvider) (*FinalityProviderInfo, SecurityContact: des.SecurityContact, Details: des.Details, }, + RegisteredEpoch: sfp.RegisteredEpoch, + MasterPubRand: sfp.MasterPubRand, LastVotedHeight: sfp.LastVotedHeight, Status: sfp.Status.String(), }, nil diff --git a/finality-provider/proto/finality_providers.pb.go b/finality-provider/proto/finality_providers.pb.go index 01c48ce6..5a05b1ae 100644 --- a/finality-provider/proto/finality_providers.pb.go +++ b/finality-provider/proto/finality_providers.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.33.0 // protoc (unknown) // source: finality_providers.proto @@ -26,11 +26,11 @@ const ( // FinalityProviderStatus is the status of a finality provider // a FinalityProvider object has 4 states: // - Created - created and managed by finality provider client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, but not voting yet (No +// the consumer chain yet +// - Registered - created and registered to the consumer chain, but not voting yet (No // delegated stake) -// - Active - created and registered to Babylon with stake to vote -// - Inactive - created and registered to Babylon with no stake to vote. +// - Active - created and registered to the consumer chain with stake to vote +// - Inactive - created and registered to the consumer chain with no stake to vote. // Finality Provider was already active. // // Valid State Transactions: @@ -44,7 +44,7 @@ const ( // CREATED defines a finality provider that is awaiting registration FinalityProviderStatus_CREATED FinalityProviderStatus = 0 // REGISTERED defines a finality provider that has been registered - // to Babylon but has no delegated stake + // to the consumer chain but has no delegated stake FinalityProviderStatus_REGISTERED FinalityProviderStatus = 1 // ACTIVE defines a finality provider that is delegated to vote FinalityProviderStatus_ACTIVE FinalityProviderStatus = 2 @@ -386,7 +386,7 @@ type RegisterFinalityProviderResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // hash of the successful Babylon registration transaction + // hash of the successful chain registration transaction TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` } @@ -436,9 +436,9 @@ type AddFinalitySignatureRequest struct { // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` - // height is the height of the Babylon block + // height is the height of the chain block Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - // app_hash is the AppHash of the Babylon block + // app_hash is the AppHash of the chain block AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } @@ -500,7 +500,7 @@ type AddFinalitySignatureResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // hash of the successful Babylon finality signature submission transaction + // hash of the successful chain finality signature submission transaction TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` // the hex string of the extracted Bitcoin secp256k1 private key ExtractedSkHex string `protobuf:"bytes,2,opt,name=extracted_sk_hex,json=extractedSkHex,proto3" json:"extracted_sk_hex,omitempty"` @@ -741,36 +741,41 @@ func (x *QueryFinalityProviderListResponse) GetFinalityProviders() []*FinalityPr return nil } -type StoreFinalityProvider struct { +type FinalityProvider struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_pk is the Babylon secp256k1 PK of this finality provider - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` + // chain_pk is the chain secp256k1 PK of this finality provider + ChainPk []byte `protobuf:"bytes,1,opt,name=chain_pk,json=chainPk,proto3" json:"chain_pk,omitempty"` // btc_pk is the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec BtcPk []byte `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` // description defines the description terms for the finality provider Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the finality provider Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` - // pop is the proof of possession of babylon_pk and btc_pk + // pop is the proof of possession of chain_pk and btc_pk Pop *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,omitempty"` + // master_pub_rand is the master public randomness of the finality provider + // encoded as a base58 string + MasterPubRand string `protobuf:"bytes,6,opt,name=master_pub_rand,json=masterPubRand,proto3" json:"master_pub_rand,omitempty"` + // registered_epoch is the epoch number when the finality provider is registered on Babylon + RegisteredEpoch uint64 `protobuf:"varint,7,opt,name=registered_epoch,json=registeredEpoch,proto3" json:"registered_epoch,omitempty"` // key_name is the identifier of the keyring - KeyName string `protobuf:"bytes,6,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + KeyName string `protobuf:"bytes,8,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` // chain_id is the identifier of the consumer chain that the finality provider connected to - ChainId string `protobuf:"bytes,7,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - // last_voted_height defines the height of the last voted Babylon block - LastVotedHeight uint64 `protobuf:"varint,8,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` + ChainId string `protobuf:"bytes,9,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // last_voted_height defines the height of the last voted chain block + LastVotedHeight uint64 `protobuf:"varint,10,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` // last_processed_height defines the height of the last successfully processed block // even though the vote is not cast - LastProcessedHeight uint64 `protobuf:"varint,9,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` + LastProcessedHeight uint64 `protobuf:"varint,11,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` // status defines the current finality provider status - Status FinalityProviderStatus `protobuf:"varint,10,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` + Status FinalityProviderStatus `protobuf:"varint,12,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` } -func (x *StoreFinalityProvider) Reset() { - *x = StoreFinalityProvider{} +func (x *FinalityProvider) Reset() { + *x = FinalityProvider{} if protoimpl.UnsafeEnabled { mi := &file_finality_providers_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -778,13 +783,13 @@ func (x *StoreFinalityProvider) Reset() { } } -func (x *StoreFinalityProvider) String() string { +func (x *FinalityProvider) String() string { return protoimpl.X.MessageStringOf(x) } -func (*StoreFinalityProvider) ProtoMessage() {} +func (*FinalityProvider) ProtoMessage() {} -func (x *StoreFinalityProvider) ProtoReflect() protoreflect.Message { +func (x *FinalityProvider) ProtoReflect() protoreflect.Message { mi := &file_finality_providers_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -796,75 +801,89 @@ func (x *StoreFinalityProvider) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use StoreFinalityProvider.ProtoReflect.Descriptor instead. -func (*StoreFinalityProvider) Descriptor() ([]byte, []int) { +// Deprecated: Use FinalityProvider.ProtoReflect.Descriptor instead. +func (*FinalityProvider) Descriptor() ([]byte, []int) { return file_finality_providers_proto_rawDescGZIP(), []int{12} } -func (x *StoreFinalityProvider) GetBabylonPk() []byte { +func (x *FinalityProvider) GetChainPk() []byte { if x != nil { - return x.BabylonPk + return x.ChainPk } return nil } -func (x *StoreFinalityProvider) GetBtcPk() []byte { +func (x *FinalityProvider) GetBtcPk() []byte { if x != nil { return x.BtcPk } return nil } -func (x *StoreFinalityProvider) GetDescription() []byte { +func (x *FinalityProvider) GetDescription() []byte { if x != nil { return x.Description } return nil } -func (x *StoreFinalityProvider) GetCommission() string { +func (x *FinalityProvider) GetCommission() string { if x != nil { return x.Commission } return "" } -func (x *StoreFinalityProvider) GetPop() *ProofOfPossession { +func (x *FinalityProvider) GetPop() *ProofOfPossession { if x != nil { return x.Pop } return nil } -func (x *StoreFinalityProvider) GetKeyName() string { +func (x *FinalityProvider) GetMasterPubRand() string { + if x != nil { + return x.MasterPubRand + } + return "" +} + +func (x *FinalityProvider) GetRegisteredEpoch() uint64 { + if x != nil { + return x.RegisteredEpoch + } + return 0 +} + +func (x *FinalityProvider) GetKeyName() string { if x != nil { return x.KeyName } return "" } -func (x *StoreFinalityProvider) GetChainId() string { +func (x *FinalityProvider) GetChainId() string { if x != nil { return x.ChainId } return "" } -func (x *StoreFinalityProvider) GetLastVotedHeight() uint64 { +func (x *FinalityProvider) GetLastVotedHeight() uint64 { if x != nil { return x.LastVotedHeight } return 0 } -func (x *StoreFinalityProvider) GetLastProcessedHeight() uint64 { +func (x *FinalityProvider) GetLastProcessedHeight() uint64 { if x != nil { return x.LastProcessedHeight } return 0 } -func (x *StoreFinalityProvider) GetStatus() FinalityProviderStatus { +func (x *FinalityProvider) GetStatus() FinalityProviderStatus { if x != nil { return x.Status } @@ -877,18 +896,27 @@ type FinalityProviderInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this finality provider - BabylonPkHex string `protobuf:"bytes,1,opt,name=babylon_pk_hex,json=babylonPkHex,proto3" json:"babylon_pk_hex,omitempty"` + // chain_pk_hex is the hex string of the chain secp256k1 PK of this finality provider + ChainPkHex string `protobuf:"bytes,1,opt,name=chain_pk_hex,json=chainPkHex,proto3" json:"chain_pk_hex,omitempty"` // btc_pk_hex is the hex string of the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec BtcPkHex string `protobuf:"bytes,2,opt,name=btc_pk_hex,json=btcPkHex,proto3" json:"btc_pk_hex,omitempty"` // description defines the description terms for the finality provider Description *Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the finality provider Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` - // last_voted_height defines the height of the last voted Babylon block - LastVotedHeight uint64 `protobuf:"varint,5,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` + // registered_epoch is the epoch number when the finality provider is registered on Babylon + RegisteredEpoch uint64 `protobuf:"varint,5,opt,name=registered_epoch,json=registeredEpoch,proto3" json:"registered_epoch,omitempty"` + // master_pub_rand is the master public randomness of the finality provider + // encoded as a base58 string + MasterPubRand string `protobuf:"bytes,6,opt,name=master_pub_rand,json=masterPubRand,proto3" json:"master_pub_rand,omitempty"` + // last_voted_height defines the height of the last voted chain block + LastVotedHeight uint64 `protobuf:"varint,7,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` // status defines the current finality provider status - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + // is_running shows whether the finality provider is running within the daemon + IsRunning bool `protobuf:"varint,9,opt,name=is_running,json=isRunning,proto3" json:"is_running,omitempty"` + // pop is the proof of possession of chain_pk and btc_pk + Pop *ProofOfPossession `protobuf:"bytes,10,opt,name=pop,proto3" json:"pop,omitempty"` } func (x *FinalityProviderInfo) Reset() { @@ -923,9 +951,9 @@ func (*FinalityProviderInfo) Descriptor() ([]byte, []int) { return file_finality_providers_proto_rawDescGZIP(), []int{13} } -func (x *FinalityProviderInfo) GetBabylonPkHex() string { +func (x *FinalityProviderInfo) GetChainPkHex() string { if x != nil { - return x.BabylonPkHex + return x.ChainPkHex } return "" } @@ -951,6 +979,20 @@ func (x *FinalityProviderInfo) GetCommission() string { return "" } +func (x *FinalityProviderInfo) GetRegisteredEpoch() uint64 { + if x != nil { + return x.RegisteredEpoch + } + return 0 +} + +func (x *FinalityProviderInfo) GetMasterPubRand() string { + if x != nil { + return x.MasterPubRand + } + return "" +} + func (x *FinalityProviderInfo) GetLastVotedHeight() uint64 { if x != nil { return x.LastVotedHeight @@ -965,6 +1007,20 @@ func (x *FinalityProviderInfo) GetStatus() string { return "" } +func (x *FinalityProviderInfo) GetIsRunning() bool { + if x != nil { + return x.IsRunning + } + return false +} + +func (x *FinalityProviderInfo) GetPop() *ProofOfPossession { + if x != nil { + return x.Pop + } + return nil +} + // Description defines description fields for a finality provider type Description struct { state protoimpl.MessageState @@ -1045,7 +1101,7 @@ func (x *Description) GetDetails() string { return "" } -// ProofOfPossession is the proof of possession that a Babylon secp256k1 +// ProofOfPossession is the proof of possession that a chain secp256k1 // secret key and a Bitcoin secp256k1 secret key are held by the same // person type ProofOfPossession struct { @@ -1053,9 +1109,9 @@ type ProofOfPossession struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) - BabylonSig []byte `protobuf:"bytes,1,opt,name=babylon_sig,json=babylonSig,proto3" json:"babylon_sig,omitempty"` - // btc_sig is the signature generated via sign(sk_btc, babylon_sig) + // chain_sig is the signature generated via sign(sk_chain, pk_btc) + ChainSig []byte `protobuf:"bytes,1,opt,name=chain_sig,json=chainSig,proto3" json:"chain_sig,omitempty"` + // btc_sig is the signature generated via sign(sk_btc, chain_sig) // the signature follows encoding in BIP-340 spec BtcSig []byte `protobuf:"bytes,2,opt,name=btc_sig,json=btcSig,proto3" json:"btc_sig,omitempty"` } @@ -1092,9 +1148,9 @@ func (*ProofOfPossession) Descriptor() ([]byte, []int) { return file_finality_providers_proto_rawDescGZIP(), []int{15} } -func (x *ProofOfPossession) GetBabylonSig() []byte { +func (x *ProofOfPossession) GetChainSig() []byte { if x != nil { - return x.BabylonSig + return x.ChainSig } return nil } @@ -1161,6 +1217,129 @@ func (x *SchnorrRandPair) GetSecRand() []byte { return nil } +type SignMessageFromChainKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // msg_to_sign the raw bytes to sign using the private key. + MsgToSign []byte `protobuf:"bytes,1,opt,name=msg_to_sign,json=msgToSign,proto3" json:"msg_to_sign,omitempty"` + // key_name is the identifier key in keyring + KeyName string `protobuf:"bytes,2,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,3,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,4,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` +} + +func (x *SignMessageFromChainKeyRequest) Reset() { + *x = SignMessageFromChainKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignMessageFromChainKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignMessageFromChainKeyRequest) ProtoMessage() {} + +func (x *SignMessageFromChainKeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignMessageFromChainKeyRequest.ProtoReflect.Descriptor instead. +func (*SignMessageFromChainKeyRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{17} +} + +func (x *SignMessageFromChainKeyRequest) GetMsgToSign() []byte { + if x != nil { + return x.MsgToSign + } + return nil +} + +func (x *SignMessageFromChainKeyRequest) GetKeyName() string { + if x != nil { + return x.KeyName + } + return "" +} + +func (x *SignMessageFromChainKeyRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +func (x *SignMessageFromChainKeyRequest) GetHdPath() string { + if x != nil { + return x.HdPath + } + return "" +} + +// SignMessageFromChainKeyResponse contains the signed message from the chain keyring. +type SignMessageFromChainKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *SignMessageFromChainKeyResponse) Reset() { + *x = SignMessageFromChainKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignMessageFromChainKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignMessageFromChainKeyResponse) ProtoMessage() {} + +func (x *SignMessageFromChainKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignMessageFromChainKeyResponse.ProtoReflect.Descriptor instead. +func (*SignMessageFromChainKeyResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{18} +} + +func (x *SignMessageFromChainKeyResponse) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + var File_finality_providers_proto protoreflect.FileDescriptor var file_finality_providers_proto_rawDesc = []byte{ @@ -1241,124 +1420,159 @@ var file_finality_providers_proto_rawDesc = []byte{ 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xad, 0x03, 0x0a, 0x15, 0x53, 0x74, 0x6f, - 0x72, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x50, - 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, - 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, - 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x2a, 0x0a, 0x03, 0x70, 0x6f, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x70, 0x6f, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x6b, - 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, - 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, - 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, - 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x99, 0x02, 0x0a, 0x14, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, 0x5f, - 0x68, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, 0x62, 0x79, 0x6c, - 0x6f, 0x6e, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, - 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, - 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, - 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, - 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, - 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, - 0x73, 0x69, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, - 0x0a, 0x0b, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x53, 0x69, 0x67, 0x12, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xf7, 0x03, 0x0a, 0x10, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, + 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, + 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, + 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x03, 0x70, 0x6f, 0x70, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x70, + 0x6f, 0x70, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, + 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x61, 0x73, + 0x74, 0x65, 0x72, 0x50, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, + 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0xb3, 0x03, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0c, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x1c, 0x0a, + 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, + 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, + 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x5f, + 0x72, 0x61, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x50, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x69, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x2a, 0x0a, 0x03, + 0x70, 0x6f, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x70, 0x6f, 0x70, 0x22, 0xa2, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, + 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, + 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x49, 0x0a, + 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x74, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x74, 0x63, 0x53, 0x69, 0x67, 0x22, 0x47, 0x0a, 0x0f, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x52, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x65, 0x63, 0x52, 0x61, 0x6e, - 0x64, 0x2a, 0xa6, 0x01, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x43, - 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, - 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x0e, 0x8a, 0x9d, 0x20, 0x0a, 0x52, 0x45, 0x47, 0x49, - 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, - 0x10, 0x02, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x1a, - 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x1a, 0x0c, 0x8a, 0x9d, - 0x20, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x4c, - 0x41, 0x53, 0x48, 0x45, 0x44, 0x10, 0x04, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x53, 0x4c, 0x41, - 0x53, 0x48, 0x45, 0x44, 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x32, 0xd6, 0x04, 0x0a, 0x11, 0x46, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x26, 0x2e, + 0x64, 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6d, 0x73, 0x67, 0x5f, 0x74, 0x6f, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x73, 0x67, 0x54, 0x6f, + 0x53, 0x69, 0x67, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, + 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0x3f, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0xa6, 0x01, 0x0a, 0x16, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, + 0x00, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x12, 0x1e, + 0x0a, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x0e, + 0x8a, 0x9d, 0x20, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x12, 0x16, + 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, + 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, + 0x56, 0x45, 0x10, 0x03, 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, + 0x56, 0x45, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x10, 0x04, 0x1a, + 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x1a, 0x04, 0x88, 0xa3, + 0x1e, 0x00, 0x32, 0xc0, 0x05, 0x0a, 0x11, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, - 0x0a, 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, - 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x62, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x19, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x66, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x53, + 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x72, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1374,7 +1588,7 @@ func file_finality_providers_proto_rawDescGZIP() []byte { } var file_finality_providers_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_finality_providers_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_finality_providers_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_finality_providers_proto_goTypes = []interface{}{ (FinalityProviderStatus)(0), // 0: proto.FinalityProviderStatus (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest @@ -1389,36 +1603,41 @@ var file_finality_providers_proto_goTypes = []interface{}{ (*QueryFinalityProviderResponse)(nil), // 10: proto.QueryFinalityProviderResponse (*QueryFinalityProviderListRequest)(nil), // 11: proto.QueryFinalityProviderListRequest (*QueryFinalityProviderListResponse)(nil), // 12: proto.QueryFinalityProviderListResponse - (*StoreFinalityProvider)(nil), // 13: proto.StoreFinalityProvider + (*FinalityProvider)(nil), // 13: proto.FinalityProvider (*FinalityProviderInfo)(nil), // 14: proto.FinalityProviderInfo (*Description)(nil), // 15: proto.Description (*ProofOfPossession)(nil), // 16: proto.ProofOfPossession (*SchnorrRandPair)(nil), // 17: proto.SchnorrRandPair + (*SignMessageFromChainKeyRequest)(nil), // 18: proto.SignMessageFromChainKeyRequest + (*SignMessageFromChainKeyResponse)(nil), // 19: proto.SignMessageFromChainKeyResponse } var file_finality_providers_proto_depIdxs = []int32{ 14, // 0: proto.CreateFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo 14, // 1: proto.QueryFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo 14, // 2: proto.QueryFinalityProviderListResponse.finality_providers:type_name -> proto.FinalityProviderInfo - 16, // 3: proto.StoreFinalityProvider.pop:type_name -> proto.ProofOfPossession - 0, // 4: proto.StoreFinalityProvider.status:type_name -> proto.FinalityProviderStatus + 16, // 3: proto.FinalityProvider.pop:type_name -> proto.ProofOfPossession + 0, // 4: proto.FinalityProvider.status:type_name -> proto.FinalityProviderStatus 15, // 5: proto.FinalityProviderInfo.description:type_name -> proto.Description - 1, // 6: proto.FinalityProviders.GetInfo:input_type -> proto.GetInfoRequest - 3, // 7: proto.FinalityProviders.CreateFinalityProvider:input_type -> proto.CreateFinalityProviderRequest - 5, // 8: proto.FinalityProviders.RegisterFinalityProvider:input_type -> proto.RegisterFinalityProviderRequest - 7, // 9: proto.FinalityProviders.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest - 9, // 10: proto.FinalityProviders.QueryFinalityProvider:input_type -> proto.QueryFinalityProviderRequest - 11, // 11: proto.FinalityProviders.QueryFinalityProviderList:input_type -> proto.QueryFinalityProviderListRequest - 2, // 12: proto.FinalityProviders.GetInfo:output_type -> proto.GetInfoResponse - 4, // 13: proto.FinalityProviders.CreateFinalityProvider:output_type -> proto.CreateFinalityProviderResponse - 6, // 14: proto.FinalityProviders.RegisterFinalityProvider:output_type -> proto.RegisterFinalityProviderResponse - 8, // 15: proto.FinalityProviders.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse - 10, // 16: proto.FinalityProviders.QueryFinalityProvider:output_type -> proto.QueryFinalityProviderResponse - 12, // 17: proto.FinalityProviders.QueryFinalityProviderList:output_type -> proto.QueryFinalityProviderListResponse - 12, // [12:18] is the sub-list for method output_type - 6, // [6:12] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 16, // 6: proto.FinalityProviderInfo.pop:type_name -> proto.ProofOfPossession + 1, // 7: proto.FinalityProviders.GetInfo:input_type -> proto.GetInfoRequest + 3, // 8: proto.FinalityProviders.CreateFinalityProvider:input_type -> proto.CreateFinalityProviderRequest + 5, // 9: proto.FinalityProviders.RegisterFinalityProvider:input_type -> proto.RegisterFinalityProviderRequest + 7, // 10: proto.FinalityProviders.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest + 9, // 11: proto.FinalityProviders.QueryFinalityProvider:input_type -> proto.QueryFinalityProviderRequest + 11, // 12: proto.FinalityProviders.QueryFinalityProviderList:input_type -> proto.QueryFinalityProviderListRequest + 18, // 13: proto.FinalityProviders.SignMessageFromChainKey:input_type -> proto.SignMessageFromChainKeyRequest + 2, // 14: proto.FinalityProviders.GetInfo:output_type -> proto.GetInfoResponse + 4, // 15: proto.FinalityProviders.CreateFinalityProvider:output_type -> proto.CreateFinalityProviderResponse + 6, // 16: proto.FinalityProviders.RegisterFinalityProvider:output_type -> proto.RegisterFinalityProviderResponse + 8, // 17: proto.FinalityProviders.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse + 10, // 18: proto.FinalityProviders.QueryFinalityProvider:output_type -> proto.QueryFinalityProviderResponse + 12, // 19: proto.FinalityProviders.QueryFinalityProviderList:output_type -> proto.QueryFinalityProviderListResponse + 19, // 20: proto.FinalityProviders.SignMessageFromChainKey:output_type -> proto.SignMessageFromChainKeyResponse + 14, // [14:21] is the sub-list for method output_type + 7, // [7:14] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_finality_providers_proto_init() } @@ -1572,7 +1791,7 @@ func file_finality_providers_proto_init() { } } file_finality_providers_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StoreFinalityProvider); i { + switch v := v.(*FinalityProvider); i { case 0: return &v.state case 1: @@ -1631,6 +1850,30 @@ func file_finality_providers_proto_init() { return nil } } + file_finality_providers_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignMessageFromChainKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignMessageFromChainKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1638,7 +1881,7 @@ func file_finality_providers_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_finality_providers_proto_rawDesc, NumEnums: 1, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, diff --git a/finality-provider/proto/finality_providers.proto b/finality-provider/proto/finality_providers.proto index 484e706f..ea587916 100644 --- a/finality-provider/proto/finality_providers.proto +++ b/finality-provider/proto/finality_providers.proto @@ -16,12 +16,12 @@ service FinalityProviders { rpc CreateFinalityProvider (CreateFinalityProviderRequest) returns (CreateFinalityProviderResponse); - // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // RegisterFinalityProvider sends a transactions to the consumer chain to register a BTC // finality provider rpc RegisterFinalityProvider (RegisterFinalityProviderRequest) returns (RegisterFinalityProviderResponse); - // AddFinalitySignature sends a transactions to Babylon to add a Finality + // AddFinalitySignature sends a transactions to the consumer chain to add a Finality // signature for a block rpc AddFinalitySignature(AddFinalitySignatureRequest) returns (AddFinalitySignatureResponse); @@ -32,6 +32,10 @@ service FinalityProviders { // QueryFinalityProviderList queries a list of finality providers rpc QueryFinalityProviderList (QueryFinalityProviderListRequest) returns (QueryFinalityProviderListResponse); + + // SignMessageFromChainKey signs a message from the chain keyring. + rpc SignMessageFromChainKey (SignMessageFromChainKeyRequest) + returns (SignMessageFromChainKeyResponse); } message GetInfoRequest { @@ -71,21 +75,21 @@ message RegisterFinalityProviderRequest { } message RegisterFinalityProviderResponse { - // hash of the successful Babylon registration transaction + // hash of the successful chain registration transaction string tx_hash = 1; } message AddFinalitySignatureRequest { // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec string btc_pk = 1; - // height is the height of the Babylon block + // height is the height of the chain block uint64 height = 2; - // app_hash is the AppHash of the Babylon block + // app_hash is the AppHash of the chain block bytes app_hash = 3; } message AddFinalitySignatureResponse { - // hash of the successful Babylon finality signature submission transaction + // hash of the successful chain finality signature submission transaction string tx_hash = 1; // the hex string of the extracted Bitcoin secp256k1 private key string extracted_sk_hex = 2; @@ -111,9 +115,9 @@ message QueryFinalityProviderListResponse { // TODO add pagination in case the list gets large } -message StoreFinalityProvider { - // babylon_pk is the Babylon secp256k1 PK of this finality provider - bytes babylon_pk = 1; +message FinalityProvider { + // chain_pk is the chain secp256k1 PK of this finality provider + bytes chain_pk = 1; // btc_pk is the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec bytes btc_pk = 2; // description defines the description terms for the finality provider @@ -123,25 +127,30 @@ message StoreFinalityProvider { (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; - // pop is the proof of possession of babylon_pk and btc_pk + // pop is the proof of possession of chain_pk and btc_pk ProofOfPossession pop = 5; + // master_pub_rand is the master public randomness of the finality provider + // encoded as a base58 string + string master_pub_rand = 6; + // registered_epoch is the epoch number when the finality provider is registered on Babylon + uint64 registered_epoch = 7; // key_name is the identifier of the keyring - string key_name = 6; + string key_name = 8; // chain_id is the identifier of the consumer chain that the finality provider connected to - string chain_id = 7; - // last_voted_height defines the height of the last voted Babylon block - uint64 last_voted_height = 8; + string chain_id = 9; + // last_voted_height defines the height of the last voted chain block + uint64 last_voted_height = 10; // last_processed_height defines the height of the last successfully processed block // even though the vote is not cast - uint64 last_processed_height = 9; + uint64 last_processed_height = 11; // status defines the current finality provider status - FinalityProviderStatus status = 10; + FinalityProviderStatus status = 12; } // FinalityProviderInfo is the basic information of a finality provider mainly for external usage message FinalityProviderInfo { - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this finality provider - string babylon_pk_hex = 1; + // chain_pk_hex is the hex string of the chain secp256k1 PK of this finality provider + string chain_pk_hex = 1; // btc_pk_hex is the hex string of the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec string btc_pk_hex = 2; // description defines the description terms for the finality provider @@ -151,10 +160,19 @@ message FinalityProviderInfo { (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; - // last_voted_height defines the height of the last voted Babylon block - uint64 last_voted_height = 5; + // registered_epoch is the epoch number when the finality provider is registered on Babylon + uint64 registered_epoch = 5; + // master_pub_rand is the master public randomness of the finality provider + // encoded as a base58 string + string master_pub_rand = 6; + // last_voted_height defines the height of the last voted chain block + uint64 last_voted_height = 7; // status defines the current finality provider status - string status = 6; + string status = 8; + // is_running shows whether the finality provider is running within the daemon + bool is_running = 9; + // pop is the proof of possession of chain_pk and btc_pk + ProofOfPossession pop = 10; } // Description defines description fields for a finality provider @@ -166,13 +184,13 @@ message Description { string details = 5; } -// ProofOfPossession is the proof of possession that a Babylon secp256k1 +// ProofOfPossession is the proof of possession that a chain secp256k1 // secret key and a Bitcoin secp256k1 secret key are held by the same // person message ProofOfPossession { - // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) - bytes babylon_sig = 1; - // btc_sig is the signature generated via sign(sk_btc, babylon_sig) + // chain_sig is the signature generated via sign(sk_chain, pk_btc) + bytes chain_sig = 1; + // btc_sig is the signature generated via sign(sk_btc, chain_sig) // the signature follows encoding in BIP-340 spec bytes btc_sig = 2; } @@ -185,11 +203,11 @@ message SchnorrRandPair { // FinalityProviderStatus is the status of a finality provider // a FinalityProvider object has 4 states: // - Created - created and managed by finality provider client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, but not voting yet (No +// the consumer chain yet +// - Registered - created and registered to the consumer chain, but not voting yet (No // delegated stake) -// - Active - created and registered to Babylon with stake to vote -// - Inactive - created and registered to Babylon with no stake to vote. +// - Active - created and registered to the consumer chain with stake to vote +// - Inactive - created and registered to the consumer chain with no stake to vote. // Finality Provider was already active. // Valid State Transactions: // - Created -> Registered @@ -202,7 +220,7 @@ enum FinalityProviderStatus { // CREATED defines a finality provider that is awaiting registration CREATED = 0 [(gogoproto.enumvalue_customname) = "CREATED"]; // REGISTERED defines a finality provider that has been registered - // to Babylon but has no delegated stake + // to the consumer chain but has no delegated stake REGISTERED = 1 [(gogoproto.enumvalue_customname) = "REGISTERED"]; // ACTIVE defines a finality provider that is delegated to vote ACTIVE = 2 [(gogoproto.enumvalue_customname) = "ACTIVE"]; @@ -211,3 +229,19 @@ enum FinalityProviderStatus { // SLASHED defines a finality provider that has been slashed SLASHED = 4 [(gogoproto.enumvalue_customname) = "SLASHED"]; } + +message SignMessageFromChainKeyRequest { + // msg_to_sign the raw bytes to sign using the private key. + bytes msg_to_sign = 1; + // key_name is the identifier key in keyring + string key_name = 2; + // passphrase is used to encrypt the keys + string passphrase = 3; + // hd_path is the hd path for private key derivation + string hd_path = 4; +} + +// SignMessageFromChainKeyResponse contains the signed message from the chain keyring. +message SignMessageFromChainKeyResponse { + bytes signature = 1; +} \ No newline at end of file diff --git a/finality-provider/proto/finality_providers_grpc.pb.go b/finality-provider/proto/finality_providers_grpc.pb.go index e8a27819..e2d7bdca 100644 --- a/finality-provider/proto/finality_providers_grpc.pb.go +++ b/finality-provider/proto/finality_providers_grpc.pb.go @@ -25,6 +25,7 @@ const ( FinalityProviders_AddFinalitySignature_FullMethodName = "/proto.FinalityProviders/AddFinalitySignature" FinalityProviders_QueryFinalityProvider_FullMethodName = "/proto.FinalityProviders/QueryFinalityProvider" FinalityProviders_QueryFinalityProviderList_FullMethodName = "/proto.FinalityProviders/QueryFinalityProviderList" + FinalityProviders_SignMessageFromChainKey_FullMethodName = "/proto.FinalityProviders/SignMessageFromChainKey" ) // FinalityProvidersClient is the client API for FinalityProviders service. @@ -35,16 +36,18 @@ type FinalityProvidersClient interface { GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) // CreateFinalityProvider generates and saves a finality provider object CreateFinalityProvider(ctx context.Context, in *CreateFinalityProviderRequest, opts ...grpc.CallOption) (*CreateFinalityProviderResponse, error) - // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // RegisterFinalityProvider sends a transactions to the consumer chain to register a BTC // finality provider RegisterFinalityProvider(ctx context.Context, in *RegisterFinalityProviderRequest, opts ...grpc.CallOption) (*RegisterFinalityProviderResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality + // AddFinalitySignature sends a transactions to the consumer chain to add a Finality // signature for a block AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) // QueryFinalityProvider queries the finality provider QueryFinalityProvider(ctx context.Context, in *QueryFinalityProviderRequest, opts ...grpc.CallOption) (*QueryFinalityProviderResponse, error) // QueryFinalityProviderList queries a list of finality providers QueryFinalityProviderList(ctx context.Context, in *QueryFinalityProviderListRequest, opts ...grpc.CallOption) (*QueryFinalityProviderListResponse, error) + // SignMessageFromChainKey signs a message from the chain keyring. + SignMessageFromChainKey(ctx context.Context, in *SignMessageFromChainKeyRequest, opts ...grpc.CallOption) (*SignMessageFromChainKeyResponse, error) } type finalityProvidersClient struct { @@ -109,6 +112,15 @@ func (c *finalityProvidersClient) QueryFinalityProviderList(ctx context.Context, return out, nil } +func (c *finalityProvidersClient) SignMessageFromChainKey(ctx context.Context, in *SignMessageFromChainKeyRequest, opts ...grpc.CallOption) (*SignMessageFromChainKeyResponse, error) { + out := new(SignMessageFromChainKeyResponse) + err := c.cc.Invoke(ctx, FinalityProviders_SignMessageFromChainKey_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // FinalityProvidersServer is the server API for FinalityProviders service. // All implementations must embed UnimplementedFinalityProvidersServer // for forward compatibility @@ -117,16 +129,18 @@ type FinalityProvidersServer interface { GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) // CreateFinalityProvider generates and saves a finality provider object CreateFinalityProvider(context.Context, *CreateFinalityProviderRequest) (*CreateFinalityProviderResponse, error) - // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // RegisterFinalityProvider sends a transactions to the consumer chain to register a BTC // finality provider RegisterFinalityProvider(context.Context, *RegisterFinalityProviderRequest) (*RegisterFinalityProviderResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality + // AddFinalitySignature sends a transactions to the consumer chain to add a Finality // signature for a block AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) // QueryFinalityProvider queries the finality provider QueryFinalityProvider(context.Context, *QueryFinalityProviderRequest) (*QueryFinalityProviderResponse, error) // QueryFinalityProviderList queries a list of finality providers QueryFinalityProviderList(context.Context, *QueryFinalityProviderListRequest) (*QueryFinalityProviderListResponse, error) + // SignMessageFromChainKey signs a message from the chain keyring. + SignMessageFromChainKey(context.Context, *SignMessageFromChainKeyRequest) (*SignMessageFromChainKeyResponse, error) mustEmbedUnimplementedFinalityProvidersServer() } @@ -152,6 +166,9 @@ func (UnimplementedFinalityProvidersServer) QueryFinalityProvider(context.Contex func (UnimplementedFinalityProvidersServer) QueryFinalityProviderList(context.Context, *QueryFinalityProviderListRequest) (*QueryFinalityProviderListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryFinalityProviderList not implemented") } +func (UnimplementedFinalityProvidersServer) SignMessageFromChainKey(context.Context, *SignMessageFromChainKeyRequest) (*SignMessageFromChainKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignMessageFromChainKey not implemented") +} func (UnimplementedFinalityProvidersServer) mustEmbedUnimplementedFinalityProvidersServer() {} // UnsafeFinalityProvidersServer may be embedded to opt out of forward compatibility for this service. @@ -273,6 +290,24 @@ func _FinalityProviders_QueryFinalityProviderList_Handler(srv interface{}, ctx c return interceptor(ctx, in, info, handler) } +func _FinalityProviders_SignMessageFromChainKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignMessageFromChainKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).SignMessageFromChainKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_SignMessageFromChainKey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).SignMessageFromChainKey(ctx, req.(*SignMessageFromChainKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // FinalityProviders_ServiceDesc is the grpc.ServiceDesc for FinalityProviders service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -304,6 +339,10 @@ var FinalityProviders_ServiceDesc = grpc.ServiceDesc{ MethodName: "QueryFinalityProviderList", Handler: _FinalityProviders_QueryFinalityProviderList_Handler, }, + { + MethodName: "SignMessageFromChainKey", + Handler: _FinalityProviders_SignMessageFromChainKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "finality_providers.proto", diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 807e0675..65a2072d 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" "sync" + "time" sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" @@ -12,6 +13,8 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/lightningnetwork/lnd/kvdb" "go.uber.org/zap" "github.com/babylonchain/finality-provider/clientcontroller" @@ -19,10 +22,10 @@ import ( "github.com/babylonchain/finality-provider/eotsmanager/client" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/finality-provider/store" fpkr "github.com/babylonchain/finality-provider/keyring" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/types" - "github.com/babylonchain/finality-provider/util" ) type FinalityProviderApp struct { @@ -32,15 +35,9 @@ type FinalityProviderApp struct { wg sync.WaitGroup quit chan struct{} - sentWg sync.WaitGroup - sentQuit chan struct{} - - eventWg sync.WaitGroup - eventQuit chan struct{} - cc clientcontroller.ClientController kr keyring.Keyring - fps *fpstore.FinalityProviderStore + fps *store.FinalityProviderStore config *fpcfg.Config logger *zap.Logger input *strings.Reader @@ -48,43 +45,45 @@ type FinalityProviderApp struct { fpManager *FinalityProviderManager eotsManager eotsmanager.EOTSManager + metrics *metrics.FpMetrics + createFinalityProviderRequestChan chan *createFinalityProviderRequest registerFinalityProviderRequestChan chan *registerFinalityProviderRequest finalityProviderRegisteredEventChan chan *finalityProviderRegisteredEvent } func NewFinalityProviderAppFromConfig( - homePath string, - config *fpcfg.Config, + cfg *fpcfg.Config, + db kvdb.Backend, logger *zap.Logger, ) (*FinalityProviderApp, error) { - cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.BTCNetParams, logger) + cc, err := clientcontroller.NewClientController(cfg.ChainName, cfg.BabylonConfig, &cfg.BTCNetParams, logger) if err != nil { - return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) + return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", cfg.ChainName, err) } // if the EOTSManagerAddress is empty, run a local EOTS manager; // otherwise connect a remote one with a gRPC client - em, err := client.NewEOTSManagerGRpcClient(config.EOTSManagerAddress) + em, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) if err != nil { return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) } - logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", cfg.EOTSManagerAddress)) - return NewFinalityProviderApp(homePath, config, cc, em, logger) + return NewFinalityProviderApp(cfg, cc, em, db, logger) } func NewFinalityProviderApp( - homePath string, config *fpcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, + db kvdb.Backend, logger *zap.Logger, ) (*FinalityProviderApp, error) { - fpStore, err := initStore(homePath, config) + fpStore, err := store.NewFinalityProviderStore(db) if err != nil { - return nil, fmt.Errorf("failed to load store: %w", err) + return nil, fmt.Errorf("failed to initiate finality provider store: %w", err) } input := strings.NewReader("") @@ -98,7 +97,9 @@ func NewFinalityProviderApp( return nil, fmt.Errorf("failed to create keyring: %w", err) } - fpm, err := NewFinalityProviderManager(fpStore, config, cc, em, logger) + fpMetrics := metrics.NewFpMetrics() + + fpm, err := NewFinalityProviderManager(fpStore, config, cc, em, fpMetrics, logger) if err != nil { return nil, fmt.Errorf("failed to create finality-provider manager: %w", err) } @@ -112,29 +113,19 @@ func NewFinalityProviderApp( input: input, fpManager: fpm, eotsManager: em, + metrics: fpMetrics, quit: make(chan struct{}), - sentQuit: make(chan struct{}), - eventQuit: make(chan struct{}), createFinalityProviderRequestChan: make(chan *createFinalityProviderRequest), registerFinalityProviderRequestChan: make(chan *registerFinalityProviderRequest), finalityProviderRegisteredEventChan: make(chan *finalityProviderRegisteredEvent), }, nil } -func initStore(homePath string, cfg *fpcfg.Config) (*fpstore.FinalityProviderStore, error) { - // Create the directory that will store the data - if err := util.MakeDirectory(fpcfg.DataDir(homePath)); err != nil { - return nil, err - } - - return fpstore.NewFinalityProviderStore(fpcfg.DBPath(homePath), cfg.DatabaseConfig.Name, cfg.DatabaseConfig.Backend) -} - func (app *FinalityProviderApp) GetConfig() *fpcfg.Config { return app.config } -func (app *FinalityProviderApp) GetFinalityProviderStore() *fpstore.FinalityProviderStore { +func (app *FinalityProviderApp) GetFinalityProviderStore() *store.FinalityProviderStore { return app.fps } @@ -150,6 +141,14 @@ func (app *FinalityProviderApp) ListFinalityProviderInstances() []*FinalityProvi return app.fpManager.ListFinalityProviderInstances() } +func (app *FinalityProviderApp) ListAllFinalityProvidersInfo() ([]*proto.FinalityProviderInfo, error) { + return app.fpManager.AllFinalityProviders() +} + +func (app *FinalityProviderApp) GetFinalityProviderInfo(fpPk *bbntypes.BIP340PubKey) (*proto.FinalityProviderInfo, error) { + return app.fpManager.FinalityProviderInfo(fpPk) +} + // GetFinalityProviderInstance returns the finality-provider instance with the given Babylon public key func (app *FinalityProviderApp) GetFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) (*FinalityProviderInstance, error) { return app.fpManager.GetFinalityProviderInstance(fpPk) @@ -161,7 +160,7 @@ func (app *FinalityProviderApp) RegisterFinalityProvider(fpPkStr string) (*Regis return nil, err } - fp, err := app.fps.GetStoreFinalityProvider(fpPk.MustMarshal()) + fp, err := app.fps.GetFinalityProvider(fpPk.MustToBTCPK()) if err != nil { return nil, err } @@ -176,22 +175,18 @@ func (app *FinalityProviderApp) RegisterFinalityProvider(fpPkStr string) (*Regis } pop := &bstypes.ProofOfPossession{ - BabylonSig: fp.Pop.BabylonSig, + BabylonSig: fp.Pop.ChainSig, BtcSig: btcSig.MustMarshal(), BtcSigType: bstypes.BTCSigType_BIP340, } - commissionRate, err := sdkmath.LegacyNewDecFromStr(fp.Commission) - if err != nil { - return nil, err - } - request := ®isterFinalityProviderRequest{ - bbnPubKey: fp.GetBabylonPK(), - btcPubKey: fp.MustGetBIP340BTCPK(), + bbnPubKey: fp.ChainPk, + btcPubKey: bbntypes.NewBIP340PubKeyFromBTCPK(fp.BtcPk), pop: pop, description: fp.Description, - commission: &commissionRate, + commission: fp.Commission, + masterPubRand: fp.MasterPubRand, errResponse: make(chan error, 1), successResponse: make(chan *RegisterFinalityProviderResponse, 1), } @@ -228,17 +223,63 @@ func (app *FinalityProviderApp) getFpPrivKey(fpPk []byte) (*btcec.PrivateKey, er return record.PrivKey, nil } +// SyncFinalityProviderStatus syncs the status of the finality-providers +func (app *FinalityProviderApp) SyncFinalityProviderStatus() error { + latestBlock, err := app.cc.QueryBestBlock() + if err != nil { + return err + } + + fps, err := app.fps.GetAllStoredFinalityProviders() + if err != nil { + return err + } + + for _, fp := range fps { + vp, err := app.cc.QueryFinalityProviderVotingPower(fp.BtcPk, latestBlock.Height) + if err != nil { + // if error occured then the finality-provider is not registered in the Babylon chain yet + continue + } + + if vp > 0 { + // voting power > 0 then set the status to ACTIVE + err = app.fps.SetFpStatus(fp.BtcPk, proto.FinalityProviderStatus_ACTIVE) + if err != nil { + return err + } + } else if vp == 0 { + // voting power == 0 then set status depending on previous status + switch fp.Status { + case proto.FinalityProviderStatus_CREATED: + // previous status is CREATED then set to REGISTERED + err = app.fps.SetFpStatus(fp.BtcPk, proto.FinalityProviderStatus_REGISTERED) + if err != nil { + return err + } + case proto.FinalityProviderStatus_ACTIVE: + // previous status is ACTIVE then set to INACTIVE + err = app.fps.SetFpStatus(fp.BtcPk, proto.FinalityProviderStatus_INACTIVE) + if err != nil { + return err + } + } + } + } + + return nil +} + // Start starts only the finality-provider daemon without any finality-provider instances func (app *FinalityProviderApp) Start() error { var startErr error app.startOnce.Do(func() { app.logger.Info("Starting FinalityProviderApp") - app.eventWg.Add(1) + app.wg.Add(3) go app.eventLoop() - - app.sentWg.Add(1) go app.registrationLoop() + go app.metricsUpdateLoop() }) return startErr @@ -260,21 +301,6 @@ func (app *FinalityProviderApp) Stop() error { return } - app.logger.Debug("Sent to Babylon loop stopped") - close(app.sentQuit) - app.sentWg.Wait() - - app.logger.Debug("Stopping main eventLoop") - close(app.eventQuit) - app.eventWg.Wait() - - // Closing db as last to avoid anybody to write do db - app.logger.Debug("Stopping data store") - if err := app.fps.Close(); err != nil { - stopErr = err - return - } - app.logger.Debug("Stopping EOTS manager") if err := app.eotsManager.Close(); err != nil { stopErr = err @@ -289,7 +315,7 @@ func (app *FinalityProviderApp) Stop() error { func (app *FinalityProviderApp) CreateFinalityProvider( keyName, chainID, passPhrase, hdPath string, - description []byte, + description *stakingtypes.Description, commission *sdkmath.LegacyDec, ) (*CreateFinalityProviderResult, error) { @@ -311,7 +337,7 @@ func (app *FinalityProviderApp) CreateFinalityProvider( return nil, err case successResponse := <-req.successResponse: return &CreateFinalityProviderResult{ - StoreFp: successResponse.StoreFp, + FpInfo: successResponse.FpInfo, }, nil case <-app.quit: return nil, fmt.Errorf("finality-provider app is shutting down") @@ -319,24 +345,65 @@ func (app *FinalityProviderApp) CreateFinalityProvider( } func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createFinalityProviderRequest) (*createFinalityProviderResponse, error) { - // 1. check if the chain key exists - kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) + storedFp, err := app.StoreFinalityProvider(req.keyName, req.passPhrase, req.hdPath, req.chainID, req.description, req.commission) if err != nil { return nil, err } - chainSk, err := kr.GetChainPrivKey(req.passPhrase) + + return &createFinalityProviderResponse{ + FpInfo: storedFp.ToFinalityProviderInfo(), + }, nil +} + +// SignRawMsg loads the keyring private key and signs a message. +func (app *FinalityProviderApp) SignRawMsg( + keyName, passPhrase, hdPath string, + rawMsgToSign []byte, +) ([]byte, error) { + _, chainSk, err := app.loadChainKeyring(keyName, passPhrase, hdPath) + if err != nil { + return nil, err + } + + return chainSk.Sign(rawMsgToSign) +} + +// loadChainKeyring checks the keyring by loading or creating a chain key. +func (app *FinalityProviderApp) loadChainKeyring( + keyName, passPhrase, hdPath string, +) (*fpkr.ChainKeyringController, *secp256k1.PrivKey, error) { + kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, keyName, app.input) + if err != nil { + return nil, nil, err + } + chainSk, err := kr.GetChainPrivKey(passPhrase) if err != nil { // the chain key does not exist, should create the chain key first - keyInfo, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + keyInfo, err := kr.CreateChainKey(passPhrase, hdPath, "") if err != nil { - return nil, fmt.Errorf("failed to create chain key %s: %w", req.keyName, err) + return nil, nil, fmt.Errorf("failed to create chain key %s: %w", keyName, err) } chainSk = &secp256k1.PrivKey{Key: keyInfo.PrivateKey.Serialize()} } + + return kr, chainSk, nil +} + +// StoreFinalityProvider stores a new finality provider in the fp store. +func (app *FinalityProviderApp) StoreFinalityProvider( + keyName, passPhrase, hdPath, chainID string, + description *stakingtypes.Description, + commission *sdkmath.LegacyDec, +) (*store.StoredFinalityProvider, error) { + // 1. check if the chain key exists + kr, chainSk, err := app.loadChainKeyring(keyName, passPhrase, hdPath) + if err != nil { + return nil, err + } chainPk := &secp256k1.PubKey{Key: chainSk.PubKey().Bytes()} // 2. create EOTS key - fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) + fpPkBytes, err := app.eotsManager.CreateKey(keyName, passPhrase, hdPath) if err != nil { return nil, err } @@ -344,35 +411,43 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF if err != nil { return nil, err } - fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), req.passPhrase) + fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), passPhrase) if err != nil { return nil, fmt.Errorf("failed to get finality-provider record: %w", err) } // 3. create proof-of-possession - pop, err := kr.CreatePop(fpRecord.PrivKey, req.passPhrase) + pop, err := kr.CreatePop(fpRecord.PrivKey, passPhrase) if err != nil { - return nil, fmt.Errorf("failed to create proof-of-possession of the finality-provider: %w", err) + return nil, fmt.Errorf("failed to create proof-of-possession of the finality provider: %w", err) } - fp := fpstore.NewStoreFinalityProvider(chainPk, fpPk, req.keyName, req.chainID, pop, req.description, req.commission) + // 4. Create derive master public randomness + _, mpr, err := fpkr.GenerateMasterRandPair(fpRecord.PrivKey.Serialize(), types.MarshalChainID(chainID)) + if err != nil { + return nil, fmt.Errorf("failed to get master public randomness of the finality provider: %w", err) + } - if err := app.fps.SaveFinalityProvider(fp); err != nil { + if err := app.fps.CreateFinalityProvider(chainPk, fpPk.MustToBTCPK(), description, commission, mpr.MarshalBase58(), keyName, chainID, pop.BabylonSig, pop.BtcSig); err != nil { return nil, fmt.Errorf("failed to save finality-provider: %w", err) } + app.fpManager.metrics.RecordFpStatus(fpPk.MarshalHex(), proto.FinalityProviderStatus_CREATED) app.logger.Info("successfully created a finality-provider", zap.String("btc_pk", fpPk.MarshalHex()), zap.String("chain_pk", chainPk.String()), - zap.String("key_name", req.keyName), + zap.String("key_name", keyName), ) - return &createFinalityProviderResponse{ - StoreFp: fp, - }, nil + storedFp, err := app.fps.GetFinalityProvider(fpPk.MustToBTCPK()) + if err != nil { + return nil, err + } + + return storedFp, nil } -func CreateChainKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.ChainKeyInfo, error) { +func CreateChainKey(keyringDir, chainID, keyName, backend, passphrase, hdPath, mnemonic string) (*types.ChainKeyInfo, error) { sdkCtx, err := fpkr.CreateClientCtx( keyringDir, chainID, ) @@ -389,12 +464,12 @@ func CreateChainKey(keyringDir, chainID, keyName, backend, passphrase, hdPath st return nil, err } - return krController.CreateChainKey(passphrase, hdPath) + return krController.CreateChainKey(passphrase, hdPath, mnemonic) } // main event loop for the finality-provider app func (app *FinalityProviderApp) eventLoop() { - defer app.eventWg.Done() + defer app.wg.Done() for { select { @@ -405,36 +480,35 @@ func (app *FinalityProviderApp) eventLoop() { continue } - req.successResponse <- &createFinalityProviderResponse{StoreFp: res.StoreFp} + req.successResponse <- &createFinalityProviderResponse{FpInfo: res.FpInfo} case ev := <-app.finalityProviderRegisteredEventChan: - fpStored, err := app.fps.GetStoreFinalityProvider(ev.btcPubKey.MustMarshal()) - if err != nil { - // we always check if the finality-provider is in the DB before sending the registration request - app.logger.Fatal( - "registered finality-provider not found in DB", + btcPK := ev.btcPubKey.MustToBTCPK() + // set the finality provider's registered epoch + if err := app.fps.SetFpRegisteredEpoch(btcPK, ev.registeredEpoch); err != nil { + app.logger.Fatal("failed to set the finality provider's registered epoch", zap.String("pk", ev.btcPubKey.MarshalHex()), zap.Error(err), ) } - // change the status of the finality-provider to registered - err = app.fps.SetFinalityProviderStatus(fpStored, proto.FinalityProviderStatus_REGISTERED) - if err != nil { - app.logger.Fatal("failed to set finality-provider status to REGISTERED", + if err := app.fps.SetFpStatus(btcPK, proto.FinalityProviderStatus_REGISTERED); err != nil { + app.logger.Fatal("failed to set the finalityprovider's status to REGISTERED", zap.String("pk", ev.btcPubKey.MarshalHex()), zap.Error(err), ) } + app.fpManager.metrics.RecordFpStatus(ev.btcPubKey.MarshalHex(), proto.FinalityProviderStatus_REGISTERED) // return to the caller ev.successResponse <- &RegisterFinalityProviderResponse{ - bbnPubKey: fpStored.GetBabylonPK(), - btcPubKey: fpStored.MustGetBIP340BTCPK(), - TxHash: ev.txHash, + bbnPubKey: ev.bbnPubKey, + btcPubKey: ev.btcPubKey, + TxHash: ev.txHash, + RegisteredEpoch: ev.registeredEpoch, } - case <-app.eventQuit: + case <-app.quit: app.logger.Debug("exiting main event loop") return } @@ -442,7 +516,7 @@ func (app *FinalityProviderApp) eventLoop() { } func (app *FinalityProviderApp) registrationLoop() { - defer app.sentWg.Done() + defer app.wg.Done() for { select { case req := <-app.registerFinalityProviderRequestChan: @@ -455,12 +529,18 @@ func (app *FinalityProviderApp) registrationLoop() { continue } - res, err := app.cc.RegisterFinalityProvider( + desBytes, err := req.description.Marshal() + if err != nil { + req.errResponse <- err + continue + } + res, registeredEpoch, err := app.cc.RegisterFinalityProvider( req.bbnPubKey.Key, req.btcPubKey.MustToBTCPK(), popBytes, req.commission, - req.description, + desBytes, + req.masterPubRand, ) if err != nil { @@ -481,16 +561,42 @@ func (app *FinalityProviderApp) registrationLoop() { ) app.finalityProviderRegisteredEventChan <- &finalityProviderRegisteredEvent{ - btcPubKey: req.btcPubKey, - bbnPubKey: req.bbnPubKey, - txHash: res.TxHash, + btcPubKey: req.btcPubKey, + bbnPubKey: req.bbnPubKey, + txHash: res.TxHash, + registeredEpoch: registeredEpoch, // pass the channel to the event so that we can send the response to the user which requested // the registration successResponse: req.successResponse, } - case <-app.sentQuit: + case <-app.quit: app.logger.Debug("exiting registration loop") return } } } + +func (app *FinalityProviderApp) metricsUpdateLoop() { + defer app.wg.Done() + + interval := app.config.Metrics.UpdateInterval + app.logger.Info("starting metrics update loop", + zap.Float64("interval seconds", interval.Seconds())) + updateTicker := time.NewTicker(interval) + + for { + select { + case <-updateTicker.C: + fps, err := app.fps.GetAllStoredFinalityProviders() + if err != nil { + app.logger.Error("failed to get finality-providers from the store", zap.Error(err)) + continue + } + app.metrics.UpdateFpMetrics(fps) + case <-app.quit: + updateTicker.Stop() + app.logger.Info("exiting metrics update loop") + return + } + } +} diff --git a/finality-provider/service/app_test.go b/finality-provider/service/app_test.go index 74d2ca01..69ebd01c 100644 --- a/finality-provider/service/app_test.go +++ b/finality-provider/service/app_test.go @@ -13,6 +13,8 @@ import ( "go.uber.org/zap" "github.com/babylonchain/finality-provider/eotsmanager" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" "github.com/babylonchain/finality-provider/finality-provider/service" "github.com/babylonchain/finality-provider/testutil" @@ -32,10 +34,13 @@ func FuzzRegisterFinalityProvider(f *testing.F) { logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") - eotsCfg := testutil.GenEOTSConfig(r, t) - em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + eotsCfg := eotscfg.DefaultConfigWithHomePath(eotsHomeDir) + dbBackend, err := eotsCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg.KeyringBackend, dbBackend, logger) require.NoError(t, err) defer func() { + dbBackend.Close() err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) }() @@ -47,15 +52,20 @@ func FuzzRegisterFinalityProvider(f *testing.F) { mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()).Return(uint64(0), nil).AnyTimes() + mockClientController.EXPECT().QueryLastFinalizedEpoch().Return(uint64(0), nil).AnyTimes() // Create randomized config fpHomeDir := filepath.Join(t.TempDir(), "fp-home") - fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg := config.DefaultConfigWithHome(fpHomeDir) fpCfg.PollerConfig.AutoChainScanningMode = false fpCfg.PollerConfig.StaticChainScanningStartHeight = randomStartingHeight - app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, mockClientController, em, logger) + fpdb, err := fpCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + app, err := service.NewFinalityProviderApp(&fpCfg, mockClientController, em, fpdb, logger) require.NoError(t, err) defer func() { + err = fpdb.Close() + require.NoError(t, err) err = os.RemoveAll(fpHomeDir) require.NoError(t, err) }() @@ -73,33 +83,45 @@ func FuzzRegisterFinalityProvider(f *testing.F) { err = btcSig.Unmarshal(fp.Pop.BtcSig) require.NoError(t, err) pop := &bstypes.ProofOfPossession{ - BabylonSig: fp.Pop.BabylonSig, + BabylonSig: fp.Pop.ChainSig, BtcSig: btcSig.MustMarshal(), BtcSigType: bstypes.BTCSigType_BIP340, } popBytes, err := pop.Marshal() require.NoError(t, err) + fpInfo, err := app.GetFinalityProviderInfo(fp.GetBIP340BTCPK()) + require.NoError(t, err) + require.Equal(t, proto.FinalityProviderStatus_name[0], fpInfo.Status) + require.Equal(t, false, fpInfo.IsRunning) + fpListInfo, err := app.ListAllFinalityProvidersInfo() + require.NoError(t, err) + require.Equal(t, fpInfo.BtcPkHex, fpListInfo[0].BtcPkHex) txHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). RegisterFinalityProvider( - fp.GetBabylonPK().Key, - fp.MustGetBIP340BTCPK().MustToBTCPK(), + fp.ChainPk.Key, + fp.BtcPk, popBytes, testutil.ZeroCommissionRate(), - testutil.EmptyDescription(), - ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() + gomock.Any(), + fp.MasterPubRand, + ).Return(&types.TxResponse{TxHash: txHash}, uint64(0), nil).AnyTimes() - res, err := app.RegisterFinalityProvider(fp.MustGetBIP340BTCPK().MarshalHex()) + res, err := app.RegisterFinalityProvider(fp.GetBIP340BTCPK().MarshalHex()) require.NoError(t, err) require.Equal(t, txHash, res.TxHash) - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() - err = app.StartHandlingFinalityProvider(fp.MustGetBIP340BTCPK(), passphrase) + err = app.StartHandlingFinalityProvider(fp.GetBIP340BTCPK(), passphrase) + require.NoError(t, err) + + fpAfterReg, err := app.GetFinalityProviderInstance(fp.GetBIP340BTCPK()) require.NoError(t, err) + require.Equal(t, proto.FinalityProviderStatus_REGISTERED, fpAfterReg.GetStoreFinalityProvider().Status) - fpAfterReg, err := app.GetFinalityProviderInstance(fp.MustGetBIP340BTCPK()) + fpInfo, err = app.GetFinalityProviderInfo(fp.GetBIP340BTCPK()) require.NoError(t, err) - require.Equal(t, fpAfterReg.GetStoreFinalityProvider().Status, proto.FinalityProviderStatus_REGISTERED) + require.Equal(t, proto.FinalityProviderStatus_name[1], fpInfo.Status) + require.Equal(t, true, fpInfo.IsRunning) }) } diff --git a/finality-provider/service/chain_poller.go b/finality-provider/service/chain_poller.go index 9dcba37b..e7fe1c40 100644 --- a/finality-provider/service/chain_poller.go +++ b/finality-provider/service/chain_poller.go @@ -11,6 +11,7 @@ import ( "github.com/babylonchain/finality-provider/clientcontroller" cfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/types" ) @@ -43,6 +44,7 @@ type ChainPoller struct { cc clientcontroller.ClientController cfg *cfg.ChainPollerConfig + metrics *metrics.FpMetrics blockInfoChan chan *types.BlockInfo skipHeightChan chan *skipHeightRequest nextHeight uint64 @@ -53,12 +55,14 @@ func NewChainPoller( logger *zap.Logger, cfg *cfg.ChainPollerConfig, cc clientcontroller.ClientController, + metrics *metrics.FpMetrics, ) *ChainPoller { return &ChainPoller{ isStarted: atomic.NewBool(false), logger: logger, cfg: cfg, cc: cc, + metrics: metrics, blockInfoChan: make(chan *types.BlockInfo, cfg.BufferSize), skipHeightChan: make(chan *skipHeightRequest), quit: make(chan struct{}), @@ -83,6 +87,7 @@ func (cp *ChainPoller) Start(startHeight uint64) error { go cp.pollChain() + cp.metrics.RecordPollerStartingHeight(startHeight) cp.logger.Info("the chain poller is successfully started") return nil @@ -245,6 +250,7 @@ func (cp *ChainPoller) pollChain() { // notification about data cp.nextHeight = blockToRetrieve + 1 failedCycles = 0 + cp.metrics.RecordLastPolledHeight(block.Height) cp.logger.Info("the poller retrieved the block from the consumer chain", zap.Uint64("height", block.Height)) diff --git a/finality-provider/service/chain_poller_test.go b/finality-provider/service/chain_poller_test.go index 8c5fdc90..4e899ed2 100644 --- a/finality-provider/service/chain_poller_test.go +++ b/finality-provider/service/chain_poller_test.go @@ -12,6 +12,7 @@ import ( fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/testutil" "github.com/babylonchain/finality-provider/testutil/mocks" "github.com/babylonchain/finality-provider/types" @@ -45,9 +46,11 @@ func FuzzChainPoller_Start(f *testing.F) { mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() } + // TODO: use mock metrics + m := metrics.NewFpMetrics() pollerCfg := fpcfg.DefaultChainPollerConfig() pollerCfg.PollInterval = 10 * time.Millisecond - poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController, m) err := poller.Start(startHeight) require.NoError(t, err) defer func() { @@ -94,9 +97,11 @@ func FuzzChainPoller_SkipHeight(f *testing.F) { mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() } + // TODO: use mock metrics + m := metrics.NewFpMetrics() pollerCfg := fpcfg.DefaultChainPollerConfig() pollerCfg.PollInterval = 1 * time.Second - poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController, m) // should expect error if the poller is not started err := poller.SkipToHeight(skipHeight) require.Error(t, err) diff --git a/finality-provider/service/client/rpcclient.go b/finality-provider/service/client/rpcclient.go index 13e2677e..dffcd75d 100644 --- a/finality-provider/service/client/rpcclient.go +++ b/finality-provider/service/client/rpcclient.go @@ -120,3 +120,17 @@ func (c *FinalityProviderServiceGRpcClient) QueryFinalityProviderInfo(ctx contex return res, nil } + +func (c *FinalityProviderServiceGRpcClient) SignMessageFromChainKey( + ctx context.Context, + keyName, passphrase, hdPath string, + rawMsgToSign []byte, +) (*proto.SignMessageFromChainKeyResponse, error) { + req := &proto.SignMessageFromChainKeyRequest{ + MsgToSign: rawMsgToSign, + KeyName: keyName, + Passphrase: passphrase, + HdPath: hdPath, + } + return c.client.SignMessageFromChainKey(ctx, req) +} diff --git a/finality-provider/service/fastsync.go b/finality-provider/service/fastsync.go index b0d16b9a..4a033378 100644 --- a/finality-provider/service/fastsync.go +++ b/finality-provider/service/fastsync.go @@ -59,16 +59,9 @@ func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*Fa return nil, err } if !hasVp { + fp.metrics.IncrementFpTotalBlocksWithoutVotingPower(fp.GetBtcPkHex()) continue } - // check whether the randomness has been committed - hasRand, err := fp.hasRandomness(b) - if err != nil { - return nil, err - } - if !hasRand { - break - } // all good, add the block for catching up catchUpBlocks = append(catchUpBlocks, b) } @@ -83,6 +76,7 @@ func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*Fa if err != nil { return nil, err } + fp.metrics.AddToFpTotalVotedBlocks(fp.GetBtcPkHex(), float64(len(catchUpBlocks))) responses = append(responses, res) diff --git a/finality-provider/service/fastsync_test.go b/finality-provider/service/fastsync_test.go index bd4940ee..52c0ebbb 100644 --- a/finality-provider/service/fastsync_test.go +++ b/finality-provider/service/fastsync_test.go @@ -4,7 +4,6 @@ import ( "math/rand" "testing" - "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -12,31 +11,28 @@ import ( "github.com/babylonchain/finality-provider/types" ) -// FuzzFastSync_SufficientRandomness tests a case where we have sufficient -// randomness and voting power when the finality provider enters fast-sync -// it is expected that the finality provider could catch up to the current +// FuzzFastSync tests a case where we have voting power when the finality +// provider enters fast-sync. +// It is expected that the finality provider could catch up to the current // height through fast-sync -func FuzzFastSync_SufficientRandomness(f *testing.F) { +func FuzzFastSync(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) + randomRegiteredEpoch := uint64(r.Int63n(10) + 1) randomStartingHeight := uint64(r.Int63n(100) + 1) finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return(nil, nil).AnyTimes() - _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + // mock finalised BTC timestamped + mockClientController.EXPECT().QueryLastFinalizedEpoch().Return(randomRegiteredEpoch, nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight, randomRegiteredEpoch) defer cleanUp() - mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + // mock voting power + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.GetBtcPk(), gomock.Any()). Return(uint64(1), nil).AnyTimes() - // the last committed height is higher than the current height - // to make sure the randomness is sufficient - lastCommittedHeight := randomStartingHeight + testutil.TestPubRandNum - lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) - lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) expectedTxHash := testutil.GenRandomHexStr(r, 32) @@ -44,7 +40,7 @@ func FuzzFastSync_SufficientRandomness(f *testing.F) { mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return([]*types.BlockInfo{finalizedBlock}, nil).AnyTimes() mockClientController.EXPECT().QueryBlocks(finalizedHeight+1, currentHeight, uint64(10)). Return(catchUpBlocks, nil) - mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.MustGetBtcPk(), catchUpBlocks, gomock.Any()). + mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.GetBtcPk(), catchUpBlocks, gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() result, err := fpIns.FastSync(finalizedHeight+1, currentHeight) require.NoError(t, err) @@ -54,45 +50,3 @@ func FuzzFastSync_SufficientRandomness(f *testing.F) { require.Equal(t, currentHeight, fpIns.GetLastProcessedHeight()) }) } - -// FuzzFastSync_SufficientRandomness tests a case where we have insufficient -// randomness but with voting power when the finality provider enters fast-sync -// it is expected that the finality provider could catch up to the last -// committed height -func FuzzFastSync_NoRandomness(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - randomStartingHeight := uint64(r.Int63n(100) + 1) - finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return(nil, nil).AnyTimes() - _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) - defer cleanUp() - - mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). - Return(uint64(1), nil).AnyTimes() - // the last committed height is set in [finalizedHeight+1, currentHeight] - lastCommittedHeight := uint64(rand.Intn(int(currentHeight)-int(finalizedHeight))) + finalizedHeight + 1 - lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) - lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() - - catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) - expectedTxHash := testutil.GenRandomHexStr(r, 32) - finalizedBlock := &types.BlockInfo{Height: finalizedHeight, Hash: testutil.GenRandomByteArray(r, 32)} - mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return([]*types.BlockInfo{finalizedBlock}, nil).AnyTimes() - mockClientController.EXPECT().QueryBlocks(finalizedHeight+1, currentHeight, uint64(10)). - Return(catchUpBlocks, nil) - mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.MustGetBtcPk(), catchUpBlocks[:lastCommittedHeight-finalizedHeight], gomock.Any()). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - result, err := fpIns.FastSync(finalizedHeight+1, currentHeight) - require.NoError(t, err) - require.NotNil(t, result) - require.Equal(t, expectedTxHash, result.Responses[0].TxHash) - require.Equal(t, lastCommittedHeight, fpIns.GetLastVotedHeight()) - require.Equal(t, lastCommittedHeight, fpIns.GetLastProcessedHeight()) - }) -} diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go index 4864c08a..b5f80695 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -21,21 +21,23 @@ import ( "github.com/babylonchain/finality-provider/eotsmanager" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/types" ) type FinalityProviderInstance struct { - bbnPk *secp256k1.PubKey - btcPk *bbntypes.BIP340PubKey + chainPk *secp256k1.PubKey + btcPk *bbntypes.BIP340PubKey state *fpState cfg *fpcfg.Config - logger *zap.Logger - em eotsmanager.EOTSManager - cc clientcontroller.ClientController - poller *ChainPoller + logger *zap.Logger + em eotsmanager.EOTSManager + cc clientcontroller.ClientController + poller *ChainPoller + metrics *metrics.FpMetrics // passphrase is used to unlock private keys passphrase string @@ -56,26 +58,36 @@ type FinalityProviderInstance struct { func NewFinalityProviderInstance( fpPk *bbntypes.BIP340PubKey, cfg *fpcfg.Config, - s *fpstore.FinalityProviderStore, + s *store.FinalityProviderStore, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, + metrics *metrics.FpMetrics, passphrase string, errChan chan<- *CriticalError, logger *zap.Logger, ) (*FinalityProviderInstance, error) { - sfp, err := s.GetStoreFinalityProvider(fpPk.MustMarshal()) + sfp, err := s.GetFinalityProvider(fpPk.MustToBTCPK()) if err != nil { - return nil, fmt.Errorf("failed to retrive the finality-provider %s from DB: %w", sfp.GetBabylonPkHexString(), err) + return nil, fmt.Errorf("failed to retrive the finality-provider %s from DB: %w", fpPk.MarshalHex(), err) } // ensure the finality-provider has been registered if sfp.Status < proto.FinalityProviderStatus_REGISTERED { - return nil, fmt.Errorf("the finality-provider %s has not been registered", sfp.KeyName) + return nil, fmt.Errorf("the finality provider %s has not been registered", sfp.KeyName) + } + + registeredEpoch := sfp.RegisteredEpoch + lastFinalizedEpoch, err := cc.QueryLastFinalizedEpoch() + if err != nil { + return nil, fmt.Errorf("failed to get the last finalized epoch: %v", err) + } + if lastFinalizedEpoch < registeredEpoch { + return nil, fmt.Errorf("the registered epoch %d of the finality provider %s is not BTC timestamped yet (last finalized epoch: %d)", registeredEpoch, sfp.KeyName, lastFinalizedEpoch) } return &FinalityProviderInstance{ - btcPk: sfp.MustGetBIP340BTCPK(), - bbnPk: sfp.GetBabylonPK(), + btcPk: bbntypes.NewBIP340PubKeyFromBTCPK(sfp.BtcPk), + chainPk: sfp.ChainPk, state: &fpState{ fp: sfp, s: s, @@ -89,6 +101,7 @@ func NewFinalityProviderInstance( passphrase: passphrase, em: em, cc: cc, + metrics: metrics, }, nil } @@ -104,10 +117,10 @@ func (fp *FinalityProviderInstance) Start() error { return fmt.Errorf("failed to bootstrap the finality-provider %s: %w", fp.GetBtcPkHex(), err) } - fp.logger.Info("the finality-provider %s has been bootstrapped", + fp.logger.Info("the finality-provider has been bootstrapped", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", startHeight)) - poller := NewChainPoller(fp.logger, fp.cfg.PollerConfig, fp.cc) + poller := NewChainPoller(fp.logger, fp.cfg.PollerConfig, fp.cc, fp.metrics) if err := poller.Start(startHeight + 1); err != nil { return fmt.Errorf("failed to start the poller: %w", err) @@ -122,8 +135,6 @@ func (fp *FinalityProviderInstance) Start() error { fp.wg.Add(1) go fp.finalitySigSubmissionLoop() fp.wg.Add(1) - go fp.randomnessCommitmentLoop() - fp.wg.Add(1) go fp.checkLaggingLoop() return nil @@ -199,20 +210,15 @@ func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { // the finality provider does not have voting power // and it will never will at this block fp.MustSetLastProcessedHeight(b.Height) + fp.metrics.IncrementFpTotalBlocksWithoutVotingPower(fp.GetBtcPkHex()) continue } - // check whether the randomness has been committed - // we should stall here until we have randomness committed at this - // height, otherwise, we might miss blocks - if err := fp.retryCheckRandomnessUntilBlockFinalized(b); err != nil { - fp.reportCriticalErr(err) - break - } // use the copy of the block to avoid the impact to other receivers nextBlock := *b res, err := fp.retrySubmitFinalitySignatureUntilBlockFinalized(&nextBlock) if err != nil { + fp.metrics.IncrementFpTotalFailedVotes(fp.GetBtcPkHex()) fp.reportCriticalErr(err) continue } @@ -270,41 +276,6 @@ func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { } } -func (fp *FinalityProviderInstance) randomnessCommitmentLoop() { - defer fp.wg.Done() - - commitRandTicker := time.NewTicker(fp.cfg.RandomnessCommitInterval) - defer commitRandTicker.Stop() - - for { - select { - case <-commitRandTicker.C: - tipBlock, err := fp.getLatestBlockWithRetry() - if err != nil { - fp.reportCriticalErr(err) - continue - } - txRes, err := fp.retryCommitPubRandUntilBlockFinalized(tipBlock) - if err != nil { - fp.reportCriticalErr(err) - continue - } - // txRes could be nil if no need to commit more randomness - if txRes != nil { - fp.logger.Info( - "successfully committed public randomness to the consumer chain", - zap.String("pk", fp.GetBtcPkHex()), - zap.String("tx_hash", txRes.TxHash), - ) - } - - case <-fp.quit: - fp.logger.Info("the randomness commitment loop is closing") - return - } - } -} - func (fp *FinalityProviderInstance) checkLaggingLoop() { defer fp.wg.Done() @@ -399,6 +370,7 @@ func (fp *FinalityProviderInstance) hasProcessed(b *types.BlockInfo) bool { return false } +// hasVotingPower checks whether the finality provider has voting power for the given block func (fp *FinalityProviderInstance) hasVotingPower(b *types.BlockInfo) (bool, error) { power, err := fp.GetVotingPowerWithRetry(b.Height) if err != nil { @@ -406,7 +378,7 @@ func (fp *FinalityProviderInstance) hasVotingPower(b *types.BlockInfo) (bool, er } if power == 0 { fp.logger.Debug( - "the finality-provider does not have voting power", + "the finality provider does not have voting power", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), ) @@ -417,24 +389,6 @@ func (fp *FinalityProviderInstance) hasVotingPower(b *types.BlockInfo) (bool, er return true, nil } -func (fp *FinalityProviderInstance) hasRandomness(b *types.BlockInfo) (bool, error) { - lastCommittedHeight, err := fp.GetLastCommittedHeight() - if err != nil { - return false, err - } - if b.Height > lastCommittedHeight { - fp.logger.Debug( - "the finality provider has not committed public randomness for the height", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("block_height", b.Height), - zap.Uint64("last_committed_height", lastCommittedHeight), - ) - return false, nil - } - - return true, nil -} - func (fp *FinalityProviderInstance) reportCriticalErr(err error) { fp.criticalErrChan <- &CriticalError{ err: err, @@ -447,65 +401,6 @@ func (fp *FinalityProviderInstance) checkLagging(currentBlock *types.BlockInfo) return currentBlock.Height >= fp.GetLastProcessedHeight()+fp.cfg.FastSyncGap } -// retryQueryingRandomnessUntilBlockFinalized periodically checks whether -// the randomness has been committed to the target block until the block is -// finalized -// error will be returned if maximum retries have been reached or the query to -// the consumer chain fails -func (fp *FinalityProviderInstance) retryCheckRandomnessUntilBlockFinalized(targetBlock *types.BlockInfo) error { - var failedCycles uint32 - - // we break the for loop if the block is finalized or the randomness is successfully committed - // error will be returned if maximum retries have been reached or the query to the consumer chain fails - for { - fp.logger.Debug( - "checking randomness", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("target_block_height", targetBlock.Height), - ) - hasRand, err := fp.hasRandomness(targetBlock) - if err != nil { - fp.logger.Debug( - "failed to check last committed randomness", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint32("current_failures", failedCycles), - zap.Uint64("target_block_height", targetBlock.Height), - zap.Error(err), - ) - - failedCycles += 1 - if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { - return fmt.Errorf("reached max failed cycles with err: %w", err) - } - } else if hasRand { - // the randomness has been successfully committed - return nil - } - select { - case <-time.After(fp.cfg.SubmissionRetryInterval): - // periodically query the index block to be later checked whether it is Finalized - finalized, err := fp.checkBlockFinalization(targetBlock.Height) - if err != nil { - return fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) - } - if finalized { - fp.logger.Debug( - "the block is already finalized, skip checking randomness", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("target_height", targetBlock.Height), - ) - // TODO: returning nil here is to safely break the loop - // the error still exists - return nil - } - - case <-fp.quit: - fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) - return nil - } - } -} - // retrySubmitFinalitySignatureUntilBlockFinalized periodically tries to submit finality signature until success or the block is finalized // error will be returned if maximum retries have been reached or the query to the consumer chain fails func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { @@ -576,149 +471,6 @@ func (fp *FinalityProviderInstance) checkBlockFinalization(height uint64) (bool, return b.Finalized, nil } -// retryCommitPubRandUntilBlockFinalized periodically tries to commit public rand until success or the block is finalized -// error will be returned if maximum retries have been reached or the query to the consumer chain fails -func (fp *FinalityProviderInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { - var failedCycles uint32 - - // we break the for loop if the block is finalized or the public rand is successfully committed - // error will be returned if maximum retries have been reached or the query to the consumer chain fails - for { - // error will be returned if max retries have been reached - res, err := fp.CommitPubRand(targetBlock) - if err != nil { - if clientcontroller.IsUnrecoverable(err) { - return nil, err - } - fp.logger.Debug( - "failed to commit public randomness to the consumer chain", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint32("current_failures", failedCycles), - zap.Uint64("target_block_height", targetBlock.Height), - zap.Error(err), - ) - - failedCycles += 1 - if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { - return nil, fmt.Errorf("reached max failed cycles with err: %w", err) - } - } else { - // the public randomness has been successfully submitted - return res, nil - } - select { - case <-time.After(fp.cfg.SubmissionRetryInterval): - // periodically query the index block to be later checked whether it is Finalized - finalized, err := fp.checkBlockFinalization(targetBlock.Height) - if err != nil { - return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) - } - if finalized { - fp.logger.Debug( - "the block is already finalized, skip submission", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("target_height", targetBlock.Height), - ) - // TODO: returning nil here is to safely break the loop - // the error still exists - return nil, nil - } - - case <-fp.quit: - fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) - return nil, nil - } - } -} - -// CommitPubRand generates a list of Schnorr rand pairs, -// commits the public randomness for the managed finality providers, -// and save the randomness pair to DB -func (fp *FinalityProviderInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxResponse, error) { - lastCommittedHeight, err := fp.GetLastCommittedHeight() - if err != nil { - return nil, err - } - - var startHeight uint64 - if lastCommittedHeight == uint64(0) { - // the finality-provider has never submitted public rand before - startHeight = tipBlock.Height + 1 - // should not use subtraction because they are in the type of uint64 - } else if lastCommittedHeight < fp.cfg.MinRandHeightGap+tipBlock.Height { - // we are running out of the randomness - startHeight = lastCommittedHeight + 1 - } else { - fp.logger.Debug( - "the finality-provider has sufficient public randomness, skip committing more", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("block_height", tipBlock.Height), - zap.Uint64("last_committed_height", lastCommittedHeight), - ) - return nil, nil - } - - // generate a list of Schnorr randomness pairs - // NOTE: currently, calling this will create and save a list of randomness - // in case of failure, randomness that has been created will be overwritten - // for safety reason as the same randomness must not be used twice - // TODO: should consider an implementation that deterministically create - // randomness without saving it - pubRandList, err := fp.createPubRandList(startHeight) - if err != nil { - return nil, fmt.Errorf("failed to generate randomness: %w", err) - } - - // get the message hash for signing - msg := &ftypes.MsgCommitPubRandList{ - FpBtcPk: fp.btcPk, - StartHeight: startHeight, - PubRandList: pubRandList, - } - hash, err := msg.HashToSign() - if err != nil { - return nil, fmt.Errorf("failed to sign the commit public randomness message: %w", err) - } - - // sign the message hash using the finality-provider's BTC private key - schnorrSig, err := fp.em.SignSchnorrSig(fp.btcPk.MustMarshal(), hash, fp.passphrase) - if err != nil { - return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) - } - - pubRandByteList := make([]*btcec.FieldVal, 0, len(pubRandList)) - for _, r := range pubRandList { - pubRandByteList = append(pubRandByteList, r.ToFieldVal()) - } - res, err := fp.cc.CommitPubRandList(fp.MustGetBtcPk(), startHeight, pubRandByteList, schnorrSig) - if err != nil { - // TODO Add retry. check issue: https://github.com/babylonchain/finality-provider/issues/34 - return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) - } - - return res, nil -} - -func (fp *FinalityProviderInstance) createPubRandList(startHeight uint64) ([]bbntypes.SchnorrPubRand, error) { - pubRandList, err := fp.em.CreateRandomnessPairList( - fp.btcPk.MustMarshal(), - fp.GetChainID(), - startHeight, - uint32(fp.cfg.NumPubRand), - fp.passphrase, - ) - if err != nil { - return nil, err - } - - schnorrPubRandList := make([]bbntypes.SchnorrPubRand, 0, len(pubRandList)) - for _, pr := range pubRandList { - schnorrPubRandList = append(schnorrPubRandList, *bbntypes.NewSchnorrPubRandFromFieldVal(pr)) - } - - return schnorrPubRandList, nil -} - // SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain func (fp *FinalityProviderInstance) SubmitFinalitySignature(b *types.BlockInfo) (*types.TxResponse, error) { eotsSig, err := fp.signEotsSig(b) @@ -727,7 +479,7 @@ func (fp *FinalityProviderInstance) SubmitFinalitySignature(b *types.BlockInfo) } // send finality signature to the consumer chain - res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + res, err := fp.cc.SubmitFinalitySig(fp.GetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) if err != nil { return nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) } @@ -735,6 +487,10 @@ func (fp *FinalityProviderInstance) SubmitFinalitySignature(b *types.BlockInfo) // update DB fp.MustUpdateStateAfterFinalitySigSubmission(b.Height) + // update metrics + fp.metrics.RecordFpVoteTime(fp.GetBtcPkHex()) + fp.metrics.IncrementFpTotalVotedBlocks(fp.GetBtcPkHex()) + return res, nil } @@ -755,7 +511,7 @@ func (fp *FinalityProviderInstance) SubmitBatchFinalitySignatures(blocks []*type } // send finality signature to the consumer chain - res, err := fp.cc.SubmitBatchFinalitySigs(fp.MustGetBtcPk(), blocks, sigs) + res, err := fp.cc.SubmitBatchFinalitySigs(fp.GetBtcPk(), blocks, sigs) if err != nil { return nil, fmt.Errorf("failed to send a batch of finality signatures to the consumer chain: %w", err) } @@ -787,23 +543,13 @@ func (fp *FinalityProviderInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.S // this API is the same as SubmitFinalitySignature except that we don't constraint the voting height and update status // Note: this should not be used in the submission loop func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { - // check last committed height - lastCommittedHeight, err := fp.GetLastCommittedHeight() - if err != nil { - return nil, nil, err - } - if lastCommittedHeight < b.Height { - return nil, nil, fmt.Errorf("the finality-provider's last committed height %v is lower than the current block height %v", - lastCommittedHeight, b.Height) - } - eotsSig, err := fp.signEotsSig(b) if err != nil { return nil, nil, err } // send finality signature to the consumer chain - res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + res, err := fp.cc.SubmitFinalitySig(fp.GetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) if err != nil { return nil, nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) } @@ -861,50 +607,6 @@ func (fp *FinalityProviderInstance) getPollerStartingHeight() (uint64, error) { return initialBlockToGet, nil } -func (fp *FinalityProviderInstance) GetLastCommittedHeight() (uint64, error) { - pubRandMap, err := fp.lastCommittedPublicRandWithRetry(1) - if err != nil { - return 0, err - } - - // no committed randomness yet - if len(pubRandMap) == 0 { - return 0, nil - } - - if len(pubRandMap) > 1 { - return 0, fmt.Errorf("got more than one last committed public randomness") - } - heights := make([]uint64, 0, 1) - for k := range pubRandMap { - heights = append(heights, k) - } - - return heights[0], nil -} - -func (fp *FinalityProviderInstance) lastCommittedPublicRandWithRetry(count uint64) (map[uint64]*btcec.FieldVal, error) { - var response map[uint64]*btcec.FieldVal - if err := retry.Do(func() error { - pubRandMap, err := fp.cc.QueryLastCommittedPublicRand(fp.MustGetBtcPk(), count) - if err != nil { - return err - } - response = pubRandMap - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - fp.logger.Debug( - "failed to query babylon for the last committed public randomness", - zap.Uint("attempt", n+1), - zap.Uint("max_attempts", RtyAttNum), - zap.Error(err), - ) - })); err != nil { - return nil, err - } - return response, nil -} - func (fp *FinalityProviderInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*types.BlockInfo, error) { var response []*types.BlockInfo if err := retry.Do(func() error { @@ -949,6 +651,7 @@ func (fp *FinalityProviderInstance) getLatestBlockWithRetry() (*types.BlockInfo, })); err != nil { return nil, err } + fp.metrics.RecordBabylonTipHeight(latestBlock.Height) return latestBlock, nil } @@ -960,7 +663,7 @@ func (fp *FinalityProviderInstance) GetVotingPowerWithRetry(height uint64) (uint ) if err := retry.Do(func() error { - power, err = fp.cc.QueryFinalityProviderVotingPower(fp.MustGetBtcPk(), height) + power, err = fp.cc.QueryFinalityProviderVotingPower(fp.GetBtcPk(), height) if err != nil { return err } @@ -986,7 +689,7 @@ func (fp *FinalityProviderInstance) GetFinalityProviderSlashedWithRetry() (bool, ) if err := retry.Do(func() error { - slashed, err = fp.cc.QueryFinalityProviderSlashed(fp.MustGetBtcPk()) + slashed, err = fp.cc.QueryFinalityProviderSlashed(fp.GetBtcPk()) if err != nil { return err } diff --git a/finality-provider/service/fp_instance_test.go b/finality-provider/service/fp_instance_test.go index c58ad91d..9cc2c696 100644 --- a/finality-provider/service/fp_instance_test.go +++ b/finality-provider/service/fp_instance_test.go @@ -6,64 +6,39 @@ import ( "path/filepath" "testing" - "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "go.uber.org/zap" "github.com/babylonchain/finality-provider/clientcontroller" "github.com/babylonchain/finality-provider/eotsmanager" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/testutil" "github.com/babylonchain/finality-provider/types" ) -func FuzzCommitPubRandList(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - randomStartingHeight := uint64(r.Int63n(100) + 1) - currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()). - Return(uint64(0), nil).AnyTimes() - _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) - defer cleanUp() - - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() - res, err := fpIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - }) -} - func FuzzSubmitFinalitySig(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) + randomRegiteredEpoch := uint64(r.Int63n(10) + 1) randomStartingHeight := uint64(r.Int63n(100) + 1) currentHeight := randomStartingHeight + uint64(r.Int63n(10)+1) startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + // mock finalised BTC timestamped + mockClientController.EXPECT().QueryLastFinalizedEpoch().Return(randomRegiteredEpoch, nil).AnyTimes() + + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight, randomRegiteredEpoch) defer cleanUp() - mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). - Return(uint64(1), nil).AnyTimes() - lastCommittedHeight := randomStartingHeight + 25 - lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) - lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() - mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + // mock voting power + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.GetBtcPk(), gomock.Any()). Return(uint64(1), nil).AnyTimes() // submit finality sig @@ -73,7 +48,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { } expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - SubmitFinalitySig(fpIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). + SubmitFinalitySig(fpIns.GetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() providerRes, err := fpIns.SubmitFinalitySignature(nextBlock) require.NoError(t, err) @@ -85,21 +60,25 @@ func FuzzSubmitFinalitySig(f *testing.F) { }) } -func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.FinalityProviderApp, *service.FinalityProviderInstance, func()) { +func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64, registeredEpoch uint64) (*service.FinalityProviderApp, *service.FinalityProviderInstance, func()) { logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") - eotsCfg := testutil.GenEOTSConfig(r, t) - em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + eotsCfg := eotscfg.DefaultConfigWithHomePath(eotsHomeDir) + eotsdb, err := eotsCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg.KeyringBackend, eotsdb, logger) require.NoError(t, err) // create finality-provider app with randomized config fpHomeDir := filepath.Join(t.TempDir(), "fp-home") - fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg := config.DefaultConfigWithHome(fpHomeDir) fpCfg.NumPubRand = testutil.TestPubRandNum fpCfg.PollerConfig.AutoChainScanningMode = false fpCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight - app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, cc, em, logger) + fpdb, err := fpCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + app, err := service.NewFinalityProviderApp(&fpCfg, cc, em, fpdb, logger) require.NoError(t, err) err = app.Start() require.NoError(t, err) @@ -108,14 +87,24 @@ func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc cli // create registered finality-provider fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) - err = app.GetFinalityProviderStore().SetFinalityProviderStatus(fp, proto.FinalityProviderStatus_REGISTERED) + err = app.GetFinalityProviderStore().SetFpStatus(fp.BtcPk, proto.FinalityProviderStatus_REGISTERED) + require.NoError(t, err) + + err = app.GetFinalityProviderStore().SetFpRegisteredEpoch(fp.BtcPk, registeredEpoch) require.NoError(t, err) - fpIns, err := service.NewFinalityProviderInstance(fp.MustGetBIP340BTCPK(), fpCfg, app.GetFinalityProviderStore(), cc, em, passphrase, make(chan *service.CriticalError), logger) + + // TODO: use mock metrics + m := metrics.NewFpMetrics() + fpIns, err := service.NewFinalityProviderInstance(fp.GetBIP340BTCPK(), &fpCfg, app.GetFinalityProviderStore(), cc, em, m, passphrase, make(chan *service.CriticalError), logger) require.NoError(t, err) cleanUp := func() { err = app.Stop() require.NoError(t, err) + err = eotsdb.Close() + require.NoError(t, err) + err = fpdb.Close() + require.NoError(t, err) err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) err = os.RemoveAll(fpHomeDir) diff --git a/finality-provider/service/fp_manager.go b/finality-provider/service/fp_manager.go index 921747e4..03fef45c 100644 --- a/finality-provider/service/fp_manager.go +++ b/finality-provider/service/fp_manager.go @@ -1,8 +1,8 @@ package service import ( - "errors" "fmt" + "strings" "sync" "time" @@ -16,7 +16,8 @@ import ( "github.com/babylonchain/finality-provider/eotsmanager" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/types" ) @@ -41,21 +42,25 @@ type FinalityProviderManager struct { fpis map[string]*FinalityProviderInstance // needed for initiating finality-provider instances - fps *fpstore.FinalityProviderStore + fps *store.FinalityProviderStore config *fpcfg.Config cc clientcontroller.ClientController em eotsmanager.EOTSManager logger *zap.Logger + metrics *metrics.FpMetrics + criticalErrChan chan *CriticalError quit chan struct{} } -func NewFinalityProviderManager(fps *fpstore.FinalityProviderStore, +func NewFinalityProviderManager( + fps *store.FinalityProviderStore, config *fpcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, + metrics *metrics.FpMetrics, logger *zap.Logger, ) (*FinalityProviderManager, error) { return &FinalityProviderManager{ @@ -66,6 +71,7 @@ func NewFinalityProviderManager(fps *fpstore.FinalityProviderStore, config: config, cc: cc, em: em, + metrics: metrics, logger: logger, quit: make(chan struct{}), }, nil @@ -88,7 +94,9 @@ func (fpm *FinalityProviderManager) monitorCriticalErr() { zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) continue } - if errors.Is(criticalErr.err, btcstakingtypes.ErrFpAlreadySlashed) { + // cannot use error.Is because the unwrapped error + // is not the expected error type + if strings.Contains(criticalErr.err.Error(), btcstakingtypes.ErrFpAlreadySlashed.Error()) { fpm.setFinalityProviderSlashed(fpi) fpm.logger.Debug("the finality-provider has been slashed", zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) @@ -229,14 +237,19 @@ func (fpm *FinalityProviderManager) StartAll() error { go fpm.monitorStatusUpdate() } - registeredFps, err := fpm.fps.ListRegisteredFinalityProviders() + storedFps, err := fpm.fps.GetAllStoredFinalityProviders() if err != nil { return err } - for _, fp := range registeredFps { - // TODO: passphrase is not available for starting all the finality providers - if err := fpm.StartFinalityProvider(fp.MustGetBIP340BTCPK(), ""); err != nil { + for _, fp := range storedFps { + if fp.Status == proto.FinalityProviderStatus_CREATED || fp.Status == proto.FinalityProviderStatus_SLASHED { + fpm.logger.Info("the finality provider cannot be started with status", + zap.String("btc-pk", fp.GetBIP340BTCPK().MarshalHex()), + zap.String("status", fp.Status.String())) + continue + } + if err := fpm.StartFinalityProvider(fp.GetBIP340BTCPK(), ""); err != nil { return err } } @@ -259,6 +272,7 @@ func (fpm *FinalityProviderManager) Stop() error { stopErr = err break } + fpm.metrics.DecrementRunningFpGauge() } close(fpm.quit) @@ -279,6 +293,49 @@ func (fpm *FinalityProviderManager) ListFinalityProviderInstances() []*FinalityP return fpisList } +func (fpm *FinalityProviderManager) AllFinalityProviders() ([]*proto.FinalityProviderInfo, error) { + storedFps, err := fpm.fps.GetAllStoredFinalityProviders() + if err != nil { + return nil, err + } + + fpsInfo := make([]*proto.FinalityProviderInfo, 0, len(storedFps)) + for _, fp := range storedFps { + fpInfo := fp.ToFinalityProviderInfo() + + if fpm.IsFinalityProviderRunning(fp.GetBIP340BTCPK()) { + fpInfo.IsRunning = true + } + + fpsInfo = append(fpsInfo, fpInfo) + } + + return fpsInfo, nil +} + +func (fpm *FinalityProviderManager) FinalityProviderInfo(fpPk *bbntypes.BIP340PubKey) (*proto.FinalityProviderInfo, error) { + storedFp, err := fpm.fps.GetFinalityProvider(fpPk.MustToBTCPK()) + if err != nil { + return nil, err + } + + fpInfo := storedFp.ToFinalityProviderInfo() + + if fpm.IsFinalityProviderRunning(fpPk) { + fpInfo.IsRunning = true + } + + return fpInfo, nil +} + +func (fpm *FinalityProviderManager) IsFinalityProviderRunning(fpPk *bbntypes.BIP340PubKey) bool { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + _, exists := fpm.fpis[fpPk.MarshalHex()] + return exists +} + func (fpm *FinalityProviderManager) GetFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) (*FinalityProviderInstance, error) { fpm.mu.Lock() defer fpm.mu.Unlock() @@ -308,6 +365,7 @@ func (fpm *FinalityProviderManager) removeFinalityProviderInstance(fpPk *bbntype } delete(fpm.fpis, keyHex) + fpm.metrics.DecrementRunningFpGauge() return nil } @@ -331,7 +389,7 @@ func (fpm *FinalityProviderManager) addFinalityProviderInstance( return fmt.Errorf("finality-provider instance already exists") } - fpIns, err := NewFinalityProviderInstance(pk, fpm.config, fpm.fps, fpm.cc, fpm.em, passphrase, fpm.criticalErrChan, fpm.logger) + fpIns, err := NewFinalityProviderInstance(pk, fpm.config, fpm.fps, fpm.cc, fpm.em, fpm.metrics, passphrase, fpm.criticalErrChan, fpm.logger) if err != nil { return fmt.Errorf("failed to create finality-provider %s instance: %w", pkHex, err) } @@ -341,6 +399,7 @@ func (fpm *FinalityProviderManager) addFinalityProviderInstance( } fpm.fpis[pkHex] = fpIns + fpm.metrics.IncrementRunningFpGauge() return nil } diff --git a/finality-provider/service/fp_manager_test.go b/finality-provider/service/fp_manager_test.go index 511068bb..486fcb73 100644 --- a/finality-provider/service/fp_manager_test.go +++ b/finality-provider/service/fp_manager_test.go @@ -8,28 +8,26 @@ import ( "testing" "time" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" - "github.com/babylonchain/finality-provider/util" - - "go.uber.org/zap" - - "github.com/babylonchain/finality-provider/keyring" - "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" - "github.com/babylonchain/finality-provider/clientcontroller" "github.com/babylonchain/finality-provider/eotsmanager" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" "github.com/babylonchain/finality-provider/finality-provider/service" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/keyring" + fpkr "github.com/babylonchain/finality-provider/keyring" + "github.com/babylonchain/finality-provider/metrics" "github.com/babylonchain/finality-provider/testutil" "github.com/babylonchain/finality-provider/testutil/mocks" "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/util" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" ) var ( @@ -59,7 +57,7 @@ func FuzzStatusUpdate(f *testing.F) { mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() mockClientController.EXPECT().QueryBlock(gomock.Any()).Return(currentBlockRes, nil).AnyTimes() - mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryLastFinalizedEpoch().Return(uint64(0), nil).AnyTimes() votingPower := uint64(r.Intn(2)) mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() @@ -99,13 +97,15 @@ func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc c logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") - eotsCfg := testutil.GenEOTSConfig(r, t) - em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + eotsCfg := eotscfg.DefaultConfigWithHomePath(eotsHomeDir) + eotsdb, err := eotsCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg.KeyringBackend, eotsdb, logger) require.NoError(t, err) // create finality-provider app with randomized config fpHomeDir := filepath.Join(t.TempDir(), "fp-home") - fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg := fpcfg.DefaultConfigWithHome(fpHomeDir) fpCfg.StatusUpdateInterval = 10 * time.Millisecond input := strings.NewReader("") kr, err := keyring.CreateKeyring( @@ -117,14 +117,13 @@ func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) err = util.MakeDirectory(fpcfg.DataDir(fpHomeDir)) require.NoError(t, err) - fpStore, err := fpstore.NewFinalityProviderStore( - fpcfg.DBPath(fpHomeDir), - fpCfg.DatabaseConfig.Name, - fpCfg.DatabaseConfig.Backend, - ) + fpdb, err := fpCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + fpStore, err := fpstore.NewFinalityProviderStore(fpdb) require.NoError(t, err) - vm, err := service.NewFinalityProviderManager(fpStore, fpCfg, cc, em, logger) + metricsCollectors := metrics.NewFpMetrics() + vm, err := service.NewFinalityProviderManager(fpStore, &fpCfg, cc, em, metricsCollectors, logger) require.NoError(t, err) // create registered finality-provider @@ -136,7 +135,7 @@ func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - keyInfo, err := kc.CreateChainKey(passphrase, hdPath) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath, "") require.NoError(t, err) bbnPk := &secp256k1.PubKey{Key: keyInfo.PublicKey.SerializeCompressed()} fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) @@ -144,14 +143,35 @@ func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc c pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) require.NoError(t, err) - storedFp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) - storedFp.Status = proto.FinalityProviderStatus_REGISTERED - err = fpStore.SaveFinalityProvider(storedFp) + _, mpr, err := fpkr.GenerateMasterRandPair(fpRecord.PrivKey.Serialize(), types.MarshalChainID(chainID)) + require.NoError(t, err) + + err = fpStore.CreateFinalityProvider( + bbnPk, + btcPk.MustToBTCPK(), + testutil.RandomDescription(r), + testutil.ZeroCommissionRate(), + mpr.MarshalBase58(), + keyName, + chainID, + pop.BabylonSig, + pop.BtcSig, + ) + require.NoError(t, err) + + err = fpStore.SetFpStatus(btcPk.MustToBTCPK(), proto.FinalityProviderStatus_REGISTERED) + require.NoError(t, err) + + err = fpStore.SetFpRegisteredEpoch(btcPk.MustToBTCPK(), 0) require.NoError(t, err) cleanUp := func() { err = vm.Stop() require.NoError(t, err) + err = eotsdb.Close() + require.NoError(t, err) + err = fpdb.Close() + require.NoError(t, err) err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) err = os.RemoveAll(fpHomeDir) diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go index a2948746..877a9dd2 100644 --- a/finality-provider/service/rpcserver.go +++ b/finality-provider/service/rpcserver.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "google.golang.org/grpc" "github.com/babylonchain/finality-provider/finality-provider/proto" @@ -89,12 +90,17 @@ func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.Creat return nil, err } + var description stakingtypes.Description + if err := description.Unmarshal(req.Description); err != nil { + return nil, err + } + result, err := r.app.CreateFinalityProvider( req.KeyName, req.ChainId, req.Passphrase, req.HdPath, - req.Description, + &description, &commissionRate, ) @@ -102,12 +108,8 @@ func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.Creat return nil, err } - fpInfo, err := proto.NewFinalityProviderInfo(result.StoreFp) - if err != nil { - return nil, err - } return &proto.CreateFinalityProviderResponse{ - FinalityProvider: fpInfo, + FinalityProvider: result.FpInfo, }, nil } @@ -188,33 +190,33 @@ func (r *rpcServer) QueryFinalityProvider(ctx context.Context, req *proto.QueryF if err != nil { return nil, err } - fp, err := r.app.GetFinalityProviderInstance(fpPk) - if err != nil { - return nil, err - } - - fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + fp, err := r.app.GetFinalityProviderInfo(fpPk) if err != nil { return nil, err } - return &proto.QueryFinalityProviderResponse{FinalityProvider: fpInfo}, nil + return &proto.QueryFinalityProviderResponse{FinalityProvider: fp}, nil } // QueryFinalityProviderList queries the information of a list of finality providers func (r *rpcServer) QueryFinalityProviderList(ctx context.Context, req *proto.QueryFinalityProviderListRequest) ( *proto.QueryFinalityProviderListResponse, error) { - fps := r.app.ListFinalityProviderInstances() + fps, err := r.app.ListAllFinalityProvidersInfo() + if err != nil { + return nil, err + } - fpsInfo := make([]*proto.FinalityProviderInfo, len(fps)) - for i, fp := range fps { - fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) - if err != nil { - return nil, err - } - fpsInfo[i] = fpInfo + return &proto.QueryFinalityProviderListResponse{FinalityProviders: fps}, nil +} + +// SignMessageFromChainKey signs a message from the chain keyring. +func (r *rpcServer) SignMessageFromChainKey(ctx context.Context, req *proto.SignMessageFromChainKeyRequest) ( + *proto.SignMessageFromChainKeyResponse, error) { + signature, err := r.app.SignRawMsg(req.KeyName, req.Passphrase, req.HdPath, req.MsgToSign) + if err != nil { + return nil, err } - return &proto.QueryFinalityProviderListResponse{FinalityProviders: fpsInfo}, nil + return &proto.SignMessageFromChainKeyResponse{Signature: signature}, nil } diff --git a/finality-provider/service/server.go b/finality-provider/service/server.go index 5b4dbf58..94050b81 100644 --- a/finality-provider/service/server.go +++ b/finality-provider/service/server.go @@ -1,16 +1,19 @@ package service import ( + "context" "fmt" "net" "sync" "sync/atomic" + "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/signal" "go.uber.org/zap" "google.golang.org/grpc" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/metrics" ) // Server is the main daemon construct for the Finality Provider server. It handles @@ -23,17 +26,19 @@ type Server struct { logger *zap.Logger rpcServer *rpcServer + db kvdb.Backend interceptor signal.Interceptor quit chan struct{} } // NewFinalityproviderServer creates a new server with the given config. -func NewFinalityProviderServer(cfg *fpcfg.Config, l *zap.Logger, fpa *FinalityProviderApp, sig signal.Interceptor) *Server { +func NewFinalityProviderServer(cfg *fpcfg.Config, l *zap.Logger, fpa *FinalityProviderApp, db kvdb.Backend, sig signal.Interceptor) *Server { return &Server{ cfg: cfg, logger: l, rpcServer: newRPCServer(fpa), + db: db, interceptor: sig, quit: make(chan struct{}, 1), } @@ -46,10 +51,25 @@ func (s *Server) RunUntilShutdown() error { return nil } + // Start the metrics server. + promAddr, err := s.cfg.Metrics.Address() + if err != nil { + return fmt.Errorf("failed to get prometheus address: %w", err) + } + metricsServer := metrics.Start(promAddr, s.logger) + defer func() { s.logger.Info("Shutdown complete") }() + defer func() { + s.logger.Info("Closing database...") + s.db.Close() + s.logger.Info("Database closed") + metricsServer.Stop(context.Background()) + s.logger.Info("Metrics server stopped") + }() + listenAddr := s.cfg.RpcListener // we create listeners from the RPCListeners defined // in the config. diff --git a/finality-provider/service/types.go b/finality-provider/service/types.go index b2aa907b..389de729 100644 --- a/finality-provider/service/types.go +++ b/finality-provider/service/types.go @@ -8,21 +8,24 @@ import ( btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "go.uber.org/zap" "github.com/babylonchain/finality-provider/finality-provider/proto" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/types" ) type createFinalityProviderResponse struct { - StoreFp *proto.StoreFinalityProvider + FpInfo *proto.FinalityProviderInfo } + type createFinalityProviderRequest struct { keyName string passPhrase string hdPath string chainID string - description []byte + description *stakingtypes.Description commission *sdkmath.LegacyDec errResponse chan error successResponse chan *createFinalityProviderResponse @@ -33,8 +36,9 @@ type registerFinalityProviderRequest struct { btcPubKey *bbntypes.BIP340PubKey // TODO we should have our own representation of PoP pop *btcstakingtypes.ProofOfPossession - description []byte + description *stakingtypes.Description commission *sdkmath.LegacyDec + masterPubRand string errResponse chan error successResponse chan *RegisterFinalityProviderResponse } @@ -43,26 +47,28 @@ type finalityProviderRegisteredEvent struct { bbnPubKey *secp256k1.PubKey btcPubKey *bbntypes.BIP340PubKey txHash string + registeredEpoch uint64 successResponse chan *RegisterFinalityProviderResponse } type RegisterFinalityProviderResponse struct { - bbnPubKey *secp256k1.PubKey - btcPubKey *bbntypes.BIP340PubKey - TxHash string + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + TxHash string + RegisteredEpoch uint64 } type CreateFinalityProviderResult struct { - StoreFp *proto.StoreFinalityProvider + FpInfo *proto.FinalityProviderInfo } type fpState struct { mu sync.Mutex - fp *proto.StoreFinalityProvider - s *fpstore.FinalityProviderStore + fp *store.StoredFinalityProvider + s *store.FinalityProviderStore } -func (fps *fpState) getStoreFinalityProvider() *proto.StoreFinalityProvider { +func (fps *fpState) getStoreFinalityProvider() *store.StoredFinalityProvider { fps.mu.Lock() defer fps.mu.Unlock() return fps.fp @@ -72,14 +78,14 @@ func (fps *fpState) setStatus(s proto.FinalityProviderStatus) error { fps.mu.Lock() fps.fp.Status = s fps.mu.Unlock() - return fps.s.UpdateFinalityProvider(fps.fp) + return fps.s.SetFpStatus(fps.fp.BtcPk, s) } func (fps *fpState) setLastProcessedHeight(height uint64) error { fps.mu.Lock() fps.fp.LastProcessedHeight = height fps.mu.Unlock() - return fps.s.UpdateFinalityProvider(fps.fp) + return fps.s.SetFpLastProcessedHeight(fps.fp.BtcPk, height) } func (fps *fpState) setLastProcessedAndVotedHeight(height uint64) error { @@ -87,27 +93,19 @@ func (fps *fpState) setLastProcessedAndVotedHeight(height uint64) error { fps.fp.LastVotedHeight = height fps.fp.LastProcessedHeight = height fps.mu.Unlock() - return fps.s.UpdateFinalityProvider(fps.fp) + return fps.s.SetFpLastVotedHeight(fps.fp.BtcPk, height) } -func (fp *FinalityProviderInstance) GetStoreFinalityProvider() *proto.StoreFinalityProvider { +func (fp *FinalityProviderInstance) GetStoreFinalityProvider() *store.StoredFinalityProvider { return fp.state.getStoreFinalityProvider() } -func (fp *FinalityProviderInstance) GetBabylonPk() *secp256k1.PubKey { - return fp.state.getStoreFinalityProvider().GetBabylonPK() -} - -func (fp *FinalityProviderInstance) GetBabylonPkHex() string { - return fp.state.getStoreFinalityProvider().GetBabylonPkHexString() -} - func (fp *FinalityProviderInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { - return fp.state.getStoreFinalityProvider().MustGetBIP340BTCPK() + return fp.state.getStoreFinalityProvider().GetBIP340BTCPK() } -func (fp *FinalityProviderInstance) MustGetBtcPk() *btcec.PublicKey { - return fp.state.getStoreFinalityProvider().MustGetBTCPK() +func (fp *FinalityProviderInstance) GetBtcPk() *btcec.PublicKey { + return fp.state.getStoreFinalityProvider().BtcPk } func (fp *FinalityProviderInstance) GetBtcPkHex() string { @@ -127,7 +125,7 @@ func (fp *FinalityProviderInstance) GetLastProcessedHeight() uint64 { } func (fp *FinalityProviderInstance) GetChainID() []byte { - return []byte(fp.state.getStoreFinalityProvider().ChainId) + return types.MarshalChainID(fp.state.getStoreFinalityProvider().ChainID) } func (fp *FinalityProviderInstance) SetStatus(s proto.FinalityProviderStatus) error { @@ -150,6 +148,7 @@ func (fp *FinalityProviderInstance) MustSetLastProcessedHeight(height uint64) { fp.logger.Fatal("failed to set last processed height", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("last_processed_height", height)) } + fp.metrics.RecordFpLastProcessedHeight(fp.GetBtcPkHex(), height) } func (fp *FinalityProviderInstance) updateStateAfterFinalitySigSubmission(height uint64) error { @@ -161,6 +160,8 @@ func (fp *FinalityProviderInstance) MustUpdateStateAfterFinalitySigSubmission(he fp.logger.Fatal("failed to update state after finality signature submitted", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", height)) } + fp.metrics.RecordFpLastVotedHeight(fp.GetBtcPkHex(), height) + fp.metrics.RecordFpLastProcessedHeight(fp.GetBtcPkHex(), height) } func (fp *FinalityProviderInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { @@ -176,3 +177,8 @@ func (fp *FinalityProviderInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) func (fp *FinalityProviderInstance) BtcPrivKey() (*btcec.PrivateKey, error) { return fp.getEOTSPrivKey() } + +// only used for testing purposes +func (fp *FinalityProviderInstance) RegisteredEpoch() uint64 { + return fp.state.fp.RegisteredEpoch +} diff --git a/finality-provider/store/errors.go b/finality-provider/store/errors.go new file mode 100644 index 00000000..982369ab --- /dev/null +++ b/finality-provider/store/errors.go @@ -0,0 +1,14 @@ +package store + +import "errors" + +var ( + // ErrCorruptedFinalityProviderDb For some reason, db on disk representation have changed + ErrCorruptedFinalityProviderDb = errors.New("finality provider db is corrupted") + + // ErrFinalityProviderNotFound The finality provider we try update is not found in db + ErrFinalityProviderNotFound = errors.New("finality provider not found") + + // ErrDuplicateFinalityProvider The finality provider we try to add already exists in db + ErrDuplicateFinalityProvider = errors.New("finality provider already exists") +) diff --git a/finality-provider/store/fpstore.go b/finality-provider/store/fpstore.go index feaa6088..df916fd5 100644 --- a/finality-provider/store/fpstore.go +++ b/finality-provider/store/fpstore.go @@ -5,206 +5,254 @@ import ( "math" sdkmath "cosmossdk.io/math" - "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcwallet/walletdb" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - gproto "google.golang.org/protobuf/proto" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/lightningnetwork/lnd/kvdb" + pm "google.golang.org/protobuf/proto" "github.com/babylonchain/finality-provider/finality-provider/proto" - "github.com/babylonchain/finality-provider/store" ) -const ( - fpPrefix = "finality-provider" +var ( + // mapping pk -> proto.FinalityProvider + finalityProviderBucketName = []byte("finalityProviders") ) -func NewStoreFinalityProvider(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des []byte, com *sdkmath.LegacyDec) *proto.StoreFinalityProvider { - return &proto.StoreFinalityProvider{ - KeyName: keyName, - BabylonPk: babylonPk.Bytes(), - BtcPk: btcPk.MustMarshal(), - Pop: &proto.ProofOfPossession{ - BabylonSig: pop.BabylonSig, - BtcSig: pop.BtcSig, - }, - ChainId: chainID, - Status: proto.FinalityProviderStatus_CREATED, - Description: des, - Commission: com.String(), - } -} - type FinalityProviderStore struct { - s store.Store + db kvdb.Backend } -func NewFinalityProviderStore(dbPath string, dbName string, dbBackend string) (*FinalityProviderStore, error) { - s, err := openStore(dbPath, dbName, dbBackend) - if err != nil { +// NewFinalityProviderStore returns a new store backed by db +func NewFinalityProviderStore(db kvdb.Backend) (*FinalityProviderStore, error) { + store := &FinalityProviderStore{db} + if err := store.initBuckets(); err != nil { return nil, err } - return &FinalityProviderStore{s: s}, nil -} - -func getFinalityProviderKey(pk []byte) []byte { - return append([]byte(fpPrefix), pk...) + return store, nil } -func (vs *FinalityProviderStore) getFinalityProviderListKey() []byte { - return []byte(fpPrefix) +func (s *FinalityProviderStore) initBuckets() error { + return kvdb.Batch(s.db, func(tx kvdb.RwTx) error { + _, err := tx.CreateTopLevelBucket(finalityProviderBucketName) + return err + }) } -func (vs *FinalityProviderStore) SaveFinalityProvider(fp *proto.StoreFinalityProvider) error { - k := getFinalityProviderKey(fp.BtcPk) - v, err := gproto.Marshal(fp) +func (s *FinalityProviderStore) CreateFinalityProvider( + chainPk *secp256k1.PubKey, + btcPk *btcec.PublicKey, + description *stakingtypes.Description, + commission *sdkmath.LegacyDec, + masterPubRand string, + keyName, chainId string, + chainSig, btcSig []byte, +) error { + desBytes, err := description.Marshal() if err != nil { - return fmt.Errorf("failed to marshal the created finality-provider object: %w", err) + return fmt.Errorf("invalid description: %w", err) } - - if err := vs.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the created finality-provider object: %w", err) + fp := &proto.FinalityProvider{ + ChainPk: chainPk.Key, + BtcPk: schnorr.SerializePubKey(btcPk), + Description: desBytes, + Commission: commission.String(), + Pop: &proto.ProofOfPossession{ + ChainSig: chainSig, + BtcSig: btcSig, + }, + RegisteredEpoch: math.MaxUint64, + MasterPubRand: masterPubRand, + KeyName: keyName, + ChainId: chainId, + Status: proto.FinalityProviderStatus_CREATED, } - return nil + return s.createFinalityProviderInternal(fp) } -func (vs *FinalityProviderStore) UpdateFinalityProvider(fp *proto.StoreFinalityProvider) error { - k := getFinalityProviderKey(fp.BtcPk) - exists, err := vs.s.Exists(k) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("the finality-provider does not exist") +func (s *FinalityProviderStore) createFinalityProviderInternal( + fp *proto.FinalityProvider, +) error { + return kvdb.Batch(s.db, func(tx kvdb.RwTx) error { + fpBucket := tx.ReadWriteBucket(finalityProviderBucketName) + if fpBucket == nil { + return ErrCorruptedFinalityProviderDb + } + + // check btc pk first to avoid duplicates + if fpBucket.Get(fp.BtcPk) != nil { + return ErrDuplicateFinalityProvider + } + + return saveFinalityProvider(fpBucket, fp) + }) +} + +func saveFinalityProvider( + fpBucket walletdb.ReadWriteBucket, + fp *proto.FinalityProvider, +) error { + if fp == nil { + return fmt.Errorf("cannot save nil finality provider") } - v, err := gproto.Marshal(fp) + marshalled, err := pm.Marshal(fp) if err != nil { return err } - if err := vs.s.Put(k, v); err != nil { - return err + return fpBucket.Put(fp.BtcPk, marshalled) +} + +func (s *FinalityProviderStore) SetFpStatus(btcPk *btcec.PublicKey, status proto.FinalityProviderStatus) error { + setFpStatus := func(fp *proto.FinalityProvider) error { + fp.Status = status + return nil } - return nil + return s.setFinalityProviderState(btcPk, setFpStatus) } -func (vs *FinalityProviderStore) SetFinalityProviderStatus(fp *proto.StoreFinalityProvider, status proto.FinalityProviderStatus) error { - fp.Status = status - return vs.UpdateFinalityProvider(fp) +func (s *FinalityProviderStore) SetFpRegisteredEpoch(btcPk *btcec.PublicKey, registeredEpoch uint64) error { + setFpStatus := func(fp *proto.FinalityProvider) error { + fp.RegisteredEpoch = registeredEpoch + return nil + } + + return s.setFinalityProviderState(btcPk, setFpStatus) } -func (vs *FinalityProviderStore) GetStoreFinalityProvider(pk []byte) (*proto.StoreFinalityProvider, error) { - k := getFinalityProviderKey(pk) - fpBytes, err := vs.s.Get(k) - if err != nil { - return nil, err - } +// SetFpLastVotedHeight sets the last voted height to the stored last voted height and last processed height +// only if it is larger than the stored one. This is to ensure the stored state to increase monotonically +func (s *FinalityProviderStore) SetFpLastVotedHeight(btcPk *btcec.PublicKey, lastVotedHeight uint64) error { + setFpLastVotedHeight := func(fp *proto.FinalityProvider) error { + if fp.LastVotedHeight < lastVotedHeight { + fp.LastVotedHeight = lastVotedHeight + } + if fp.LastProcessedHeight < lastVotedHeight { + fp.LastProcessedHeight = lastVotedHeight + } - fp := new(proto.StoreFinalityProvider) - err = gproto.Unmarshal(fpBytes, fp) - if err != nil { - panic(fmt.Errorf("unable to unmarshal finality-provider object: %w", err)) + return nil } - return fp, nil + return s.setFinalityProviderState(btcPk, setFpLastVotedHeight) } -func (vs *FinalityProviderStore) ListFinalityProviders() ([]*proto.StoreFinalityProvider, error) { - k := vs.getFinalityProviderListKey() - fpsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - fpsList := make([]*proto.StoreFinalityProvider, len(fpsBytes)) - for i := 0; i < len(fpsBytes); i++ { - fp := new(proto.StoreFinalityProvider) - err := gproto.Unmarshal(fpsBytes[i].Value, fp) - if err != nil { - panic(fmt.Errorf("failed to unmarshal finality-provider from the database: %w", err)) +// SetFpLastProcessedHeight sets the last processed height to the stored last processed height +// only if it is larger than the stored one. This is to ensure the stored state to increase monotonically +func (s *FinalityProviderStore) SetFpLastProcessedHeight(btcPk *btcec.PublicKey, lastProcessedHeight uint64) error { + setFpLastProcessedHeight := func(fp *proto.FinalityProvider) error { + if fp.LastProcessedHeight < lastProcessedHeight { + fp.LastProcessedHeight = lastProcessedHeight } - fpsList[i] = fp + + return nil } - return fpsList, nil + return s.setFinalityProviderState(btcPk, setFpLastProcessedHeight) } -// ListRegisteredFinalityProviders returns a list of finality providers whose status is more than CREATED -// but less than SLASHED -func (vs *FinalityProviderStore) ListRegisteredFinalityProviders() ([]*proto.StoreFinalityProvider, error) { - k := vs.getFinalityProviderListKey() - fpsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } +func (s *FinalityProviderStore) setFinalityProviderState( + btcPk *btcec.PublicKey, + stateTransitionFn func(provider *proto.FinalityProvider) error, +) error { + pkBytes := schnorr.SerializePubKey(btcPk) + return kvdb.Batch(s.db, func(tx kvdb.RwTx) error { + fpBucket := tx.ReadWriteBucket(finalityProviderBucketName) + if fpBucket == nil { + return ErrCorruptedFinalityProviderDb + } - fpsList := make([]*proto.StoreFinalityProvider, 0) - for i := 0; i < len(fpsBytes); i++ { - fp := new(proto.StoreFinalityProvider) - err := gproto.Unmarshal(fpsBytes[i].Value, fp) - if err != nil { - panic(fmt.Errorf("failed to unmarshal finality-provider from the database: %w", err)) + fpFromDb := fpBucket.Get(pkBytes) + if fpFromDb == nil { + return ErrFinalityProviderNotFound } - if fp.Status > proto.FinalityProviderStatus_CREATED && fp.Status < proto.FinalityProviderStatus_SLASHED { - fpsList = append(fpsList, fp) + + var storedFp proto.FinalityProvider + if err := pm.Unmarshal(fpFromDb, &storedFp); err != nil { + return ErrCorruptedFinalityProviderDb } - } - return fpsList, nil + if err := stateTransitionFn(&storedFp); err != nil { + return err + } + + return saveFinalityProvider(fpBucket, &storedFp) + }) } -func (vs *FinalityProviderStore) GetEarliestActiveFinalityProviderVotedHeight() (uint64, error) { - registeredFps, err := vs.ListRegisteredFinalityProviders() - if err != nil { - return 0, err - } +func (s *FinalityProviderStore) GetFinalityProvider(btcPk *btcec.PublicKey) (*StoredFinalityProvider, error) { + var storedFp *StoredFinalityProvider + pkBytes := schnorr.SerializePubKey(btcPk) - if len(registeredFps) == 0 { - return 0, nil - } + err := s.db.View(func(tx kvdb.RTx) error { + fpBucket := tx.ReadBucket(finalityProviderBucketName) + if fpBucket == nil { + return ErrCorruptedFinalityProviderDb + } - earliestHeight := uint64(math.MaxUint64) - activeFpsCnt := 0 - for _, fp := range registeredFps { - // Note there might be a delay between the finality-provider being active on Babylon - // and this program capturing that. However, given that we only care - // about the `LastVotedHeight` of the finality-provider, other parts of the program - // ensure that when this value is set, the finality-provider is stored as ACTIVE. - // TODO: Another option would be to query here for the - // active status of each finality-provider although this might prove inefficient. - if fp.Status != proto.FinalityProviderStatus_ACTIVE { - continue + fpBytes := fpBucket.Get(pkBytes) + if fpBytes == nil { + return ErrFinalityProviderNotFound } - activeFpsCnt += 1 - if earliestHeight > fp.LastVotedHeight { - earliestHeight = fp.LastVotedHeight + + var fpProto proto.FinalityProvider + if err := pm.Unmarshal(fpBytes, &fpProto); err != nil { + return ErrCorruptedFinalityProviderDb } - } - // If there are no active finality providers, return 0 - if activeFpsCnt == 0 { - return 0, nil - } - return earliestHeight, nil -} -func (vs *FinalityProviderStore) Close() error { - if err := vs.s.Close(); err != nil { - return err + fpFromDb, err := protoFpToStoredFinalityProvider(&fpProto) + if err != nil { + return err + } + + storedFp = fpFromDb + return nil + }, func() {}) + + if err != nil { + return nil, err } - return nil + return storedFp, nil } -// openStore returns a Store instance with the given db type, path and name -// currently, we only support bbolt -func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { - switch dbBackend { - case "bbolt": - return store.NewBboltStore(dbPath, dbName) - default: - return nil, fmt.Errorf("unsupported database type") +// GetAllStoredFinalityProviders fetches all the stored finality providers from db +// pagination is probably not needed as the expected number of finality providers +// in the store is small +func (s *FinalityProviderStore) GetAllStoredFinalityProviders() ([]*StoredFinalityProvider, error) { + var storedFps []*StoredFinalityProvider + + err := s.db.View(func(tx kvdb.RTx) error { + fpBucket := tx.ReadBucket(finalityProviderBucketName) + if fpBucket == nil { + return ErrCorruptedFinalityProviderDb + } + + return fpBucket.ForEach(func(k, v []byte) error { + var fpProto proto.FinalityProvider + if err := pm.Unmarshal(v, &fpProto); err != nil { + return ErrCorruptedFinalityProviderDb + } + + fpFromDb, err := protoFpToStoredFinalityProvider(&fpProto) + if err != nil { + return err + } + storedFps = append(storedFps, fpFromDb) + + return nil + }) + }, func() {}) + + if err != nil { + return nil, err } + + return storedFps, nil } diff --git a/finality-provider/store/fpstore_test.go b/finality-provider/store/fpstore_test.go index a8c39a2b..a0935d81 100644 --- a/finality-provider/store/fpstore_test.go +++ b/finality-provider/store/fpstore_test.go @@ -3,11 +3,12 @@ package store_test import ( "math/rand" "os" - "path/filepath" "testing" + "github.com/babylonchain/babylon/testutil/datagen" "github.com/stretchr/testify/require" + "github.com/babylonchain/finality-provider/finality-provider/config" fpstore "github.com/babylonchain/finality-provider/finality-provider/store" "github.com/babylonchain/finality-provider/testutil" ) @@ -18,28 +19,62 @@ func FuzzFinalityProvidersStore(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - dbPath := filepath.Join(t.TempDir(), "db") - dbcfg := testutil.GenDBConfig(r, t) - vs, err := fpstore.NewFinalityProviderStore(dbPath, dbcfg.Name, dbcfg.Backend) + homePath := t.TempDir() + cfg := config.DefaultDBConfigWithHomePath(homePath) + + fpdb, err := cfg.GetDbBackend() + require.NoError(t, err) + vs, err := fpstore.NewFinalityProviderStore(fpdb) require.NoError(t, err) defer func() { - err := os.RemoveAll(dbPath) + err := fpdb.Close() + require.NoError(t, err) + err = os.RemoveAll(homePath) require.NoError(t, err) }() fp := testutil.GenRandomFinalityProvider(r, t) - err = vs.SaveFinalityProvider(fp) + // create the fp for the first time + err = vs.CreateFinalityProvider( + fp.ChainPk, + fp.BtcPk, + fp.Description, + fp.Commission, + fp.MasterPubRand, + fp.KeyName, + fp.ChainID, + fp.Pop.ChainSig, + fp.Pop.BtcSig, + ) require.NoError(t, err) - fpList, err := vs.ListFinalityProviders() + // create same finality provider again + // and expect duplicate error + err = vs.CreateFinalityProvider( + fp.ChainPk, + fp.BtcPk, + fp.Description, + fp.Commission, + fp.KeyName, + fp.MasterPubRand, + fp.ChainID, + fp.Pop.ChainSig, + fp.Pop.BtcSig, + ) + require.ErrorIs(t, err, fpstore.ErrDuplicateFinalityProvider) + + fpList, err := vs.GetAllStoredFinalityProviders() require.NoError(t, err) - require.Equal(t, fp.BtcPk, fpList[0].BtcPk) + require.True(t, fp.BtcPk.IsEqual(fpList[0].BtcPk)) - actualFp, err := vs.GetStoreFinalityProvider(fp.BtcPk) + actualFp, err := vs.GetFinalityProvider(fp.BtcPk) require.NoError(t, err) - require.Equal(t, fp.BabylonPk, actualFp.BabylonPk) require.Equal(t, fp.BtcPk, actualFp.BtcPk) - require.Equal(t, fp.KeyName, actualFp.KeyName) + + _, randomBtcPk, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + _, err = vs.GetFinalityProvider(randomBtcPk) + require.ErrorIs(t, err, fpstore.ErrFinalityProviderNotFound) }) } diff --git a/finality-provider/store/storedfp.go b/finality-provider/store/storedfp.go new file mode 100644 index 00000000..1bed2abd --- /dev/null +++ b/finality-provider/store/storedfp.go @@ -0,0 +1,94 @@ +package store + +import ( + "encoding/hex" + "fmt" + + sdkmath "cosmossdk.io/math" + bbn "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/babylonchain/finality-provider/finality-provider/proto" +) + +type StoredFinalityProvider struct { + ChainPk *secp256k1.PubKey + BtcPk *btcec.PublicKey + Description *stakingtypes.Description + Commission *sdkmath.LegacyDec + Pop *proto.ProofOfPossession + RegisteredEpoch uint64 + MasterPubRand string + KeyName string + ChainID string + LastVotedHeight uint64 + LastProcessedHeight uint64 + Status proto.FinalityProviderStatus +} + +func protoFpToStoredFinalityProvider(fp *proto.FinalityProvider) (*StoredFinalityProvider, error) { + chainPk := &secp256k1.PubKey{Key: fp.ChainPk} + btcPk, err := schnorr.ParsePubKey(fp.BtcPk) + if err != nil { + return nil, fmt.Errorf("invalid BTC public key: %w", err) + } + + var des stakingtypes.Description + if err := des.Unmarshal(fp.Description); err != nil { + return nil, fmt.Errorf("invalid description: %w", err) + } + + commission, err := sdkmath.LegacyNewDecFromStr(fp.Commission) + if err != nil { + return nil, fmt.Errorf("invalid commission: %w", err) + } + + return &StoredFinalityProvider{ + ChainPk: chainPk, + BtcPk: btcPk, + Description: &des, + Commission: &commission, + Pop: &proto.ProofOfPossession{ + ChainSig: fp.Pop.ChainSig, + BtcSig: fp.Pop.BtcSig, + }, + RegisteredEpoch: fp.RegisteredEpoch, + MasterPubRand: fp.MasterPubRand, + KeyName: fp.KeyName, + ChainID: fp.ChainId, + LastVotedHeight: fp.LastVotedHeight, + LastProcessedHeight: fp.LastProcessedHeight, + Status: fp.Status, + }, nil +} + +func (sfp *StoredFinalityProvider) GetChainPkHexString() string { + return hex.EncodeToString(sfp.ChainPk.Key) +} + +func (sfp *StoredFinalityProvider) GetBIP340BTCPK() *bbn.BIP340PubKey { + return bbn.NewBIP340PubKeyFromBTCPK(sfp.BtcPk) +} + +func (sfp *StoredFinalityProvider) ToFinalityProviderInfo() *proto.FinalityProviderInfo { + return &proto.FinalityProviderInfo{ + ChainPkHex: sfp.GetChainPkHexString(), + BtcPkHex: sfp.GetBIP340BTCPK().MarshalHex(), + Description: &proto.Description{ + Moniker: sfp.Description.Moniker, + Identity: sfp.Description.Identity, + Website: sfp.Description.Website, + SecurityContact: sfp.Description.SecurityContact, + Details: sfp.Description.Details, + }, + Pop: sfp.Pop, + RegisteredEpoch: sfp.RegisteredEpoch, + MasterPubRand: sfp.MasterPubRand, + Commission: sfp.Commission.String(), + LastVotedHeight: sfp.LastVotedHeight, + Status: sfp.Status.String(), + } +} diff --git a/go.mod b/go.mod index ff2e9477..46201905 100644 --- a/go.mod +++ b/go.mod @@ -6,51 +6,51 @@ toolchain go1.21.4 require ( cosmossdk.io/errors v1.0.1 - cosmossdk.io/math v1.2.0 + cosmossdk.io/math v1.3.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonchain/babylon v0.8.0 - github.com/babylonchain/rpc-client v0.8.0 + github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b github.com/btcsuite/btcd v0.24.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.5 - github.com/cosmos/cosmos-proto v1.0.0-beta.3 - github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 + github.com/btcsuite/btcwallet/walletdb v1.4.0 + github.com/cosmos/cosmos-proto v1.0.0-beta.4 + github.com/cosmos/cosmos-sdk v0.50.5 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.11 - github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 + github.com/cosmos/relayer/v2 v2.5.2 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 github.com/jessevdk/go-flags v1.5.0 github.com/jsternberg/zap-logfmt v1.3.0 github.com/lightningnetwork/lnd v0.16.4-beta.rc1 - github.com/stretchr/testify v1.8.4 + github.com/lightningnetwork/lnd/kvdb v1.4.1 + github.com/prometheus/client_golang v1.18.0 + github.com/stretchr/testify v1.9.0 github.com/urfave/cli v1.22.14 - go.etcd.io/bbolt v1.3.8 go.uber.org/atomic v1.10.0 go.uber.org/zap v1.26.0 - google.golang.org/grpc v1.60.1 - google.golang.org/protobuf v1.32.0 + google.golang.org/grpc v1.62.0 + google.golang.org/protobuf v1.33.0 ) require ( - cloud.google.com/go v0.110.10 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect - cosmossdk.io/api v0.7.2 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/storage v1.36.0 // indirect + cosmossdk.io/api v0.7.3 // indirect cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect - cosmossdk.io/log v1.3.0 // indirect + cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/store v1.0.2 // indirect cosmossdk.io/x/circuit v0.1.0 // indirect cosmossdk.io/x/evidence v0.1.0 // indirect cosmossdk.io/x/feegrant v0.1.0 // indirect cosmossdk.io/x/nft v0.1.0 // indirect - cosmossdk.io/x/tx v0.13.0 // indirect + cosmossdk.io/x/tx v0.13.1 // indirect cosmossdk.io/x/upgrade v0.1.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -60,11 +60,12 @@ require ( github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/aead/siphash v1.0.1 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/aws/aws-sdk-go v1.44.312 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect - github.com/bits-and-blooms/bitset v1.8.0 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect @@ -75,18 +76,20 @@ require ( github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v0.38.5 // indirect github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.0 // indirect + github.com/cosmos/cosmos-db v1.0.2 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v1.0.0 // indirect + github.com/cosmos/iavl v1.0.1 // indirect github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect github.com/cosmos/ibc-go/v8 v8.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect @@ -96,48 +99,53 @@ require ( github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/distribution/reference v0.5.0 // indirect - github.com/docker/docker v23.0.8+incompatible // indirect + github.com/docker/docker v24.0.9+incompatible // indirect + github.com/dsnet/compress v0.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect - github.com/emicklei/dot v1.6.0 // indirect + github.com/emicklei/dot v1.6.1 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.13.5 // indirect + github.com/ethereum/go-ethereum v1.13.15 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fergusstrange/embedded-postgres v1.10.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/getsentry/sentry-go v0.25.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-stack/stack v1.8.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect - github.com/gtank/merlin v0.1.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.2 // indirect + github.com/hashicorp/go-getter v1.7.4 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.1 // indirect @@ -148,91 +156,143 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect - github.com/holiman/uint256 v1.2.3 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/huandu/skiplist v1.2.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.3 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.3 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/jackc/pgx/v4 v4.18.2 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/linxGnu/grocksdb v1.8.6 // indirect + github.com/lightningnetwork/lnd/healthcheck v1.2.2 // indirect + github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect + github.com/lightningnetwork/lnd/tor v1.1.0 // indirect + github.com/linxGnu/grocksdb v1.8.12 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mholt/archiver/v3 v3.5.0 // indirect + github.com/miekg/dns v1.1.43 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/nwaples/rardecode v1.1.2 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect + github.com/pierrec/lz4/v4 v4.1.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.31.0 // indirect + github.com/rs/zerolog v1.32.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/soheilhy/cmux v0.1.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect - github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 // indirect + github.com/strangelove-ventures/cometbft-client v0.1.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.8 // indirect + go.etcd.io/etcd/api/v3 v3.5.10 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect + go.etcd.io/etcd/client/v2 v2.305.10 // indirect + go.etcd.io/etcd/client/v3 v3.5.10 // indirect + go.etcd.io/etcd/pkg/v3 v3.5.7 // indirect + go.etcd.io/etcd/raft/v3 v3.5.7 // indirect + go.etcd.io/etcd/server/v3 v3.5.7 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v0.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.153.0 // indirect + golang.org/x/tools v0.18.0 // indirect + google.golang.org/api v0.162.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.4.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index ffc99b3b..4fbc1398 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= -cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -68,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -109,8 +109,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= @@ -171,8 +171,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= -cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= -cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.3 h1:V815i8YOwOAQa1rLCsSMjVG5Gnzs02JLq+l7ks8s1jk= +cosmossdk.io/api v0.7.3/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -196,10 +196,10 @@ cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98ok cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= -cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo= -cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= -cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= -cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= +cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= +cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= @@ -210,8 +210,8 @@ cosmossdk.io/x/feegrant v0.1.0 h1:c7s3oAq/8/UO0EiN1H5BIjwVntujVTkYs35YPvvrdQk= cosmossdk.io/x/feegrant v0.1.0/go.mod h1:4r+FsViJRpcZif/yhTn+E0E6OFfg4n0Lx+6cCtnZElU= cosmossdk.io/x/nft v0.1.0 h1:VhcsFiEK33ODN27kxKLa0r/CeFd8laBfbDBwYqCyYCM= cosmossdk.io/x/nft v0.1.0/go.mod h1:ec4j4QAO4mJZ+45jeYRnW7awLHby1JZANqe1hNZ4S3g= -cosmossdk.io/x/tx v0.13.0 h1:8lzyOh3zONPpZv2uTcUmsv0WTXy6T1/aCVDCqShmpzU= -cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/tx v0.13.1 h1:Mg+EMp67Pz+NukbJqYxuo8uRp7N/a9uR+oVS9pONtj8= +cosmossdk.io/x/tx v0.13.1/go.mod h1:CBCU6fsRVz23QGFIQBb1DNX2DztJCf3jWyEkHY2nJQ0= cosmossdk.io/x/upgrade v0.1.0 h1:z1ZZG4UL9ICTNbJDYZ6jOnF9GdEK9wyoEFi4BUScHXE= cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -222,10 +222,9 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= -github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/CosmWasm/wasmd v0.50.0 h1:NVaGqCSTRfb9UTDHJwT6nQIWcb6VjlQl88iI+u1+qjE= github.com/CosmWasm/wasmd v0.50.0/go.mod h1:UjmShW4l9YxaMytwJZ7IB7MWzHiynSZP3DdWrG0FRtk= github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= @@ -235,6 +234,10 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= @@ -259,6 +262,9 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= @@ -275,10 +281,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon v0.8.0 h1:QC04LPCFBD0MZyiM3cAjVBlr3CXEZPdhORWPBlO2gaQ= -github.com/babylonchain/babylon v0.8.0/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= -github.com/babylonchain/rpc-client v0.8.0 h1:H7VN7dTR1Z6uffRrziFRD9FTj+1Jf3u9gL2RLm3z9Jo= -github.com/babylonchain/rpc-client v0.8.0/go.mod h1:+7IiKHmIAmfM888hPpfAVmGs85yZRxfbJym4swmgKG8= +github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b h1:HfjAGZiebrcInFAq8Lk8MXbKbtTYxRoO65vfLPOCXzw= +github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b/go.mod h1:lfeASLNJgcUsX7LEns3HRUv0k+MjzcB2q2AMasfz38M= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -289,12 +293,13 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= -github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= @@ -313,6 +318,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcwallet/walletdb v1.4.0 h1:/C5JRF+dTuE2CNMCO/or5N8epsrhmSM4710uBQoYPTQ= +github.com/btcsuite/btcwallet/walletdb v1.4.0/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= @@ -357,6 +364,10 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -366,8 +377,8 @@ github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZ github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb h1:6Po+YYKT5B5ZXN0wd2rwFBaebM0LufPf8p4zxOd48Kg= -github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= @@ -386,19 +397,23 @@ github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1A github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0E= -github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= -github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= -github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= -github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 h1:Pjvcy7wHUoYh253LvNv5Dyx+d3SNkRPsDZH+FytqZ3w= -github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987/go.mod h1:0D9mrUy1eAUMQuvYzf2xvhEPk2ta9w7XH1zcYvyFiuM= +github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= +github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= +github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= +github.com/cosmos/cosmos-sdk v0.50.5 h1:MOEi+DKYgW67YaPgB+Pf+nHbD3V9S/ayitRKJYLfGIA= +github.com/cosmos/cosmos-sdk v0.50.5/go.mod h1:oV/k6GJgXV9QPoM2fsYDPPsyPBgQbdotv532O6Mz1OQ= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -406,8 +421,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v1.0.0 h1:bw6t0Mv/mVCJvlMTOPHWLs5uUE3BRBfVWCRelOzl+so= -github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/iavl v1.0.1 h1:D+mYbcRO2wptYzOM1Hxl9cpmmHU1ZEt9T2Wv5nZTeUw= +github.com/cosmos/iavl v1.0.1/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOhg= @@ -418,17 +433,17 @@ github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= -github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483 h1:l8Elru92qhdzwJdOYDEKcDfFPEdPPFH5jTRL7OZWGMA= -github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483/go.mod h1:eBKSRbCx2zhqpvzZG4+HcDacWz4BywqgcLBkiyzuGYI= +github.com/cosmos/relayer/v2 v2.5.2 h1:AF0MOo1GvJo94QNB996fBHdKlH+vrIY3JcFNrIvZNP0= +github.com/cosmos/relayer/v2 v2.5.2/go.mod h1:h4Ng2QsVpxExIq5S+WvLr8slDb9MSBh82gQS4DeMwDo= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= -github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= @@ -458,12 +473,15 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v23.0.8+incompatible h1:z4ZCIwfqHgOEwhxmAWugSL1PFtPQmLP60EVhJYJPaX8= -github.com/docker/docker v23.0.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -474,8 +492,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emicklei/dot v1.6.0 h1:vUzuoVE8ipzS7QkES4UfxdpCwdU2U97m2Pb2tQCoYRY= -github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI= +github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -487,16 +505,20 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= -github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= +github.com/ethereum/go-ethereum v1.13.15 h1:U7sSGYGo4SPjP6iNIifNoyIAiNjrmQkz6EwQG+/EZWo= +github.com/ethereum/go-ethereum v1.13.15/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg= +github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -507,8 +529,10 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= -github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -533,8 +557,13 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -547,8 +576,6 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= @@ -564,10 +591,15 @@ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -605,9 +637,10 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -660,6 +693,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -667,8 +702,8 @@ github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -696,22 +731,20 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= -github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= -github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -719,8 +752,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.2 h1:uJDtyXwEfalmp1PqdxuhZqrNkUyClZAhVeZYTArbqkg= -github.com/hashicorp/go-getter v1.7.2/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= +github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -762,8 +795,8 @@ github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7H github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= -github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= @@ -780,6 +813,53 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= +github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= +github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= +github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= @@ -796,6 +876,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -814,24 +896,34 @@ github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuy github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -842,16 +934,30 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightningnetwork/lnd v0.16.4-beta.rc1 h1:L8ktsv1lM5esVtiOlEtOBqU1dCoDckbm0FkcketBskQ= github.com/lightningnetwork/lnd v0.16.4-beta.rc1/go.mod h1:sK9F98TpFuO/fjLCX4jEjc65qr2GZGs8IquVde1N46I= +github.com/lightningnetwork/lnd/healthcheck v1.2.2 h1:im+qcpgSuteqRCGeorT9yqVXuLrS6A7/acYzGgarMS4= +github.com/lightningnetwork/lnd/healthcheck v1.2.2/go.mod h1:IWY0GChlarRbXFkFDdE4WY5POYJabe/7/H1iCZt4ZKs= +github.com/lightningnetwork/lnd/kvdb v1.4.1 h1:l/nLBPLbdvP/lajMtrFMLzAi5OoLTH3+zUU6SwoEEv8= +github.com/lightningnetwork/lnd/kvdb v1.4.1/go.mod h1:f+F7Da8HTa8MePFsdWvusGRdcmWTgSWykGsVyC02Z5M= +github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= +github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= +github.com/lightningnetwork/lnd/tor v1.0.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= +github.com/lightningnetwork/lnd/tor v1.1.0 h1:iXO7fSzjxTI+p88KmtpbuyuRJeNfgtpl9QeaAliILXE= +github.com/lightningnetwork/lnd/tor v1.1.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= -github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.12 h1:1/pCztQUOa3BX/1gR3jSZDoaKFpeHFvQ1XrqZpSvZVo= +github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -859,12 +965,16 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -875,13 +985,14 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= -github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= -github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -921,6 +1032,9 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= +github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -976,6 +1090,9 @@ github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6 github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -994,24 +1111,24 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= +github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1025,20 +1142,25 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5X github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1051,19 +1173,26 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= @@ -1088,16 +1217,18 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 h1:sOdCYxFMTVbEGvJ6LfjQsm+tQbB5YdUpvMcXJnHBFm4= -github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3/go.mod h1:Jgux5ULdCs9N7ARy9NHe+hPfJQhUFpYF6+/+gmcqsGw= +github.com/strangelove-ventures/cometbft-client v0.1.0 h1:fcA652QaaR0LDnyJOZVjZKtuyAawnVXaq/p1MWJSYD4= +github.com/strangelove-ventures/cometbft-client v0.1.0/go.mod h1:QzThgjzvsGgUNVNpGPitmxOWMIhp6a0oqf80nCRNt/0= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1108,8 +1239,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= @@ -1125,6 +1257,8 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= @@ -1134,6 +1268,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -1143,6 +1279,9 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/vulpine-io/io-test v1.0.0 h1:Ot8vMh+ssm1VWDAwJ3U4C5qG9aRnr5YfQFZPNZBAUGI= github.com/vulpine-io/io-test v1.0.0/go.mod h1:X1I+p5GCxVX9m4nFd1HBtr2bVX9v1ZE6x8w+Obt36AU= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1151,14 +1290,30 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k= +go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= +go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0= +go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= +go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4= +go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= +go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao= +go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= +go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= +go.etcd.io/etcd/pkg/v3 v3.5.7/go.mod h1:kcOfWt3Ov9zgYdOiJ/o1Y9zFfLhQjylTgL4Lru8opRo= +go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= +go.etcd.io/etcd/raft/v3 v3.5.7/go.mod h1:TflkAb/8Uy6JFBxcRaH2Fr6Slm9mCPVdI2efzxY96yU= +go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= +go.etcd.io/etcd/server/v3 v3.5.7/go.mod h1:gxBgT84issUVBRpZ3XkW1T55NjOb4vZZRI4wVvNhf4A= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -1170,10 +1325,32 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -1182,10 +1359,12 @@ go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= @@ -1196,15 +1375,20 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1216,8 +1400,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1244,8 +1428,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1287,6 +1471,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1294,6 +1479,7 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1306,8 +1492,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1333,8 +1519,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1349,8 +1535,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1362,7 +1548,9 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1371,6 +1559,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1407,11 +1596,13 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1441,6 +1632,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1448,13 +1640,14 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1483,12 +1676,14 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1534,8 +1729,10 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1594,8 +1791,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= -google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.162.0 h1:Vhs54HkaEpkMBdgGdOT2P6F0csGG/vxDS0hWHJzmmps= +google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1713,12 +1910,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= -google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= -google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY= -google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c h1:NUsgEN92SQQqzfA+YtqYNqYmB3DMMYLlIwUZAQFVFbo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1751,6 +1948,7 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= @@ -1760,8 +1958,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1778,8 +1976,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1792,8 +1990,11 @@ gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -1822,6 +2023,34 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk= +modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs= +modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= +modernc.org/tcl v1.15.0/go.mod h1:xRoGotBZ6dU+Zo2tca+2EqVEeMmOUBzHnhIwq4YrVnE= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= +modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index f5e63e20..eb53b360 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -130,6 +130,7 @@ func NewBabylonNodeHandler(t *testing.T, covenantQuorum int, covenantPks []*type "--keyring-backend=test", "--chain-id=chain-test", "--additional-sender-account", + fmt.Sprintf("--epoch-interval=%d", 5), fmt.Sprintf("--slashing-address=%s", slashingAddr), fmt.Sprintf("--covenant-quorum=%d", covenantQuorum), fmt.Sprintf("--covenant-pks=%s", strings.Join(covenantPksStr, ",")), diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 4139b3fe..44cde78b 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" - "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/finality-provider/proto" "github.com/babylonchain/finality-provider/types" ) @@ -26,22 +26,21 @@ var ( // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestFinalityProviderLifeCycle(t *testing.T) { - tm, fpInsList := StartManagerWithFinalityProvider(t, 1) + tm, fpInsList, _ := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) fpIns := fpInsList[0] - // check the public randomness is committed - tm.WaitForFpPubRandCommitted(t, fpIns) - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.GetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) + delsResp := tm.WaitForNPendingDels(t, 1) + del, err := ParseRespBTCDelToBTCDel(delsResp[0]) + require.NoError(t, err) // send covenant sigs - tm.InsertCovenantSigForDelegation(t, dels[0]) + tm.InsertCovenantSigForDelegation(t, del) // check the BTC delegation is active _ = tm.WaitForNActiveDels(t, 1) @@ -56,22 +55,21 @@ func TestFinalityProviderLifeCycle(t *testing.T) { // sends a finality vote over a conflicting block // in this case, the BTC private key should be extracted by Babylon func TestDoubleSigning(t *testing.T) { - tm, fpInsList := StartManagerWithFinalityProvider(t, 1) + tm, fpInsList, _ := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) fpIns := fpInsList[0] - // check the public randomness is committed - tm.WaitForFpPubRandCommitted(t, fpIns) - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.GetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) + delsResp := tm.WaitForNPendingDels(t, 1) + del, err := ParseRespBTCDelToBTCDel(delsResp[0]) + require.NoError(t, err) // send covenant sigs - tm.InsertCovenantSigForDelegation(t, dels[0]) + tm.InsertCovenantSigForDelegation(t, del) // check the BTC delegation is active _ = tm.WaitForNActiveDels(t, 1) @@ -103,35 +101,34 @@ func TestDoubleSigning(t *testing.T) { // try to start all the finality providers and the slashed one should not be restarted err = tm.Fpa.StartHandlingAll() require.NoError(t, err) - fps := tm.Fpa.ListFinalityProviderInstances() - require.Equal(t, 0, len(fps)) + fps, err := tm.Fpa.ListAllFinalityProvidersInfo() + require.NoError(t, err) + require.Equal(t, 1, len(fps)) + require.Equal(t, proto.FinalityProviderStatus_name[4], fps[0].Status) + require.Equal(t, false, fps[0].IsRunning) } // TestMultipleFinalityProviders tests starting with multiple finality providers func TestMultipleFinalityProviders(t *testing.T) { n := 3 - tm, fpInstances := StartManagerWithFinalityProvider(t, n) + tm, fpInstances, _ := StartManagerWithFinalityProvider(t, n) defer tm.Stop(t) // submit BTC delegations for each finality-provider for _, fpIns := range fpInstances { - tm.Wg.Add(1) - go func(fpi *service.FinalityProviderInstance) { - defer tm.Wg.Done() - // check the public randomness is committed - tm.WaitForFpPubRandCommitted(t, fpi) - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpi.MustGetBtcPk()}, stakingTime, stakingAmount) - }(fpIns) + // send a BTC delegation + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.GetBtcPk()}, stakingTime, stakingAmount) } tm.Wg.Wait() // check the BTC delegations are pending - dels := tm.WaitForNPendingDels(t, n) - require.Equal(t, n, len(dels)) + delsResp := tm.WaitForNPendingDels(t, n) + require.Equal(t, n, len(delsResp)) // send covenant sigs to each of the delegations - for _, d := range dels { + for _, delResp := range delsResp { + d, err := ParseRespBTCDelToBTCDel(delResp) + require.NoError(t, err) // send covenant sigs tm.InsertCovenantSigForDelegation(t, d) } @@ -145,22 +142,21 @@ func TestMultipleFinalityProviders(t *testing.T) { // TestFastSync tests the fast sync process where the finality-provider is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm, fpInsList := StartManagerWithFinalityProvider(t, 1) + tm, fpInsList, _ := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) fpIns := fpInsList[0] - // check the public randomness is committed - tm.WaitForFpPubRandCommitted(t, fpIns) - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.GetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) + delsResp := tm.WaitForNPendingDels(t, 1) + del, err := ParseRespBTCDelToBTCDel(delsResp[0]) + require.NoError(t, err) // send covenant sigs - tm.InsertCovenantSigForDelegation(t, dels[0]) + tm.InsertCovenantSigForDelegation(t, del) // check the BTC delegation is active _ = tm.WaitForNActiveDels(t, 1) @@ -191,67 +187,3 @@ func TestFastSync(t *testing.T) { require.NoError(t, err) require.True(t, currentHeight < finalizedHeight+uint64(n)) } - -// TestFastSync_DuplicateVotes covers a special case when the finality signature -// has inconsistent view of last voted height with the Babylon node and during -// fast-sync it submits a batch of finality sigs, one of which is rejected due -// to duplicate error -// this test covers this case by starting 3 finality providers, 2 of which -// are stopped after gaining voting power to simulate the case where no blocks -// are finalized. Then we let one of the finality providers "forget" the last -// voted height and restart all the finality providers, expecting it them to -// catch up and finalize new blocks -func TestFastSync_DuplicateVotes(t *testing.T) { - tm, fpInsList := StartManagerWithFinalityProvider(t, 3) - defer tm.Stop(t) - - fpIns1 := fpInsList[0] - fpIns2 := fpInsList[1] - fpIns3 := fpInsList[2] - - // check the public randomness is committed - tm.WaitForFpPubRandCommitted(t, fpIns1) - tm.WaitForFpPubRandCommitted(t, fpIns2) - tm.WaitForFpPubRandCommitted(t, fpIns3) - - // send 3 BTC delegations to empower the three finality providers - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns1.MustGetBtcPk()}, stakingTime, stakingAmount) - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns2.MustGetBtcPk()}, stakingTime, stakingAmount) - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns3.MustGetBtcPk()}, stakingTime, stakingAmount) - - // check the BTC delegations are pending - dels := tm.WaitForNPendingDels(t, 3) - - // send covenant sigs to each delegation - tm.InsertCovenantSigForDelegation(t, dels[0]) - tm.InsertCovenantSigForDelegation(t, dels[1]) - tm.InsertCovenantSigForDelegation(t, dels[2]) - - // check the BTC delegations are active - _ = tm.WaitForNActiveDels(t, 3) - - // stop 2 of the finality providers so that no blocks will be finalized - err := fpIns2.Stop() - require.NoError(t, err) - err = fpIns3.Stop() - require.NoError(t, err) - - // make sure fp1 has cast a finality vote - // and then make it "forget" the last voted height - lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns1) - fpIns1.MustUpdateStateAfterFinalitySigSubmission(lastVotedHeight - 1) - - // stop fp1, restarts all the fps after 3 blocks for them to catch up - // and expect a block will be finalized - n := 3 - tm.FpConfig.FastSyncGap = uint64(n) - tm.StopAndRestartFpAfterNBlocks(t, n, fpIns1) - err = fpIns2.Start() - require.NoError(t, err) - err = fpIns3.Start() - require.NoError(t, err) - require.Eventually(t, func() bool { - finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) - return finalizedBlocks[0].Height > lastVotedHeight - }, eventuallyWaitTimeOut, eventuallyPollTime) -} diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go index 2c644500..fbdca9a6 100644 --- a/itest/eotsmanager_handler.go +++ b/itest/eotsmanager_handler.go @@ -22,11 +22,13 @@ func NewEOTSServerHandler(t *testing.T, cfg *config.Config, eotsHomeDir string) shutdownInterceptor, err := signal.Intercept() require.NoError(t, err) + dbBackend, err := cfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) logger := zap.NewNop() - eotsManager, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, cfg, logger) + eotsManager, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, cfg.KeyringBackend, dbBackend, logger) require.NoError(t, err) - eotsServer := service.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + eotsServer := service.NewEOTSManagerServer(cfg, logger, eotsManager, dbBackend, shutdownInterceptor) return &EOTSServerHandler{ t: t, diff --git a/itest/test_manager.go b/itest/test_manager.go index e89ec430..63af3876 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -1,6 +1,7 @@ package e2etest import ( + "encoding/hex" "math/rand" "os" "path/filepath" @@ -12,18 +13,21 @@ import ( sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/btcstaking" + txformat "github.com/babylonchain/babylon/btctxformatter" asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + ckpttypes "github.com/babylonchain/babylon/x/checkpointing/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdkquerytypes "github.com/cosmos/cosmos-sdk/types/query" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -102,14 +106,16 @@ func StartManager(t *testing.T) *TestManager { // 3. prepare EOTS manager eotsHomeDir := filepath.Join(testDir, "eots-home") - eotsCfg := defaultEOTSConfig() + eotsCfg := eotsconfig.DefaultConfigWithHomePath(eotsHomeDir) eh := NewEOTSServerHandler(t, eotsCfg, eotsHomeDir) eh.Start() eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) // 4. prepare finality-provider - fpApp, err := service.NewFinalityProviderApp(fpHomeDir, cfg, bc, eotsCli, logger) + fpdb, err := cfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + fpApp, err := service.NewFinalityProviderApp(cfg, bc, eotsCli, fpdb, logger) require.NoError(t, err) err = fpApp.Start() require.NoError(t, err) @@ -145,63 +151,74 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*service.FinalityProviderInstance) { +func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*service.FinalityProviderInstance, uint64) { tm := StartManager(t) app := tm.Fpa + // register all finality providers + registeredEpoch := uint64(0) + fpPKs := make([]*bbntypes.BIP340PubKey, 0, n) for i := 0; i < n; i++ { fpName := fpNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) commission := sdkmath.LegacyZeroDec() - desc, err := newDescription(moniker).Marshal() - require.NoError(t, err) + desc := newDescription(moniker) cfg := app.GetConfig() - _, err = service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, fpName, keyring.BackendTest, passphrase, hdPath) + _, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, fpName, keyring.BackendTest, passphrase, hdPath, "") require.NoError(t, err) res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, desc, &commission) require.NoError(t, err) - fpPk, err := bbntypes.NewBIP340PubKey(res.StoreFp.BtcPk) + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(res.FpInfo.BtcPkHex) require.NoError(t, err) - _, err = app.RegisterFinalityProvider(fpPk.MarshalHex()) + fpPKs = append(fpPKs, fpPk) + resp, err := app.RegisterFinalityProvider(fpPk.MarshalHex()) require.NoError(t, err) - err = app.StartHandlingFinalityProvider(fpPk, passphrase) + registeredEpoch = resp.RegisteredEpoch // last registered epoch + } + + // wait until the last registered epoch is finalised + tm.FinalizeUntilEpoch(t, registeredEpoch) + + for i := 0; i < n; i++ { + // start + err := app.StartHandlingFinalityProvider(fpPKs[i], passphrase) require.NoError(t, err) - fpIns, err := app.GetFinalityProviderInstance(fpPk) + fpIns, err := app.GetFinalityProviderInstance(fpPKs[i]) require.NoError(t, err) require.True(t, fpIns.IsRunning()) require.NoError(t, err) + } - // check finality providers on Babylon side - require.Eventually(t, func() bool { - fps, err := tm.BBNClient.QueryFinalityProviders() - if err != nil { - t.Logf("failed to query finality providers from Babylon %s", err.Error()) - return false - } + // check finality providers on Babylon side + require.Eventually(t, func() bool { + fps, err := tm.BBNClient.QueryFinalityProviders() + if err != nil { + t.Logf("failed to query finality providers from Babylon %s", err.Error()) + return false + } - if len(fps) != i+1 { + if len(fps) != n { + return false + } + + for _, fp := range fps { + if !strings.Contains(fp.Description.Moniker, monikerPrefix) { return false } - - for _, fp := range fps { - if !strings.Contains(fp.Description.Moniker, monikerPrefix) { - return false - } - if !fp.Commission.Equal(sdkmath.LegacyZeroDec()) { - return false - } + if !fp.Commission.Equal(sdkmath.LegacyZeroDec()) { + return false } + } - return true - }, eventuallyWaitTimeOut, eventuallyPollTime) - } + return true + }, eventuallyWaitTimeOut, eventuallyPollTime) fpInsList := app.ListFinalityProviderInstances() require.Equal(t, n, len(fpInsList)) t.Logf("the test manager is running with %v finality-provider(s)", len(fpInsList)) - return tm, fpInsList + return tm, fpInsList, registeredEpoch } func (tm *TestManager) Stop(t *testing.T) { @@ -226,21 +243,9 @@ func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey t.Logf("the finality-provider is successfully registered") } -func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.FinalityProviderInstance) { - require.Eventually(t, func() bool { - lastCommittedHeight, err := fpIns.GetLastCommittedHeight() - if err != nil { - return false - } - return lastCommittedHeight > 0 - }, eventuallyWaitTimeOut, eventuallyPollTime) - - t.Logf("public randomness is successfully committed") -} - -func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDelegation { +func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDelegationResponse { var ( - dels []*bstypes.BTCDelegation + dels []*bstypes.BTCDelegationResponse err error ) require.Eventually(t, func() bool { @@ -258,9 +263,9 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe return dels } -func (tm *TestManager) WaitForNActiveDels(t *testing.T, n int) []*bstypes.BTCDelegation { +func (tm *TestManager) WaitForNActiveDels(t *testing.T, n int) []*bstypes.BTCDelegationResponse { var ( - dels []*bstypes.BTCDelegation + dels []*bstypes.BTCDelegationResponse err error ) require.Eventually(t, func() bool { @@ -541,15 +546,17 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe require.NoError(t, err) // create and insert BTC headers which include the staking tx to get staking tx info - currentBtcTip, err := tm.BBNClient.QueryBtcLightClientTip() + btcTipHeaderResp, err := tm.BBNClient.QueryBtcLightClientTip() + require.NoError(t, err) + tipHeader, err := bbntypes.NewBTCHeaderBytesFromHex(btcTipHeaderResp.HeaderHex) require.NoError(t, err) - blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), testStakingInfo.StakingTx) + blockWithStakingTx := datagen.CreateBlockWithTransaction(r, tipHeader.ToBlockHeader(), testStakingInfo.StakingTx) accumulatedWork := btclctypes.CalcWork(&blockWithStakingTx.HeaderBytes) - accumulatedWork = btclctypes.CumulativeWork(accumulatedWork, *currentBtcTip.Work) + accumulatedWork = btclctypes.CumulativeWork(accumulatedWork, btcTipHeaderResp.Work) parentBlockHeaderInfo := &btclctypes.BTCHeaderInfo{ Header: &blockWithStakingTx.HeaderBytes, Hash: blockWithStakingTx.HeaderBytes.Hash(), - Height: currentBtcTip.Height + 1, + Height: btcTipHeaderResp.Height + 1, Work: &accumulatedWork, } headers := make([]bbntypes.BTCHeaderBytes, 0) @@ -667,12 +674,6 @@ func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { return &cfg } -func defaultEOTSConfig() *eotsconfig.Config { - cfg := eotsconfig.DefaultConfig() - - return &cfg -} - func tempDirWithName(name string) (string, error) { tempPath := os.TempDir() @@ -694,3 +695,184 @@ func newDescription(moniker string) *stakingtypes.Description { dec := stakingtypes.NewDescription(moniker, "", "", "", "") return &dec } + +// ParseRespBTCDelToBTCDel parses an BTC delegation response to BTC Delegation +// adapted from +// https://github.com/babylonchain/babylon/blob/1a3c50da64885452c8d669fcea2a2fad78c8a028/test/e2e/btc_staking_e2e_test.go#L548 +func ParseRespBTCDelToBTCDel(resp *bstypes.BTCDelegationResponse) (btcDel *bstypes.BTCDelegation, err error) { + stakingTx, err := hex.DecodeString(resp.StakingTxHex) + if err != nil { + return nil, err + } + + delSig, err := bbntypes.NewBIP340SignatureFromHex(resp.DelegatorSlashSigHex) + if err != nil { + return nil, err + } + + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(resp.SlashingTxHex) + if err != nil { + return nil, err + } + + btcDel = &bstypes.BTCDelegation{ + // missing BabylonPk, Pop + // these fields are not sent out to the client on BTCDelegationResponse + BtcPk: resp.BtcPk, + FpBtcPkList: resp.FpBtcPkList, + StartHeight: resp.StartHeight, + EndHeight: resp.EndHeight, + TotalSat: resp.TotalSat, + StakingTx: stakingTx, + DelegatorSig: delSig, + StakingOutputIdx: resp.StakingOutputIdx, + CovenantSigs: resp.CovenantSigs, + UnbondingTime: resp.UnbondingTime, + SlashingTx: slashingTx, + } + + if resp.UndelegationResponse != nil { + ud := resp.UndelegationResponse + unbondTx, err := hex.DecodeString(ud.UnbondingTxHex) + if err != nil { + return nil, err + } + + slashTx, err := bstypes.NewBTCSlashingTxFromHex(ud.SlashingTxHex) + if err != nil { + return nil, err + } + + delSlashingSig, err := bbntypes.NewBIP340SignatureFromHex(ud.DelegatorSlashingSigHex) + if err != nil { + return nil, err + } + + btcDel.BtcUndelegation = &bstypes.BTCUndelegation{ + UnbondingTx: unbondTx, + CovenantUnbondingSigList: ud.CovenantUnbondingSigList, + CovenantSlashingSigs: ud.CovenantSlashingSigs, + SlashingTx: slashTx, + DelegatorSlashingSig: delSlashingSig, + } + + if len(ud.DelegatorUnbondingSigHex) > 0 { + delUnbondingSig, err := bbntypes.NewBIP340SignatureFromHex(ud.DelegatorUnbondingSigHex) + if err != nil { + return nil, err + } + btcDel.BtcUndelegation.DelegatorUnbondingSig = delUnbondingSig + } + } + + return btcDel, nil +} + +func (tm *TestManager) InsertWBTCHeaders(t *testing.T, r *rand.Rand) { + params, err := tm.BBNClient.QueryStakingParams() + require.NoError(t, err) + btcTipResp, err := tm.BBNClient.QueryBtcLightClientTip() + require.NoError(t, err) + tipHeader, err := bbntypes.NewBTCHeaderBytesFromHex(btcTipResp.HeaderHex) + require.NoError(t, err) + kHeaders := datagen.NewBTCHeaderChainFromParentInfo(r, &btclctypes.BTCHeaderInfo{ + Header: &tipHeader, + Hash: tipHeader.Hash(), + Height: btcTipResp.Height, + Work: &btcTipResp.Work, + }, uint32(params.FinalizationTimeoutBlocks)) + _, err = tm.BBNClient.InsertBtcBlockHeaders(kHeaders.ChainToBytes()) + require.NoError(t, err) +} + +func (tm *TestManager) FinalizeUntilEpoch(t *testing.T, epoch uint64) { + bbnClient := tm.BBNClient.GetBBNClient() + + // wait until the checkpoint of this epoch is sealed + require.Eventually(t, func() bool { + lastSealedCkpt, err := bbnClient.LatestEpochFromStatus(ckpttypes.Sealed) + if err != nil { + return false + } + return epoch <= lastSealedCkpt.RawCheckpoint.EpochNum + }, eventuallyWaitTimeOut, 1*time.Second) + + t.Logf("start finalizing epochs till %d", epoch) + // Random source for the generation of BTC data + r := rand.New(rand.NewSource(time.Now().Unix())) + + // get all checkpoints of these epochs + pagination := &sdkquerytypes.PageRequest{ + Key: ckpttypes.CkptsObjectKey(1), + Limit: epoch, + } + resp, err := bbnClient.RawCheckpoints(pagination) + require.NoError(t, err) + require.Equal(t, int(epoch), len(resp.RawCheckpoints)) + + submitter := tm.BBNClient.GetKeyAddress() + + for _, checkpoint := range resp.RawCheckpoints { + currentBtcTipResp, err := tm.BBNClient.QueryBtcLightClientTip() + require.NoError(t, err) + tipHeader, err := bbntypes.NewBTCHeaderBytesFromHex(currentBtcTipResp.HeaderHex) + require.NoError(t, err) + + rawCheckpoint, err := checkpoint.Ckpt.ToRawCheckpoint() + require.NoError(t, err) + + btcCheckpoint, err := ckpttypes.FromRawCkptToBTCCkpt(rawCheckpoint, submitter) + require.NoError(t, err) + + babylonTagBytes, err := hex.DecodeString("01020304") + require.NoError(t, err) + + p1, p2, err := txformat.EncodeCheckpointData( + babylonTagBytes, + txformat.CurrentVersion, + btcCheckpoint, + ) + require.NoError(t, err) + + tx1 := datagen.CreatOpReturnTransaction(r, p1) + + opReturn1 := datagen.CreateBlockWithTransaction(r, tipHeader.ToBlockHeader(), tx1) + tx2 := datagen.CreatOpReturnTransaction(r, p2) + opReturn2 := datagen.CreateBlockWithTransaction(r, opReturn1.HeaderBytes.ToBlockHeader(), tx2) + + // insert headers and proofs + _, err = tm.BBNClient.InsertBtcBlockHeaders([]bbntypes.BTCHeaderBytes{ + opReturn1.HeaderBytes, + opReturn2.HeaderBytes, + }) + require.NoError(t, err) + + _, err = tm.BBNClient.InsertSpvProofs(submitter.String(), []*btcctypes.BTCSpvProof{ + opReturn1.SpvProof, + opReturn2.SpvProof, + }) + require.NoError(t, err) + + // wait until this checkpoint is submitted + require.Eventually(t, func() bool { + ckpt, err := bbnClient.RawCheckpoint(checkpoint.Ckpt.EpochNum) + require.NoError(t, err) + return ckpt.RawCheckpoint.Status == ckpttypes.Submitted + }, eventuallyWaitTimeOut, eventuallyPollTime) + } + + // insert w BTC headers + tm.InsertWBTCHeaders(t, r) + + // wait until the checkpoint of this epoch is finalised + require.Eventually(t, func() bool { + lastFinalizedCkpt, err := bbnClient.LatestEpochFromStatus(ckpttypes.Finalized) + if err != nil { + t.Logf("failed to get last finalized epoch: %v", err) + return false + } + return epoch <= lastFinalizedCkpt.RawCheckpoint.EpochNum + }, eventuallyWaitTimeOut, 1*time.Second) + + t.Logf("epoch %d is finalised", epoch) +} diff --git a/keyring/keyringcontroller.go b/keyring/keyringcontroller.go index 14e2cca7..c04224de 100644 --- a/keyring/keyringcontroller.go +++ b/keyring/keyringcontroller.go @@ -70,22 +70,24 @@ func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { return kc.kr } -func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*types.ChainKeyInfo, error) { +func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath, mnemonic string) (*types.ChainKeyInfo, error) { keyringAlgos, _ := kc.kr.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { return nil, err } - // read entropy seed straight from tmcrypto.Rand and convert to mnemonic - entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) - if err != nil { - return nil, err - } - - mnemonic, err := bip39.NewMnemonic(entropySeed) - if err != nil { - return nil, err + if len(mnemonic) == 0 { + // read entropy seed straight from tmcrypto.Rand and convert to mnemonic + entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + if err != nil { + return nil, err + } + + mnemonic, err = bip39.NewMnemonic(entropySeed) + if err != nil { + return nil, err + } } // we need to repeat the passphrase to mock the reentry diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go index d63c8a71..4f654d57 100644 --- a/keyring/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -8,14 +8,14 @@ import ( "go.uber.org/zap" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" - "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/stretchr/testify/require" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + fpkr "github.com/babylonchain/finality-provider/keyring" "github.com/babylonchain/finality-provider/eotsmanager" @@ -36,14 +36,16 @@ func FuzzCreatePoP(f *testing.F) { keyName := testutil.GenRandomHexStr(r, 4) sdkCtx := testutil.GenSdkContext(r, t) - chainID := testutil.GenRandomHexStr(r, 4) kc, err := fpkr.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) require.NoError(t, err) eotsHome := filepath.Join(t.TempDir(), "eots-home") - cfg := testutil.GenEOTSConfig(r, t) - em, err := eotsmanager.NewLocalEOTSManager(eotsHome, cfg, zap.NewNop()) + eotsCfg := eotscfg.DefaultConfigWithHomePath(eotsHome) + dbBackend, err := eotsCfg.DatabaseConfig.GetDbBackend() + require.NoError(t, err) + em, err := eotsmanager.NewLocalEOTSManager(eotsHome, eotsCfg.KeyringBackend, dbBackend, zap.NewNop()) defer func() { + dbBackend.Close() err := os.RemoveAll(eotsHome) require.NoError(t, err) }() @@ -53,18 +55,13 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) btcPk, err := types.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - keyInfo, err := kc.CreateChainKey(passphrase, hdPath) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath, "") require.NoError(t, err) bbnPk := &secp256k1.PubKey{Key: keyInfo.PublicKey.SerializeCompressed()} fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) require.NoError(t, err) - fp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) - - btcSig := new(types.BIP340Signature) - err = btcSig.Unmarshal(fp.Pop.BtcSig) - require.NoError(t, err) err = pop.Verify(bbnPk, btcPk, &chaincfg.SimNetParams) require.NoError(t, err) }) diff --git a/keyring/randgenerator.go b/keyring/randgenerator.go new file mode 100644 index 00000000..6183365d --- /dev/null +++ b/keyring/randgenerator.go @@ -0,0 +1,24 @@ +package keyring + +import ( + "crypto/hmac" + "crypto/sha256" + + "github.com/babylonchain/babylon/crypto/eots" +) + +// GenerateMasterRandPair generates pair of master secret/public randomness +// The result is deterministic with each given input +func GenerateMasterRandPair(key []byte, chainID []byte) (*eots.MasterSecretRand, *eots.MasterPublicRand, error) { + // calculate the random hash of the key concatenated with chainID and height + hasher := hmac.New(sha256.New, key) + hasher.Write(chainID) + seedSlice := hasher.Sum(nil) + + // convert to 32-byte seed + var seed [32]byte + copy(seed[:], seedSlice[:32]) + + // convert the hash into private random + return eots.NewMasterRandPairFromSeed(seed) +} diff --git a/log/log.go b/log/log.go index fd3643c4..791179c1 100644 --- a/log/log.go +++ b/log/log.go @@ -2,13 +2,14 @@ package log import ( "fmt" - "github.com/babylonchain/finality-provider/util" "io" "os" "path/filepath" "strings" "time" + "github.com/babylonchain/finality-provider/util" + zaplogfmt "github.com/jsternberg/zap-logfmt" "go.uber.org/zap" "go.uber.org/zap/zapcore" diff --git a/metrics/config.go b/metrics/config.go new file mode 100644 index 00000000..17bde531 --- /dev/null +++ b/metrics/config.go @@ -0,0 +1,56 @@ +package metrics + +import ( + "fmt" + "net" + "time" +) + +const ( + defaultFpMetricsPort = 2112 + defaultEotsMetricsPort = 2113 + defaultMetricsHost = "127.0.0.1" + defaultMetricsUpdateInterval = 100 * time.Millisecond +) + +type Config struct { + Host string `long:"host" description:"IP of the Prometheus server"` + Port int `long:"port" description:"Port of the Prometheus server"` + UpdateInterval time.Duration `long:"updateinterval" description:"The interval of Prometheus metrics updated"` +} + +func (cfg *Config) Validate() error { + if cfg.Port < 0 || cfg.Port > 65535 { + return fmt.Errorf("invalid port: %d", cfg.Port) + } + + ip := net.ParseIP(cfg.Host) + if ip == nil { + return fmt.Errorf("invalid host: %v", cfg.Host) + } + + return nil +} + +func (cfg *Config) Address() (string, error) { + if err := cfg.Validate(); err != nil { + return "", err + } + return fmt.Sprintf("%s:%d", cfg.Host, cfg.Port), nil +} + +func DefaultFpConfig() *Config { + return &Config{ + Port: defaultFpMetricsPort, + Host: defaultMetricsHost, + UpdateInterval: defaultMetricsUpdateInterval, + } +} + +func DefaultEotsConfig() *Config { + return &Config{ + Port: defaultEotsMetricsPort, + Host: defaultMetricsHost, + UpdateInterval: defaultMetricsUpdateInterval, + } +} diff --git a/metrics/eots_collectors.go b/metrics/eots_collectors.go new file mode 100644 index 00000000..f0221de4 --- /dev/null +++ b/metrics/eots_collectors.go @@ -0,0 +1,78 @@ +package metrics + +import ( + "sync" + + "github.com/prometheus/client_golang/prometheus" +) + +type EotsMetrics struct { + EotsCreatedKeysCounter prometheus.Counter + EotsFpTotalEotsSignCounter *prometheus.CounterVec + EotsFpLastEotsSignHeight *prometheus.GaugeVec + EotsFpTotalSchnorrSignCounter *prometheus.CounterVec +} + +var eotsMetricsRegisterOnce sync.Once + +var eotsMetricsInstance *EotsMetrics + +func NewEotsMetrics() *EotsMetrics { + eotsMetricsRegisterOnce.Do(func() { + eotsMetricsInstance = &EotsMetrics{ + EotsCreatedKeysCounter: prometheus.NewCounter(prometheus.CounterOpts{ + Name: "eots_created_keys_counter", + Help: "Total number of EOTS keys created", + }), + EotsFpTotalEotsSignCounter: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "eots_fp_total_eots_sign_counter", + Help: "Total number of EOTS signatures made", + }, + []string{"fp_btc_pk_hex"}, + ), + EotsFpLastEotsSignHeight: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "eots_fp_last_eots_sign_height", + Help: "Height of the last EOTS signature made", + }, + []string{"fp_btc_pk_hex"}, + ), + EotsFpTotalSchnorrSignCounter: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "eots_fp_total_schnorr_sign_counter", + Help: "Total number of Schnorr signatures made by EOTS", + }, + []string{"fp_btc_pk_hex"}, + ), + } + + // Register the EOTS metrics with Prometheus + prometheus.MustRegister(eotsMetricsInstance.EotsCreatedKeysCounter) + prometheus.MustRegister(eotsMetricsInstance.EotsFpTotalEotsSignCounter) + prometheus.MustRegister(eotsMetricsInstance.EotsFpLastEotsSignHeight) + prometheus.MustRegister(eotsMetricsInstance.EotsFpTotalSchnorrSignCounter) + }) + + return eotsMetricsInstance +} + +// IncrementEotsCreatedKeysCounter increments the EOTS created keys counter +func (em *EotsMetrics) IncrementEotsCreatedKeysCounter() { + em.EotsCreatedKeysCounter.Inc() +} + +// IncrementEotsFpTotalEotsSignCounter increments the EOTS signature counter +func (em *EotsMetrics) IncrementEotsFpTotalEotsSignCounter(fpBtcPkHex string) { + em.EotsFpTotalEotsSignCounter.WithLabelValues(fpBtcPkHex).Inc() +} + +// SetEotsFpLastEotsSignHeight sets the height of the last EOTS signature made +func (em *EotsMetrics) SetEotsFpLastEotsSignHeight(fpBtcPkHex string, height float64) { + em.EotsFpLastEotsSignHeight.WithLabelValues(fpBtcPkHex).Set(height) +} + +// IncrementEotsFpTotalSchnorrSignCounter increments the EOTS Schnorr signature counter +func (em *EotsMetrics) IncrementEotsFpTotalSchnorrSignCounter(fpBtcPkHex string) { + em.EotsFpTotalSchnorrSignCounter.WithLabelValues(fpBtcPkHex).Inc() +} diff --git a/metrics/fp_collectors.go b/metrics/fp_collectors.go new file mode 100644 index 00000000..82c6e0fc --- /dev/null +++ b/metrics/fp_collectors.go @@ -0,0 +1,287 @@ +package metrics + +import ( + "sync" + "time" + + "github.com/prometheus/client_golang/prometheus" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/store" +) + +type FpMetrics struct { + // all finality provider metrics + runningFpGauge prometheus.Gauge + // poller metrics + babylonTipHeight prometheus.Gauge + lastPolledHeight prometheus.Gauge + pollerStartingHeight prometheus.Gauge + // single finality provider metrics + fpStatus *prometheus.GaugeVec + fpSecondsSinceLastVote *prometheus.GaugeVec + fpSecondsSinceLastRandomness *prometheus.GaugeVec + fpLastVotedHeight *prometheus.GaugeVec + fpLastProcessedHeight *prometheus.GaugeVec + fpLastCommittedRandomnessHeight *prometheus.GaugeVec + fpTotalBlocksWithoutVotingPower *prometheus.CounterVec + fpTotalVotedBlocks *prometheus.GaugeVec + fpTotalCommittedRandomness *prometheus.GaugeVec + fpTotalFailedVotes *prometheus.CounterVec + fpTotalFailedRandomness *prometheus.CounterVec + // time keeper + mu sync.Mutex + previousVoteByFp map[string]*time.Time + previousRandomnessByFp map[string]*time.Time +} + +// Declare a package-level variable for sync.Once to ensure metrics are registered only once +var fpMetricsRegisterOnce sync.Once + +// Declare a variable to hold the instance of FpMetrics +var fpMetricsInstance *FpMetrics + +// NewFpMetrics initializes and registers the metrics, using sync.Once to ensure it's done only once +func NewFpMetrics() *FpMetrics { + fpMetricsRegisterOnce.Do(func() { + fpMetricsInstance = &FpMetrics{ + runningFpGauge: prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "total_running_fps", + Help: "Current number of finality providers that are running", + }), + fpStatus: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "fp_status", + Help: "Current status of a finality provider", + }, []string{"fp_btc_pk_hex"}), + babylonTipHeight: prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "babylon_tip_height", + Help: "The current tip height of the Babylon network", + }), + lastPolledHeight: prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "last_polled_height", + Help: "The most recent block height checked by the poller", + }), + pollerStartingHeight: prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "poller_starting_height", + Help: "The initial block height when the poller started operation", + }), + fpSecondsSinceLastVote: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_seconds_since_last_vote", + Help: "Seconds since the last finality sig vote by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpSecondsSinceLastRandomness: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_seconds_since_last_randomness", + Help: "Seconds since the last public randomness commitment by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpLastVotedHeight: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_last_voted_height", + Help: "The last block height voted by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpLastProcessedHeight: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_last_processed_height", + Help: "The last block height processed by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpTotalBlocksWithoutVotingPower: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "fp_total_blocks_without_voting_power", + Help: "The total number of blocks without voting power for a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpTotalVotedBlocks: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_total_voted_blocks", + Help: "The total number of blocks voted by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpTotalCommittedRandomness: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_total_committed_randomness", + Help: "The total number of randomness commitments by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpLastCommittedRandomnessHeight: prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "fp_last_committed_randomness_height", + Help: "The last block height with randomness commitment by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpTotalFailedVotes: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "fp_total_failed_votes", + Help: "The total number of failed votes by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + fpTotalFailedRandomness: prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "fp_total_failed_randomness", + Help: "The total number of failed randomness commitments by a finality provider.", + }, + []string{"fp_btc_pk_hex"}, + ), + mu: sync.Mutex{}, + } + + // Register the metrics with Prometheus + prometheus.MustRegister(fpMetricsInstance.runningFpGauge) + prometheus.MustRegister(fpMetricsInstance.fpStatus) + prometheus.MustRegister(fpMetricsInstance.babylonTipHeight) + prometheus.MustRegister(fpMetricsInstance.lastPolledHeight) + prometheus.MustRegister(fpMetricsInstance.pollerStartingHeight) + prometheus.MustRegister(fpMetricsInstance.fpSecondsSinceLastVote) + prometheus.MustRegister(fpMetricsInstance.fpSecondsSinceLastRandomness) + prometheus.MustRegister(fpMetricsInstance.fpLastVotedHeight) + prometheus.MustRegister(fpMetricsInstance.fpLastProcessedHeight) + prometheus.MustRegister(fpMetricsInstance.fpTotalBlocksWithoutVotingPower) + prometheus.MustRegister(fpMetricsInstance.fpTotalVotedBlocks) + prometheus.MustRegister(fpMetricsInstance.fpTotalCommittedRandomness) + prometheus.MustRegister(fpMetricsInstance.fpLastCommittedRandomnessHeight) + prometheus.MustRegister(fpMetricsInstance.fpTotalFailedVotes) + prometheus.MustRegister(fpMetricsInstance.fpTotalFailedRandomness) + }) + return fpMetricsInstance +} + +// DecrementRunningFpGauge decrements the running finality provider gauge +func (fm *FpMetrics) DecrementRunningFpGauge() { + fm.runningFpGauge.Dec() +} + +// IncrementRunningFpGauge increments the running finality provider gauge +func (fm *FpMetrics) IncrementRunningFpGauge() { + fm.runningFpGauge.Inc() +} + +// RecordFpStatus records the status of a finality provider +func (fm *FpMetrics) RecordFpStatus(fpBtcPkHex string, status proto.FinalityProviderStatus) { + fm.fpStatus.WithLabelValues(fpBtcPkHex).Set(float64(status)) +} + +// RecordBabylonTipHeight records the current tip height of the Babylon network +func (fm *FpMetrics) RecordBabylonTipHeight(height uint64) { + fm.babylonTipHeight.Set(float64(height)) +} + +// RecordLastPolledHeight records the most recent block height checked by the poller +func (fm *FpMetrics) RecordLastPolledHeight(height uint64) { + fm.lastPolledHeight.Set(float64(height)) +} + +// RecordPollerStartingHeight records the initial block height when the poller started operation +func (fm *FpMetrics) RecordPollerStartingHeight(height uint64) { + fm.pollerStartingHeight.Set(float64(height)) +} + +// RecordFpSecondsSinceLastVote records the seconds since the last finality sig vote by a finality provider +func (fm *FpMetrics) RecordFpSecondsSinceLastVote(fpBtcPkHex string, seconds float64) { + fm.fpSecondsSinceLastVote.WithLabelValues(fpBtcPkHex).Set(seconds) +} + +// RecordFpSecondsSinceLastRandomness records the seconds since the last public randomness commitment by a finality provider +func (fm *FpMetrics) RecordFpSecondsSinceLastRandomness(fpBtcPkHex string, seconds float64) { + fm.fpSecondsSinceLastRandomness.WithLabelValues(fpBtcPkHex).Set(seconds) +} + +// RecordFpLastVotedHeight records the last block height voted by a finality provider +func (fm *FpMetrics) RecordFpLastVotedHeight(fpBtcPkHex string, height uint64) { + fm.fpLastVotedHeight.WithLabelValues(fpBtcPkHex).Set(float64(height)) +} + +// RecordFpLastProcessedHeight records the last block height processed by a finality provider +func (fm *FpMetrics) RecordFpLastProcessedHeight(fpBtcPkHex string, height uint64) { + fm.fpLastProcessedHeight.WithLabelValues(fpBtcPkHex).Set(float64(height)) +} + +// RecordFpLastCommittedRandomnessHeight record the last height at which a finality provider committed randomness +func (fm *FpMetrics) RecordFpLastCommittedRandomnessHeight(fpBtcPkHex string, height uint64) { + fm.fpLastCommittedRandomnessHeight.WithLabelValues(fpBtcPkHex).Set(float64(height)) +} + +// IncrementFpTotalBlocksWithoutVotingPower increments the total number of blocks without voting power for a finality provider +func (fm *FpMetrics) IncrementFpTotalBlocksWithoutVotingPower(fpBtcPkHex string) { + fm.fpTotalBlocksWithoutVotingPower.WithLabelValues(fpBtcPkHex).Inc() +} + +// IncrementFpTotalVotedBlocks increments the total number of blocks voted by a finality provider +func (fm *FpMetrics) IncrementFpTotalVotedBlocks(fpBtcPkHex string) { + fm.fpTotalVotedBlocks.WithLabelValues(fpBtcPkHex).Inc() +} + +// AddToFpTotalVotedBlocks adds a number to the total number of blocks voted by a finality provider +func (fm *FpMetrics) AddToFpTotalVotedBlocks(fpBtcPkHex string, num float64) { + fm.fpTotalVotedBlocks.WithLabelValues(fpBtcPkHex).Add(num) +} + +// AddToFpTotalCommittedRandomness adds a number to the total number of randomness commitments by a finality provider +func (fm *FpMetrics) AddToFpTotalCommittedRandomness(fpBtcPkHex string, num float64) { + fm.fpTotalCommittedRandomness.WithLabelValues(fpBtcPkHex).Add(num) +} + +// IncrementFpTotalFailedVotes increments the total number of failed votes by a finality provider +func (fm *FpMetrics) IncrementFpTotalFailedVotes(fpBtcPkHex string) { + fm.fpTotalFailedVotes.WithLabelValues(fpBtcPkHex).Inc() +} + +// IncrementFpTotalFailedRandomness increments the total number of failed randomness commitments by a finality provider +func (fm *FpMetrics) IncrementFpTotalFailedRandomness(fpBtcPkHex string) { + fm.fpTotalFailedRandomness.WithLabelValues(fpBtcPkHex).Inc() +} + +// RecordFpVoteTime records the time of a finality sig vote by a finality provider +func (fm *FpMetrics) RecordFpVoteTime(fpBtcPkHex string) { + fm.mu.Lock() + defer fm.mu.Unlock() + + now := time.Now() + + if fm.previousVoteByFp == nil { + fm.previousVoteByFp = make(map[string]*time.Time) + } + fm.previousVoteByFp[fpBtcPkHex] = &now +} + +// RecordFpRandomnessTime records the time of a public randomness commitment by a finality provider +func (fm *FpMetrics) RecordFpRandomnessTime(fpBtcPkHex string) { + fm.mu.Lock() + defer fm.mu.Unlock() + + now := time.Now() + + if fm.previousRandomnessByFp == nil { + fm.previousRandomnessByFp = make(map[string]*time.Time) + } + fm.previousRandomnessByFp[fpBtcPkHex] = &now +} + +func (fm *FpMetrics) UpdateFpMetrics(fps []*store.StoredFinalityProvider) { + fm.mu.Lock() + defer fm.mu.Unlock() + + for _, fp := range fps { + fm.RecordFpStatus(fp.GetBIP340BTCPK().MarshalHex(), fp.Status) + + if lastVoteTime, ok := fm.previousVoteByFp[fp.GetBIP340BTCPK().MarshalHex()]; ok { + fm.RecordFpSecondsSinceLastVote(fp.GetBIP340BTCPK().MarshalHex(), time.Since(*lastVoteTime).Seconds()) + } + + if lastRandomnessTime, ok := fm.previousRandomnessByFp[fp.GetBIP340BTCPK().MarshalHex()]; ok { + fm.RecordFpSecondsSinceLastRandomness(fp.GetBIP340BTCPK().MarshalHex(), time.Since(*lastRandomnessTime).Seconds()) + } + } +} diff --git a/metrics/server.go b/metrics/server.go new file mode 100644 index 00000000..15e850b4 --- /dev/null +++ b/metrics/server.go @@ -0,0 +1,52 @@ +package metrics + +import ( + "context" + "net/http" + + "github.com/prometheus/client_golang/prometheus/promhttp" + "go.uber.org/zap" +) + +// Server represents the metrics server. +type Server struct { + httpServer *http.Server + logger *zap.Logger +} + +func Start(addr string, logger *zap.Logger) *Server { + mux := http.NewServeMux() + mux.Handle("/metrics", promhttp.Handler()) + + // Create the HTTP server with the custom ServeMux as the handler + server := &http.Server{ + Addr: addr, + Handler: mux, + } + + // Store the logger in the server struct + s := &Server{ + httpServer: server, + logger: logger, + } + + // Start the metrics server in a goroutine. + go func() { + s.logger.Info("Metrics server is starting", zap.String("addr", addr)) + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + s.logger.Fatal("Metrics server failed to start", zap.Error(err)) + } + }() + + return s +} + +// Stop gracefully shuts down the metrics server. +func (s *Server) Stop(ctx context.Context) { + s.logger.Info("Stopping metrics server") + if err := s.httpServer.Shutdown(ctx); err != nil { + s.logger.Error("Metrics server shutdown failed", zap.Error(err)) + } else { + s.logger.Info("Metrics server stopped gracefully") + } +} diff --git a/scripts/update_changelog.sh b/scripts/update_changelog.sh new file mode 100755 index 00000000..cb35c5c1 --- /dev/null +++ b/scripts/update_changelog.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# This is a wrapper around `github_changelog_generator` (https://github.com/github-changelog-generator) +# to simplify / automate updating of the CHANGELOG.md file. +# +# Originally developed for CosmWasm cw_plus (https://github.com/CosmWasm/cw-plus) repository. +set -o errexit -o pipefail + +ORIGINAL_OPTS=$* +# Requires getopt from util-linux 2.37.4 (brew install gnu-getopt on Mac) +OPTS=$(getopt -l "help,release-branch:,since-tag:,future-release:,full,token:" -o "hft" -- "$@") || exit 1 + +function print_usage() { + echo -e "Usage: $0 [-h|--help] [-f|--full] [--release-branch ] [--since-tag ] [--future-release] [-t|--token ] + +-h, --help Display help. +-f, --full Process changes since the beginning (by default: since latest git version tag). +--since-tag Process changes since git version tag (by default: since latest git version tag). +--future-release Put the unreleased changes in the specified . +--release-branch Limit pull requests to the release branch . +--token Pass changelog github token ." +} + +function remove_opt() { + ORIGINAL_OPTS=$(echo "$ORIGINAL_OPTS" | sed "s/\\B$1\\b//") +} + +eval set -- "$OPTS" +while true +do +case $1 in + -h|--help) + print_usage + exit 0 + ;; + --since-tag) + shift + TAG="$1" + ;; + -f|--full) + TAG="" + remove_opt $1 + ;; + --) + shift + break + ;; +esac +shift +done + +# Get user and repo from ./.git/config +ORIGIN_URL=$(git config --local remote.origin.url) +GITHUB_USER=$(echo $ORIGIN_URL | sed -n 's#.*:\([^\/]*\)\/.*#\1#p') +echo "Github user: $GITHUB_USER" +GITHUB_REPO=$(echo $ORIGIN_URL | sed -n 's#.*/\([^.]*\).*#\1#p') +echo "Github repo: $GITHUB_REPO" + +if [ -z "$TAG" ] +then + # Use latest git version tag + TAG=$(git tag --sort=creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | tail -1) + ORIGINAL_OPTS="$ORIGINAL_OPTS --since-tag $TAG" +fi + +echo "Git version tag: $TAG" + +touch CHANGELOG.md +cp CHANGELOG.md /tmp/CHANGELOG.md.$$ +# Consolidate tag for matching changelog entries +TAG=$(echo "$TAG" | sed -e 's/-\([A-Za-z]*\)[^A-Za-z]*/-\1/' -e 's/-$//') +echo "Consolidated tag: $TAG" +sed -i -n "/^## \\[${TAG}[^]]*\\]/,\$p" CHANGELOG.md + +echo github_changelog_generator -u $GITHUB_USER -p $GITHUB_REPO --base CHANGELOG.md $ORIGINAL_OPTS || cp /tmp/CHANGELOG.md.$$ CHANGELOG.md +github_changelog_generator -u $GITHUB_USER -p $GITHUB_REPO --base CHANGELOG.md $ORIGINAL_OPTS || cp /tmp/CHANGELOG.md.$$ CHANGELOG.md + +rm -f /tmp/CHANGELOG.md.$$ diff --git a/store/bbolt.go b/store/bbolt.go deleted file mode 100644 index 34acd6ef..00000000 --- a/store/bbolt.go +++ /dev/null @@ -1,220 +0,0 @@ -package store - -import ( - "bytes" - "errors" - "fmt" - - bolt "go.etcd.io/bbolt" -) - -// BboltStore implements the Store interface -type BboltStore struct { - db *bolt.DB - bucketName string -} - -// Put stores the given value for the given key. -// Values are automatically marshalled to JSON or gob. -// The key must not be "" and the value must not be nil. -func (s BboltStore) Put(k []byte, v []byte) error { - if err := checkKeyAndValue(k, v); err != nil { - return err - } - - err := s.db.Update(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - return b.Put(k, v) - }) - if err != nil { - return err - } - return nil -} - -// Get retrieves the stored value for the given key. -func (s BboltStore) Get(k []byte) ([]byte, error) { - if err := checkKey(k); err != nil { - return nil, err - } - - var data []byte - err := s.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - data = b.Get(k) - return nil - }) - if err != nil { - return nil, err - } - - if err := checkValue(data); err != nil { - return nil, err - } - - return data, nil -} - -// Exists checks whether the given key exists in the store. -func (s BboltStore) Exists(k []byte) (bool, error) { - if err := checkKey(k); err != nil { - return false, err - } - - var data []byte - err := s.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - data = b.Get(k) - return checkValue(data) - }) - - if err != nil { - return false, nil - } - - return true, nil -} - -func (s BboltStore) List(keyPrefix []byte) ([]*KVPair, error) { - if len(keyPrefix) == 0 { - return s.listFromStart() - } - - var kvList []*KVPair - - err := s.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - cursor := b.Cursor() - prefix := keyPrefix - - for key, v := cursor.Seek(prefix); bytes.HasPrefix(key, prefix); key, v = cursor.Next() { - if err := checkValue(v); err != nil { - return err - } - kvList = append(kvList, &KVPair{ - Key: key, - Value: v, - }) - } - return nil - }) - - if err != nil { - return nil, err - } - - return kvList, nil -} - -func (s BboltStore) listFromStart() ([]*KVPair, error) { - var kvList []*KVPair - - err := s.db.View(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - cursor := b.Cursor() - - for key, v := cursor.First(); ; key, v = cursor.Next() { - if key == nil { - break - } - if err := checkValue(v); err != nil { - return err - } - kvList = append(kvList, &KVPair{ - Key: key, - Value: v, - }) - } - return nil - }) - - if err != nil { - return nil, err - } - - return kvList, nil -} - -// Delete deletes the stored value for the given key. -// Deleting a non-existing key-value pair does NOT lead to an error. -func (s BboltStore) Delete(k []byte) error { - if err := checkKey(k); err != nil { - return err - } - - return s.db.Update(func(tx *bolt.Tx) error { - b := tx.Bucket([]byte(s.bucketName)) - return b.Delete(k) - }) -} - -// Close closes the store. -// It must be called to make sure that all open transactions finish and to release all DB resources. -func (s BboltStore) Close() error { - return s.db.Close() -} - -// NewBboltStore creates a new bbolt store. -// Note: bbolt uses an exclusive write lock on the database file so it cannot be shared by multiple processes. -// So when creating multiple clients you should always use a new database file (by setting a different Path in the options). -// -// You must call the Close() method on the store when you're done working with it. -func NewBboltStore(path string, bucketName string) (BboltStore, error) { - result := BboltStore{} - - // Set default values - if path == "" { - return BboltStore{}, fmt.Errorf("db path is empty") - } - if bucketName == "" { - return BboltStore{}, fmt.Errorf("db bucket name is empty") - } - - // Open DB - db, err := bolt.Open(path, 0600, nil) - if err != nil { - return result, err - } - - // Create a bucket if it doesn't exist yet. - // In bbolt key/value pairs are stored to and read from buckets. - err = db.Update(func(tx *bolt.Tx) error { - _, err := tx.CreateBucketIfNotExists([]byte(bucketName)) - if err != nil { - return err - } - return nil - }) - if err != nil { - return result, err - } - - result.db = db - result.bucketName = bucketName - - return result, nil -} - -// checkKey returns an error if k == "" -func checkKey(k []byte) error { - if len(k) == 0 { - return errors.New("the key should not be empty") - } - return nil -} - -func checkValue(v []byte) error { - if v == nil { - return errors.New("the value should not be nil") - } - - return nil -} - -// checkKeyAndValue returns an error if k == "" or if v == nil -func checkKeyAndValue(k []byte, v []byte) error { - if err := checkKey(k); err != nil { - return err - } - return checkValue(v) -} diff --git a/store/bbolt_test.go b/store/bbolt_test.go deleted file mode 100644 index 7a407cee..00000000 --- a/store/bbolt_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package store_test - -import ( - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - kvstore "github.com/babylonchain/finality-provider/store" - "github.com/babylonchain/finality-provider/testutil" -) - -// FuzzBboltStore tests store interfaces works properly. -func FuzzBboltStore(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - store, path := testutil.CreateStore(r, t) - defer testutil.CleanUp(store, path, t) - - kvNum := r.Intn(10) + 1 - kvList := genRandomKVList(kvNum, r) - randIndex := r.Intn(kvNum) - - // Initially the key shouldn't exist - v, err := store.Get(kvList[randIndex].Key) - require.Error(t, err) - require.Nil(t, v) - - // Deleting a non-existing key-value pair should NOT lead to an error - err = store.Delete(kvList[randIndex].Key) - require.NoError(t, err) - - // Save all the KV pairs - for i := 0; i < kvNum; i++ { - err = store.Put(kvList[i].Key, kvList[i].Value) - require.NoError(t, err) - // Storing it again should not lead to an error but just overwrite it - err = store.Put(kvList[i].Key, kvList[i].Value) - require.NoError(t, err) - // Retrieve the object - expectedBytes := kvList[i].Value - v, err = store.Get(kvList[i].Key) - require.NoError(t, err) - require.Equal(t, expectedBytes, v) - // Exists - exists, err := store.Exists(kvList[i].Key) - require.NoError(t, err) - require.True(t, exists) - } - - // List all the KV pairs - newKvList, err := store.List(nil) - require.NoError(t, err) - require.Equal(t, kvNum, len(newKvList)) - require.Equal(t, len(kvList), len(newKvList)) - - // Delete - err = store.Delete(kvList[randIndex].Key) - require.NoError(t, err) - // Key-value pair shouldn't exist anymore - v, err = store.Get(kvList[randIndex].Key) - require.Error(t, err) - require.Nil(t, v) - exists, err := store.Exists(kvList[randIndex].Key) - require.NoError(t, err) - require.False(t, exists) - }) - -} - -func genRandomKVList(num int, r *rand.Rand) []*kvstore.KVPair { - kvList := make([]*kvstore.KVPair, num) - - for i := 0; i < num; i++ { - kvp := genRandomKV(r) - kvList[i] = kvp - } - - return kvList -} - -func genRandomKV(r *rand.Rand) *kvstore.KVPair { - k := testutil.GenRandomByteArray(r, 100) - v := testutil.GenRandomByteArray(r, 1000) - return &kvstore.KVPair{ - Key: k, - Value: v, - } -} diff --git a/store/interface.go b/store/interface.go deleted file mode 100644 index aca7fb55..00000000 --- a/store/interface.go +++ /dev/null @@ -1,23 +0,0 @@ -package store - -// Store is an abstraction for different key-value store implementations -type Store interface { - // Put stores the given value for the given key. - Put(k []byte, v []byte) error - // Get retrieves the value for the given key. - Get(k []byte) ([]byte, error) - // Exists checks if a key exists in the store - Exists(k []byte) (bool, error) - // List returns the range of keys starting with the passed in prefix - List(keyPrefix []byte) ([]*KVPair, error) - // Delete deletes the stored value for the given key. - Delete(k []byte) error - // Close must be called when the work with the key-value store is done. - Close() error -} - -// KVPair represents {Key, Value} pair -type KVPair struct { - Key []byte - Value []byte -} diff --git a/testutil/datagen.go b/testutil/datagen.go index 64c0ec1b..6afc9fe4 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -6,13 +6,14 @@ import ( "testing" "time" - "github.com/babylonchain/babylon/crypto/eots" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/store" sdkmath "cosmossdk.io/math" + "github.com/babylonchain/babylon/crypto/eots" "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" @@ -21,7 +22,6 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/finality-provider/codec" - "github.com/babylonchain/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/proto" "github.com/babylonchain/finality-provider/finality-provider/service" "github.com/babylonchain/finality-provider/types" @@ -38,6 +38,11 @@ func GenRandomHexStr(r *rand.Rand, length uint64) string { return hex.EncodeToString(randBytes) } +func RandomDescription(r *rand.Rand) *stakingtypes.Description { + des := stakingtypes.NewDescription(GenRandomHexStr(r, 10), "", "", "", "") + return &des +} + func AddRandomSeedsToFuzzer(f *testing.F, num uint) { // Seed based on the current time r := rand.New(rand.NewSource(time.Now().Unix())) @@ -47,35 +52,36 @@ func AddRandomSeedsToFuzzer(f *testing.F, num uint) { } } -func GenPublicRand(r *rand.Rand, t *testing.T) *bbn.SchnorrPubRand { - _, eotsPR, err := eots.RandGen(r) - require.NoError(t, err) - return bbn.NewSchnorrPubRandFromFieldVal(eotsPR) -} - -func GenRandomFinalityProvider(r *rand.Rand, t *testing.T) *proto.StoreFinalityProvider { +func GenRandomFinalityProvider(r *rand.Rand, t *testing.T) *store.StoredFinalityProvider { // generate BTC key pair btcSK, btcPK, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) bip340PK := bbn.NewBIP340PubKeyFromBTCPK(btcPK) // generate Babylon key pair - babylonSK, babylonPK, err := datagen.GenRandomSecp256k1KeyPair(r) + babylonSK, chainPk, err := datagen.GenRandomSecp256k1KeyPair(r) require.NoError(t, err) // generate and verify PoP, correct case pop, err := bstypes.NewPoP(babylonSK, btcSK) require.NoError(t, err) - err = pop.Verify(babylonPK, bip340PK, &chaincfg.SimNetParams) + err = pop.Verify(chainPk, bip340PK, &chaincfg.SimNetParams) require.NoError(t, err) - return &proto.StoreFinalityProvider{ - KeyName: GenRandomHexStr(r, 4), - BabylonPk: babylonPK.Bytes(), - BtcPk: bip340PK.MustMarshal(), + _, mpr, err := eots.NewMasterRandPair(r) + require.NoError(t, err) + + return &store.StoredFinalityProvider{ + KeyName: GenRandomHexStr(r, 4), + ChainID: "chain-test", + ChainPk: &secp256k1.PubKey{Key: chainPk.Bytes()}, + BtcPk: bip340PK.MustToBTCPK(), + Description: RandomDescription(r), + Commission: ZeroCommissionRate(), + MasterPubRand: mpr.MarshalBase58(), Pop: &proto.ProofOfPossession{ - BabylonSig: pop.BabylonSig, - BtcSig: pop.BtcSig, + ChainSig: pop.BabylonSig, + BtcSig: pop.BtcSig, }, } } @@ -98,47 +104,24 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { } // GenStoredFinalityProvider generates a random finality-provider from the keyring and store it in DB -func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.FinalityProviderApp, passphrase, hdPath string) *proto.StoreFinalityProvider { +func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.FinalityProviderApp, passphrase, hdPath string) *store.StoredFinalityProvider { // generate keyring keyName := GenRandomHexStr(r, 4) chainID := GenRandomHexStr(r, 4) cfg := app.GetConfig() - _, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, keyName, keyring.BackendTest, passphrase, hdPath) + _, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, keyName, keyring.BackendTest, passphrase, hdPath, "") require.NoError(t, err) - res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) + res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, RandomDescription(r), ZeroCommissionRate()) require.NoError(t, err) - fpPk := res.StoreFp.BtcPk - storedFp, err := app.GetFinalityProviderStore().GetStoreFinalityProvider(fpPk) + btcPk, err := bbn.NewBIP340PubKeyFromHex(res.FpInfo.BtcPkHex) require.NoError(t, err) - - return storedFp -} - -func GenDBConfig(r *rand.Rand, t *testing.T) *config.DatabaseConfig { - bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - dbcfg, err := config.NewDatabaseConfig( - "bbolt", - bucketName, - ) + storedFp, err := app.GetFinalityProviderStore().GetFinalityProvider(btcPk.MustToBTCPK()) require.NoError(t, err) - return dbcfg -} - -func GenEOTSConfig(r *rand.Rand, t *testing.T) *eotscfg.Config { - eotsCfg := eotscfg.DefaultConfig() - eotsCfg.DatabaseConfig = GenDBConfig(r, t) - return &eotsCfg -} - -func GenFpConfig(r *rand.Rand, t *testing.T, homeDir string) *fpcfg.Config { - fpCfg := fpcfg.DefaultConfigWithHome(homeDir) - fpCfg.DatabaseConfig = GenDBConfig(r, t) - - return &fpCfg + return storedFp } func GenSdkContext(r *rand.Rand, t *testing.T) client.Context { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index ed45056e..bf9cc8bb 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -10,7 +10,6 @@ import ( math "cosmossdk.io/math" types "github.com/babylonchain/finality-provider/types" btcec "github.com/btcsuite/btcd/btcec/v2" - schnorr "github.com/btcsuite/btcd/btcec/v2/schnorr" gomock "github.com/golang/mock/gomock" ) @@ -51,21 +50,6 @@ func (mr *MockClientControllerMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockClientController)(nil).Close)) } -// CommitPubRandList mocks base method. -func (m *MockClientController) CommitPubRandList(fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitPubRandList", fpPk, startHeight, pubRandList, sig) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CommitPubRandList indicates an expected call of CommitPubRandList. -func (mr *MockClientControllerMockRecorder) CommitPubRandList(fpPk, startHeight, pubRandList, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), fpPk, startHeight, pubRandList, sig) -} - // QueryActivatedHeight mocks base method. func (m *MockClientController) QueryActivatedHeight() (uint64, error) { m.ctrl.T.Helper() @@ -156,19 +140,19 @@ func (mr *MockClientControllerMockRecorder) QueryFinalityProviderVotingPower(fpP return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) } -// QueryLastCommittedPublicRand mocks base method. -func (m *MockClientController) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { +// QueryLastFinalizedEpoch mocks base method. +func (m *MockClientController) QueryLastFinalizedEpoch() (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLastCommittedPublicRand", fpPk, count) - ret0, _ := ret[0].(map[uint64]*btcec.FieldVal) + ret := m.ctrl.Call(m, "QueryLastFinalizedEpoch") + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryLastCommittedPublicRand indicates an expected call of QueryLastCommittedPublicRand. -func (mr *MockClientControllerMockRecorder) QueryLastCommittedPublicRand(fpPk, count interface{}) *gomock.Call { +// QueryLastFinalizedEpoch indicates an expected call of QueryLastFinalizedEpoch. +func (mr *MockClientControllerMockRecorder) QueryLastFinalizedEpoch() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastCommittedPublicRand", reflect.TypeOf((*MockClientController)(nil).QueryLastCommittedPublicRand), fpPk, count) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastFinalizedEpoch", reflect.TypeOf((*MockClientController)(nil).QueryLastFinalizedEpoch)) } // QueryLatestFinalizedBlocks mocks base method. @@ -187,18 +171,19 @@ func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count int } // RegisterFinalityProvider mocks base method. -func (m *MockClientController) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { +func (m *MockClientController) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte, masterPubRand string) (*types.TxResponse, uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description) + ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description, masterPubRand) ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // RegisterFinalityProvider indicates an expected call of RegisterFinalityProvider. -func (mr *MockClientControllerMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description, masterPubRand interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockClientController)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockClientController)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description, masterPubRand) } // SubmitBatchFinalitySigs mocks base method. diff --git a/testutil/store.go b/testutil/store.go deleted file mode 100644 index 8232282a..00000000 --- a/testutil/store.go +++ /dev/null @@ -1,29 +0,0 @@ -package testutil - -import ( - "math/rand" - "os" - "testing" - - "github.com/stretchr/testify/require" - - kvstore "github.com/babylonchain/finality-provider/store" -) - -func CreateStore(r *rand.Rand, t *testing.T) (kvstore.Store, string) { - bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - path := t.TempDir() + bucketName - store, err := kvstore.NewBboltStore(path, bucketName) - require.NoError(t, err) - - return store, path -} - -// CleanUp cleans up (deletes) the database file that has been created during a test. -// If an error occurs the test is NOT marked as failed. -func CleanUp(store kvstore.Store, path string, t *testing.T) { - err := store.Close() - require.NoError(t, err) - err = os.RemoveAll(path) - require.NoError(t, err) -} diff --git a/testutil/utils.go b/testutil/utils.go index 2fb29c8c..76f14af2 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -13,10 +13,6 @@ import ( const TestPubRandNum = 25 -func EmptyDescription() []byte { - return []byte("empty description") -} - func ZeroCommissionRate() *sdkmath.LegacyDec { zeroCom := sdkmath.LegacyZeroDec() return &zeroCom diff --git a/tools/go.mod b/tools/go.mod index c5e1d2f4..71cc1f36 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -4,7 +4,7 @@ go 1.21 toolchain go1.21.4 -require github.com/babylonchain/babylon v0.8.0 +require github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b require ( cloud.google.com/go v0.110.10 // indirect @@ -12,13 +12,13 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/storage v1.35.1 // indirect - cosmossdk.io/api v0.7.2 // indirect + cosmossdk.io/api v0.7.3 // indirect cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/errors v1.0.1 // indirect - cosmossdk.io/log v1.3.0 // indirect + cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/math v1.2.0 // indirect cosmossdk.io/store v1.0.2 // indirect cosmossdk.io/tools/confix v0.1.0 // indirect @@ -36,11 +36,11 @@ require ( github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/aead/siphash v1.0.1 // indirect - github.com/aws/aws-sdk-go v1.44.224 // indirect + github.com/aws/aws-sdk-go v1.44.312 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect - github.com/bits-and-blooms/bitset v1.8.0 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -54,19 +54,19 @@ require ( github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v0.38.5 // indirect github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.0 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.4 // indirect github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.4.11 // indirect - github.com/cosmos/iavl v1.0.0 // indirect + github.com/cosmos/iavl v1.0.1 // indirect github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect github.com/cosmos/ibc-go/v8 v8.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect @@ -82,14 +82,14 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/distribution/reference v0.5.0 // indirect - github.com/docker/docker v23.0.8+incompatible // indirect + github.com/docker/docker v24.0.9+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect - github.com/emicklei/dot v1.6.0 // indirect + github.com/emicklei/dot v1.6.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/getsentry/sentry-go v0.25.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect @@ -100,7 +100,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -111,12 +111,12 @@ require ( github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-getter v1.7.4 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.1 // indirect @@ -135,17 +135,16 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/compress v1.17.6 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/linxGnu/grocksdb v1.8.6 // indirect + github.com/linxGnu/grocksdb v1.8.12 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -158,17 +157,18 @@ require ( github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.47.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.31.0 // indirect + github.com/rs/zerolog v1.32.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -187,13 +187,13 @@ require ( go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/tools/go.sum b/tools/go.sum index 0a2974f1..f701268d 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= -cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.3 h1:V815i8YOwOAQa1rLCsSMjVG5Gnzs02JLq+l7ks8s1jk= +cosmossdk.io/api v0.7.3/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -196,8 +196,8 @@ cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98ok cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= -cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo= -cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= +cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI= +cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM= cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= @@ -265,11 +265,11 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= -github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= +github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon v0.8.0 h1:QC04LPCFBD0MZyiM3cAjVBlr3CXEZPdhORWPBlO2gaQ= -github.com/babylonchain/babylon v0.8.0/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= +github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b h1:HfjAGZiebrcInFAq8Lk8MXbKbtTYxRoO65vfLPOCXzw= +github.com/babylonchain/babylon v0.8.6-0.20240416015120-ffeb9c5b930b/go.mod h1:lfeASLNJgcUsX7LEns3HRUv0k+MjzcB2q2AMasfz38M= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -280,8 +280,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= -github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= @@ -357,8 +357,8 @@ github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZ github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb h1:6Po+YYKT5B5ZXN0wd2rwFBaebM0LufPf8p4zxOd48Kg= -github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= @@ -380,8 +380,8 @@ github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0E= github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= -github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= -github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-proto v1.0.0-beta.4 h1:aEL7tU/rLOmxZQ9z4i7mzxcLbSCY48OdY7lIWTLG7oU= +github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 h1:Pjvcy7wHUoYh253LvNv5Dyx+d3SNkRPsDZH+FytqZ3w= github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987/go.mod h1:0D9mrUy1eAUMQuvYzf2xvhEPk2ta9w7XH1zcYvyFiuM= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= @@ -391,8 +391,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v1.0.0 h1:bw6t0Mv/mVCJvlMTOPHWLs5uUE3BRBfVWCRelOzl+so= -github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/iavl v1.0.1 h1:D+mYbcRO2wptYzOM1Hxl9cpmmHU1ZEt9T2Wv5nZTeUw= +github.com/cosmos/iavl v1.0.1/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOhg= @@ -439,8 +439,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v23.0.8+incompatible h1:z4ZCIwfqHgOEwhxmAWugSL1PFtPQmLP60EVhJYJPaX8= -github.com/docker/docker v23.0.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -455,8 +455,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emicklei/dot v1.6.0 h1:vUzuoVE8ipzS7QkES4UfxdpCwdU2U97m2Pb2tQCoYRY= -github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI= +github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -484,8 +484,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= -github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -586,8 +586,9 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -671,8 +672,9 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -690,8 +692,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= -github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= +github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -785,8 +787,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -806,8 +808,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= -github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.12 h1:1/pCztQUOa3BX/1gR3jSZDoaKFpeHFvQ1XrqZpSvZVo= +github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -830,8 +832,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= @@ -940,24 +940,24 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= +github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -973,14 +973,14 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1126,8 +1126,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1139,8 +1139,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1167,8 +1167,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1229,8 +1229,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1256,8 +1256,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1272,8 +1272,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1364,6 +1364,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1371,13 +1372,13 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1459,8 +1460,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/types/chainkey.go b/types/chainkey.go index 6d5df870..56f88ced 100644 --- a/types/chainkey.go +++ b/types/chainkey.go @@ -12,3 +12,7 @@ type ChainKeyInfo struct { PublicKey *btcec.PublicKey PrivateKey *btcec.PrivateKey } + +func MarshalChainID(chainID string) []byte { + return []byte(chainID) +}