From 93bf292e6090101ae616ceab872456ef396e25d4 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 26 Sep 2023 17:02:34 +0800 Subject: [PATCH 01/66] feat: Add periodic status update to managed validators (#110) --- clientcontroller/babylon.go | 18 +++ clientcontroller/interface.go | 2 + itest/test_manager.go | 5 +- service/app.go | 4 +- service/types.go | 168 +++++++++++++++++++++- service/validator_instance.go | 226 +++++++----------------------- service/validator_manager.go | 144 ++++++++++++++++++- service/validator_manager_test.go | 137 ++++++++++++++++++ testutil/mocks/babylon.go | 15 ++ valcfg/config.go | 3 + 10 files changed, 532 insertions(+), 190 deletions(-) create mode 100644 service/validator_manager_test.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 88843a61..580256af 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -573,7 +573,25 @@ func (bc *BabylonController) QueryUnbondindBTCDelegations() ([]*btcstakingtypes. return res.BtcDelegations, nil } +func (bc *BabylonController) QueryValidator(btcPk *bbntypes.BIP340PubKey) (*btcstakingtypes.BTCValidator, error) { + ctx, cancel := getContextWithCancel(bc.timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryRequest := &btcstakingtypes.QueryBTCValidatorRequest{ValBtcPkHex: btcPk.MarshalHex()} + + queryClient := btcstakingtypes.NewQueryClient(clientCtx) + res, err := queryClient.BTCValidator(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query the validator %s: %v", btcPk.MarshalHex(), err) + } + + return res.BtcValidator, nil +} + // QueryValidators queries BTC validators +// Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, error) { var validators []*btcstakingtypes.BTCValidator pagination := &sdkquery.PageRequest{ diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 15bfa0f9..63a66ce4 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -100,6 +100,8 @@ type ClientController interface { QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) // QueryBlocks returns a list of blocks from startHeight to endHeight QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) + // QueryValidator returns a BTC validator object + QueryValidator(btcPk *bbntypes.BIP340PubKey) (*btcstakingtypes.BTCValidator, error) // QueryBlockFinalization queries whether the block has been finalized QueryBlockFinalization(height uint64) (bool, error) diff --git a/itest/test_manager.go b/itest/test_manager.go index 18417c15..47e875a2 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -80,9 +80,6 @@ func StartManager(t *testing.T, isJury bool) *TestManager { cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isJury) bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) - // making sure the fee is sufficient - cfg.BabylonConfig.GasAdjustment = 1.5 - cfg.BabylonConfig.GasPrices = "0.1ubbn" require.NoError(t, err) valApp, err := service.NewValidatorAppFromConfig(cfg, logger, bc) @@ -534,7 +531,7 @@ func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Con // errors cfg.BabylonConfig.Key = "test-spending-key" // Big adjustment to make sure we have enough gas in our transactions - cfg.BabylonConfig.GasAdjustment = 5 + cfg.BabylonConfig.GasAdjustment = 10 cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") cfg.JuryMode = isJury cfg.JuryModeConfig.QueryInterval = 7 * time.Second diff --git a/service/app.go b/service/app.go index 7239f3d8..a9e7599c 100644 --- a/service/app.go +++ b/service/app.go @@ -114,12 +114,12 @@ func (app *ValidatorApp) GetJuryPk() (*btcec.PublicKey, error) { } func (app *ValidatorApp) ListValidatorInstances() []*ValidatorInstance { - return app.validatorManager.listValidatorInstances() + return app.validatorManager.ListValidatorInstances() } // GetValidatorInstance returns the validator instance with the given Babylon public key func (app *ValidatorApp) GetValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { - return app.validatorManager.getValidatorInstance(babylonPk) + return app.validatorManager.GetValidatorInstance(babylonPk) } func (app *ValidatorApp) RegisterValidator(keyName string) (*RegisterValidatorResponse, *secp256k1.PubKey, error) { diff --git a/service/types.go b/service/types.go index ad61dd7f..ee3f6006 100644 --- a/service/types.go +++ b/service/types.go @@ -1,12 +1,18 @@ package service import ( - "github.com/babylonchain/babylon/types" + "sync" + + bbntypes "github.com/babylonchain/babylon/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/val" ) type createValidatorResponse struct { @@ -23,7 +29,7 @@ type createValidatorRequest struct { type registerValidatorRequest struct { bbnPubKey *secp256k1.PubKey - btcPubKey *types.BIP340PubKey + btcPubKey *bbntypes.BIP340PubKey // TODO we should have our own representation of PoP pop *btcstakingtypes.ProofOfPossession description *stakingtypes.Description @@ -52,12 +58,166 @@ type CreateValidatorResult struct { } type unbondingTxSigData struct { - stakerPk *types.BIP340PubKey + stakerPk *bbntypes.BIP340PubKey stakingTxHash string - signature *types.BIP340Signature + signature *bbntypes.BIP340Signature } type unbondingTxSigSendResult struct { err error stakingTxHash string } + +type valState struct { + mu sync.Mutex + v *proto.StoreValidator + s *val.ValidatorStore +} + +func (vs *valState) getStoreValidator() *proto.StoreValidator { + vs.mu.Lock() + defer vs.mu.Unlock() + return vs.v +} + +func (vs *valState) setStatus(s proto.ValidatorStatus) error { + vs.mu.Lock() + vs.v.Status = s + vs.mu.Unlock() + return vs.s.UpdateValidator(vs.v) +} + +func (vs *valState) setLastVotedHeight(height uint64) error { + vs.mu.Lock() + vs.v.LastVotedHeight = height + vs.mu.Unlock() + return vs.s.UpdateValidator(vs.v) +} + +func (vs *valState) setLastProcessedHeight(height uint64) error { + vs.mu.Lock() + vs.v.LastProcessedHeight = height + vs.mu.Unlock() + return vs.s.UpdateValidator(vs.v) +} + +func (vs *valState) setLastCommittedHeight(height uint64) error { + vs.mu.Lock() + vs.v.LastCommittedHeight = height + vs.mu.Unlock() + return vs.s.UpdateValidator(vs.v) +} + +func (vs *valState) setLastProcessedAndVotedHeight(height uint64) error { + vs.mu.Lock() + vs.v.LastVotedHeight = height + vs.v.LastProcessedHeight = height + vs.mu.Unlock() + return vs.s.UpdateValidator(vs.v) +} + +func (v *ValidatorInstance) GetStoreValidator() *proto.StoreValidator { + return v.state.getStoreValidator() +} + +func (v *ValidatorInstance) GetBabylonPk() *secp256k1.PubKey { + return v.state.getStoreValidator().GetBabylonPK() +} + +func (v *ValidatorInstance) GetBabylonPkHex() string { + return v.state.getStoreValidator().GetBabylonPkHexString() +} + +func (v *ValidatorInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { + return v.state.getStoreValidator().MustGetBIP340BTCPK() +} + +func (v *ValidatorInstance) MustGetBtcPk() *btcec.PublicKey { + return v.state.getStoreValidator().MustGetBTCPK() +} + +func (v *ValidatorInstance) GetBtcPkHex() string { + return v.GetBtcPkBIP340().MarshalHex() +} + +func (v *ValidatorInstance) GetStatus() proto.ValidatorStatus { + return v.state.getStoreValidator().Status +} + +func (v *ValidatorInstance) GetLastVotedHeight() uint64 { + return v.state.getStoreValidator().LastVotedHeight +} + +func (v *ValidatorInstance) GetLastProcessedHeight() uint64 { + return v.state.getStoreValidator().LastProcessedHeight +} + +func (v *ValidatorInstance) GetLastCommittedHeight() uint64 { + return v.state.getStoreValidator().LastCommittedHeight +} + +func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { + return v.state.setStatus(s) +} + +func (v *ValidatorInstance) MustSetStatus(s proto.ValidatorStatus) { + if err := v.SetStatus(s); err != nil { + v.logger.WithFields(logrus.Fields{ + "err": err, + "btc_pk_hex": v.GetBtcPkHex(), + "status": s.String(), + }).Fatal("failed to set validator status") + } +} + +func (v *ValidatorInstance) SetLastProcessedHeight(height uint64) error { + return v.state.setLastProcessedHeight(height) +} + +func (v *ValidatorInstance) MustSetLastProcessedHeight(height uint64) { + if err := v.SetLastProcessedHeight(height); err != nil { + v.logger.WithFields(logrus.Fields{ + "err": err, + "btc_pk_hex": v.GetBtcPkHex(), + "height": height, + }).Fatal("failed to set last processed height") + } +} + +func (v *ValidatorInstance) SetLastCommittedHeight(height uint64) error { + return v.state.setLastCommittedHeight(height) +} + +func (v *ValidatorInstance) MustSetLastCommittedHeight(height uint64) { + if err := v.SetLastCommittedHeight(height); err != nil { + v.logger.WithFields(logrus.Fields{ + "err": err, + "btc_pk_hex": v.GetBtcPkHex(), + "height": height, + }).Fatal("failed to set last committed height") + } +} + +func (v *ValidatorInstance) updateStateAfterFinalitySigSubmission(height uint64) error { + return v.state.setLastProcessedAndVotedHeight(height) +} + +func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { + if err := v.updateStateAfterFinalitySigSubmission(height); err != nil { + v.logger.WithFields(logrus.Fields{ + "err": err, + "btc_pk_hex": v.GetBtcPkHex(), + "height": height, + }).Fatal("failed to update state after finality sig submission") + } +} + +// only used for testing purpose +func (v *ValidatorInstance) GetCommittedPubRandPairList() ([]*proto.SchnorrRandPair, error) { + return v.state.s.GetRandPairList(v.bbnPk.Key) +} + +// only used for testing purposes +func (v *ValidatorInstance) BtcPrivKey() (*btcec.PrivateKey, error) { + return v.kc.GetBtcPrivKey() +} diff --git a/service/validator_instance.go b/service/validator_instance.go index 624030a8..5a0871ae 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -1,7 +1,6 @@ package service import ( - "encoding/hex" "errors" "fmt" "strings" @@ -29,16 +28,11 @@ import ( "github.com/babylonchain/btc-validator/valcfg" ) -type state struct { - v *proto.StoreValidator - s *val.ValidatorStore -} - type ValidatorInstance struct { bbnPk *secp256k1.PubKey btcPk *bbntypes.BIP340PubKey - state *state + state *valState cfg *valcfg.Config logger *logrus.Logger @@ -74,7 +68,6 @@ func NewValidatorInstance( } // ensure the validator has been registered - // TODO refactor this by getting the constants from Babylon if v.Status < proto.ValidatorStatus_REGISTERED { return nil, fmt.Errorf("the validator %s has not been registered", v.KeyName) } @@ -87,7 +80,7 @@ func NewValidatorInstance( return &ValidatorInstance{ bbnPk: bbnPk, btcPk: v.MustGetBIP340BTCPK(), - state: &state{ + state: &valState{ v: v, s: s, }, @@ -102,151 +95,6 @@ func NewValidatorInstance( }, nil } -func (v *ValidatorInstance) GetStoreValidator() *proto.StoreValidator { - return v.state.v -} - -func (v *ValidatorInstance) GetBabylonPk() *secp256k1.PubKey { - return v.state.v.GetBabylonPK() -} - -func (v *ValidatorInstance) GetBabylonPkHex() string { - return hex.EncodeToString(v.state.v.GetBabylonPk()) -} - -func (v *ValidatorInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { - return v.state.v.MustGetBIP340BTCPK() -} - -func (v *ValidatorInstance) MustGetBtcPk() *btcec.PublicKey { - return v.state.v.MustGetBTCPK() -} - -// Exposed mostly for testing purposes -func (v *ValidatorInstance) BtcPrivKey() (*btcec.PrivateKey, error) { - return v.kc.GetBtcPrivKey() -} - -func (v *ValidatorInstance) GetBtcPkHex() string { - return v.GetBtcPkBIP340().MarshalHex() -} - -func (v *ValidatorInstance) GetStatus() proto.ValidatorStatus { - return v.state.v.Status -} - -func (v *ValidatorInstance) GetLastVotedHeight() uint64 { - return v.state.v.LastVotedHeight -} - -func (v *ValidatorInstance) GetLastProcessedHeight() uint64 { - return v.state.v.LastProcessedHeight -} - -func (v *ValidatorInstance) GetLastCommittedHeight() uint64 { - return v.state.v.LastCommittedHeight -} - -func (v *ValidatorInstance) GetCommittedPubRandPairList() ([]*proto.SchnorrRandPair, error) { - return v.state.s.GetRandPairList(v.bbnPk.Key) -} - -func (v *ValidatorInstance) GetCommittedPubRandPair(height uint64) (*proto.SchnorrRandPair, error) { - return v.state.s.GetRandPair(v.bbnPk.Key, height) -} - -func (v *ValidatorInstance) GetCommittedPrivPubRand(height uint64) (*eots.PrivateRand, error) { - randPair, err := v.state.s.GetRandPair(v.bbnPk.Key, height) - if err != nil { - return nil, err - } - - if len(randPair.SecRand) != 32 { - return nil, fmt.Errorf("the private randomness should be 32 bytes") - } - - privRand := new(eots.PrivateRand) - privRand.SetByteSlice(randPair.SecRand) - - return privRand, nil -} - -func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { - v.state.v.Status = s - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetStatus(s proto.ValidatorStatus) { - if err := v.SetStatus(s); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "status": s.String(), - }).Fatal("failed to set validator status") - } -} - -func (v *ValidatorInstance) SetLastVotedHeight(height uint64) error { - v.state.v.LastVotedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastVotedHeight(height uint64) { - if err := v.SetLastVotedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last voted height") - } -} - -func (v *ValidatorInstance) SetLastProcessedHeight(height uint64) error { - v.state.v.LastProcessedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastProcessedHeight(height uint64) { - if err := v.SetLastProcessedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last processed height") - } -} - -func (v *ValidatorInstance) SetLastCommittedHeight(height uint64) error { - v.state.v.LastCommittedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastCommittedHeight(height uint64) { - if err := v.SetLastCommittedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last committed height") - } -} - -func (v *ValidatorInstance) updateStateAfterFinalitySigSubmission(height uint64) error { - v.state.v.LastProcessedHeight = height - v.state.v.LastVotedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { - if err := v.updateStateAfterFinalitySigSubmission(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to update state after finality sig submission") - } -} - func (v *ValidatorInstance) Start() error { if v.isStarted.Swap(true) { return fmt.Errorf("the validator instance %s is already started", v.GetBtcPkHex()) @@ -717,14 +565,11 @@ func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (b return false, nil } - // TODO: add retry here or within the query - power, err := v.cc.QueryValidatorVotingPower(v.GetBtcPkBIP340(), b.Height) + power, err := v.GetVotingPowerWithRetry(b.Height) if err != nil { return false, err } - v.updateStatusWithPower(power) - if power == 0 { v.logger.WithFields(logrus.Fields{ "btc_pk_hex": v.GetBtcPkHex(), @@ -939,21 +784,6 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. return res, nil } -func (v *ValidatorInstance) updateStatusWithPower(power uint64) { - if power == 0 { - if v.GetStatus() == proto.ValidatorStatus_ACTIVE { - // the validator is slashed or unbonded from the consumer chain - v.MustSetStatus(proto.ValidatorStatus_INACTIVE) - } - return - } - - // update the status - if v.GetStatus() == proto.ValidatorStatus_REGISTERED || v.GetStatus() == proto.ValidatorStatus_INACTIVE { - v.MustSetStatus(proto.ValidatorStatus_ACTIVE) - } -} - // SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*provider.RelayerTxResponse, error) { eotsSig, err := v.signEotsSig(b) @@ -1162,3 +992,53 @@ func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) return latestBlock, nil } + +func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, error) { + var ( + power uint64 + err error + ) + + if err := retry.Do(func() error { + power, err = v.cc.QueryValidatorVotingPower(v.GetBtcPkBIP340(), height) + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + v.logger.WithFields(logrus.Fields{ + "attempt": n + 1, + "max_attempts": RtyAttNum, + "error": err, + }).Debug("failed to query the voting power") + })); err != nil { + return 0, err + } + + return power, nil +} + +func (v *ValidatorInstance) GetSlashedHeightWithRetry() (uint64, error) { + var ( + slashedHeight uint64 + ) + + if err := retry.Do(func() error { + res, err := v.cc.QueryValidator(v.GetBtcPkBIP340()) + if err != nil { + return err + } + slashedHeight = res.SlashedBtcHeight + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + v.logger.WithFields(logrus.Fields{ + "attempt": n + 1, + "max_attempts": RtyAttNum, + "error": err, + }).Debug("failed to query the voting power") + })); err != nil { + return 0, err + } + + return slashedHeight, nil +} diff --git a/service/validator_manager.go b/service/validator_manager.go index 91ff32f1..ee084c3d 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -5,7 +5,9 @@ import ( "errors" "fmt" "sync" + "time" + "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -81,15 +83,17 @@ func (vm *ValidatorManager) monitorCriticalErr() { for { select { case criticalErr = <-vm.criticalErrChan: - vi, err := vm.getValidatorInstance(criticalErr.bbnPk) + vi, err := vm.GetValidatorInstance(criticalErr.bbnPk) if err != nil { panic(fmt.Errorf("failed to get the validator instance: %w", err)) } if errors.Is(criticalErr.err, types.ErrValidatorSlashed) { - vi.MustSetStatus(proto.ValidatorStatus_SLASHED) - if err := vm.removeValidatorInstance(vi.GetBabylonPk()); err != nil { - panic(fmt.Errorf("failed to terminate a slashed validator %s: %w", vi.GetBtcPkHex(), err)) - } + vm.setValidatorSlashed(vi) + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": vi.GetBtcPkHex(), + "old_status": vi.GetStatus(), + }).Debug("the validator status has been slashed") continue } vi.logger.WithFields(logrus.Fields{ @@ -102,6 +106,100 @@ func (vm *ValidatorManager) monitorCriticalErr() { } } +// monitorStatusUpdate periodically check the status of each managed validators and update +// it accordingly. We update the status by querying the latest voting power and the slashed_height. +// In particular, we perform the following status transitions (REGISTERED, ACTIVE, INACTIVE, SLASHED): +// 1. if power == 0 and slashed_height == 0, if status == ACTIVE, change to INACTIVE, otherwise remain the same +// 2. if power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the validator instance +// 3. if power > 0 (slashed_height must > 0), set status to ACTIVE +// NOTE: once error occurs, we log and continue as the status update is not critical to the entire program +func (vm *ValidatorManager) monitorStatusUpdate() { + defer vm.wg.Done() + + if vm.config.StatusUpdateInterval == 0 { + vm.logger.Info("the status update is disabled") + return + } + + statusUpdateTicker := time.NewTicker(vm.config.StatusUpdateInterval) + defer statusUpdateTicker.Stop() + + for { + select { + case <-statusUpdateTicker.C: + latestBlock, err := vm.getLatestBlockWithRetry() + if err != nil { + vm.logger.WithFields(logrus.Fields{ + "err": err, + }).Debug("failed to get the latest block") + continue + } + vals := vm.ListValidatorInstances() + for _, v := range vals { + power, err := v.GetVotingPowerWithRetry(latestBlock.Height) + if err != nil { + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": v.GetBtcPkHex(), + "height": latestBlock.Height, + }).Debug("failed to get the voting power") + continue + } + // power > 0 (slashed_height must > 0), set status to ACTIVE + if power > 0 { + if v.GetStatus() != proto.ValidatorStatus_ACTIVE { + v.MustSetStatus(proto.ValidatorStatus_ACTIVE) + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": v.GetBtcPkHex(), + "old_status": v.GetStatus(), + "power": power, + }).Debug("the validator status has changed to ACTIVE") + } + continue + } + slashedHeight, err := v.GetSlashedHeightWithRetry() + if err != nil { + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": v.GetBtcPkHex(), + }).Debug("failed to get the slashed height") + continue + } + // power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the validator instance + if slashedHeight > 0 { + vm.setValidatorSlashed(v) + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": v.GetBtcPkHex(), + "old_status": v.GetStatus(), + "slashed_height": slashedHeight, + }).Debug("the validator status has been slashed") + continue + } + // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE + if v.GetStatus() == proto.ValidatorStatus_ACTIVE { + v.MustSetStatus(proto.ValidatorStatus_INACTIVE) + vm.logger.WithFields(logrus.Fields{ + "err": err, + "val_btc_pk": v.GetBtcPkHex(), + "old_status": v.GetStatus(), + }).Debug("the validator status has changed to INACTIVE") + } + } + case <-vm.quit: + return + } + } +} + +func (vm *ValidatorManager) setValidatorSlashed(vi *ValidatorInstance) { + vi.MustSetStatus(proto.ValidatorStatus_SLASHED) + if err := vm.removeValidatorInstance(vi.GetBabylonPk()); err != nil { + panic(fmt.Errorf("failed to terminate a slashed validator %s: %w", vi.GetBtcPkHex(), err)) + } +} + func (vm *ValidatorManager) Start() error { if vm.isStarted.Swap(true) { return fmt.Errorf("the validator manager is already started") @@ -115,6 +213,9 @@ func (vm *ValidatorManager) Start() error { vm.wg.Add(1) go vm.monitorCriticalErr() + vm.wg.Add(1) + go vm.monitorStatusUpdate() + for _, v := range storedValidators { if err := vm.addValidatorInstance(v.GetBabylonPK()); err != nil { return err @@ -132,6 +233,9 @@ func (vm *ValidatorManager) Stop() error { var stopErr error for _, v := range vm.vals { + if !v.IsRunning() { + continue + } if err := v.Stop(); err != nil { stopErr = err break @@ -144,7 +248,7 @@ func (vm *ValidatorManager) Stop() error { return stopErr } -func (vm *ValidatorManager) listValidatorInstances() []*ValidatorInstance { +func (vm *ValidatorManager) ListValidatorInstances() []*ValidatorInstance { vm.mu.Lock() defer vm.mu.Unlock() @@ -156,7 +260,7 @@ func (vm *ValidatorManager) listValidatorInstances() []*ValidatorInstance { return valsList } -func (vm *ValidatorManager) getValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { +func (vm *ValidatorManager) GetValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { vm.mu.Lock() defer vm.mu.Unlock() @@ -213,3 +317,29 @@ func (vm *ValidatorManager) addValidatorInstance( return nil } + +func (vm *ValidatorManager) getLatestBlockWithRetry() (*types.BlockInfo, error) { + var latestBlock *types.BlockInfo + + if err := retry.Do(func() error { + headerResult, err := vm.cc.QueryBestHeader() + if err != nil { + return err + } + latestBlock = &types.BlockInfo{ + Height: uint64(headerResult.Header.Height), + LastCommitHash: headerResult.Header.LastCommitHash, + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + vm.logger.WithFields(logrus.Fields{ + "attempt": n + 1, + "max_attempts": RtyAttNum, + "error": err, + }).Debug("failed to query the consumer chain for the latest block") + })); err != nil { + return nil, err + } + + return latestBlock, nil +} diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go new file mode 100644 index 00000000..3f4ce5fd --- /dev/null +++ b/service/validator_manager_test.go @@ -0,0 +1,137 @@ +package service_test + +import ( + "math/rand" + "os" + "testing" + "time" + + "github.com/babylonchain/babylon/testutil/datagen" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + coretypes "github.com/cometbft/cometbft/rpc/core/types" + cometbfttypes "github.com/cometbft/cometbft/types" + "github.com/golang/mock/gomock" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/service" + "github.com/babylonchain/btc-validator/testutil" + "github.com/babylonchain/btc-validator/testutil/mocks" + "github.com/babylonchain/btc-validator/val" + "github.com/babylonchain/btc-validator/valcfg" +) + +var ( + eventuallyWaitTimeOut = 1 * time.Second + eventuallyPollTime = 10 * time.Millisecond +) + +func FuzzStatusUpdate(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + vm, cleanUp := newValidatorManagerWithRegisteredValidator(t, r, mockClientController) + defer cleanUp() + + // setup mocks + currentHeight := uint64(r.Int63n(100) + 1) + currentHeaderRes := &coretypes.ResultHeader{ + Header: &cometbfttypes.Header{ + Height: int64(currentHeight), + LastCommitHash: datagen.GenRandomByteArray(r, 32), + }, + } + mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() + status := &coretypes.ResultStatus{ + SyncInfo: coretypes.SyncInfo{LatestBlockHeight: int64(currentHeight)}, + } + mockClientController.EXPECT().QueryNodeStatus().Return(status, nil).AnyTimes() + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() + mockClientController.EXPECT().QueryHeader(gomock.Any()).Return(currentHeaderRes, nil).AnyTimes() + + votingPower := uint64(r.Intn(2)) + mockClientController.EXPECT().QueryValidatorVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() + var slashedHeight uint64 + if votingPower == 0 { + slashedHeight = uint64(r.Intn(2)) + btcVal := &bstypes.BTCValidator{SlashedBtcHeight: slashedHeight} + mockClientController.EXPECT().QueryValidator(gomock.Any()).Return(btcVal, nil).AnyTimes() + } + + err := vm.Start() + require.NoError(t, err) + valIns := vm.ListValidatorInstances()[0] + // stop the validator as we are testing static functionalities + err = valIns.Stop() + require.NoError(t, err) + + if votingPower > 0 { + waitForStatus(t, valIns, proto.ValidatorStatus_ACTIVE) + } else { + if slashedHeight == 0 && valIns.GetStatus() == proto.ValidatorStatus_ACTIVE { + waitForStatus(t, valIns, proto.ValidatorStatus_INACTIVE) + } else if slashedHeight > 0 { + waitForStatus(t, valIns, proto.ValidatorStatus_SLASHED) + } + } + }) +} + +func waitForStatus(t *testing.T, valIns *service.ValidatorInstance, s proto.ValidatorStatus) { + require.Eventually(t, + func() bool { + return valIns.GetStatus() == s + }, eventuallyWaitTimeOut, eventuallyPollTime) +} + +func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.ValidatorManager, func()) { + // create validator app with config + cfg := valcfg.DefaultConfig() + cfg.StatusUpdateInterval = 10 * time.Millisecond + cfg.DatabaseConfig = testutil.GenDBConfig(r, t) + cfg.BabylonConfig.KeyDirectory = t.TempDir() + logger := logrus.New() + + kr, err := service.CreateKeyring(cfg.BabylonConfig.KeyDirectory, + cfg.BabylonConfig.ChainID, + cfg.BabylonConfig.KeyringBackend) + require.NoError(t, err) + + valStore, err := val.NewValidatorStore(cfg.DatabaseConfig) + require.NoError(t, err) + + vm, err := service.NewValidatorManager(valStore, &cfg, kr, cc, logger) + require.NoError(t, err) + + // create registered validator + keyName := datagen.GenRandomHexStr(r, 10) + kc, err := val.NewKeyringControllerWithKeyring(kr, keyName) + require.NoError(t, err) + btcPk, bbnPk, err := kc.CreateValidatorKeys() + require.NoError(t, err) + pop, err := kc.CreatePop() + require.NoError(t, err) + + storedValidator := val.NewStoreValidator(bbnPk, btcPk, keyName, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + storedValidator.Status = proto.ValidatorStatus_REGISTERED + err = valStore.SaveValidator(storedValidator) + require.NoError(t, err) + + cleanUp := func() { + err = vm.Stop() + require.NoError(t, err) + err := os.RemoveAll(cfg.DatabaseConfig.Path) + require.NoError(t, err) + err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) + require.NoError(t, err) + } + + return vm, cleanUp +} diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 41b71dba..301fa30e 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -236,6 +236,21 @@ func (mr *MockClientControllerMockRecorder) QueryUnbondindBTCDelegations() *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondindBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondindBTCDelegations)) } +// QueryValidator mocks base method. +func (m *MockClientController) QueryValidator(btcPk *types.BIP340PubKey) (*types0.BTCValidator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryValidator", btcPk) + ret0, _ := ret[0].(*types0.BTCValidator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryValidator indicates an expected call of QueryValidator. +func (mr *MockClientControllerMockRecorder) QueryValidator(btcPk interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidator", reflect.TypeOf((*MockClientController)(nil).QueryValidator), btcPk) +} + // QueryValidatorVotingPower mocks base method. func (m *MockClientController) QueryValidatorVotingPower(btcPubKey *types.BIP340PubKey, blockHeight uint64) (uint64, error) { m.ctrl.T.Helper() diff --git a/valcfg/config.go b/valcfg/config.go index 7bce8982..636400e4 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -29,6 +29,7 @@ const ( defaultNumPubRand = 100 defaultNumPubRandMax = 100 defaultMinRandHeightGap = 10 + defaultStatusUpdateInterval = 5 * time.Second defaultRandomInterval = 5 * time.Second defautlUnbondingSigSubmissionInterval = 20 * time.Second defaultSubmitRetryInterval = 1 * time.Second @@ -65,6 +66,7 @@ type Config struct { NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` + StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of validator status"` RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` UnbondingSigSubmissionInterval time.Duration `long:"unbondingsigsubmissioninterval" description:"The interval between each attempt to check and submit unbonding signature"` @@ -115,6 +117,7 @@ func DefaultConfig() Config { NumPubRand: defaultNumPubRand, NumPubRandMax: defaultNumPubRandMax, MinRandHeightGap: defaultMinRandHeightGap, + StatusUpdateInterval: defaultStatusUpdateInterval, RandomnessCommitInterval: defaultRandomInterval, SubmissionRetryInterval: defaultSubmitRetryInterval, UnbondingSigSubmissionInterval: defautlUnbondingSigSubmissionInterval, From 232e0474149eeb3915c41023871d3df59768d18f Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 29 Sep 2023 19:01:16 +0800 Subject: [PATCH 02/66] chore: Modularize EOTS manager (#112) --- eotsmanager/eotsmanager.go | 36 ++++ eotsmanager/errors.go | 8 + eotsmanager/local/eotsstore.go | 118 +++++++++++++ eotsmanager/local/localmanager.go | 232 +++++++++++++++++++++++++ eotsmanager/local/localmanager_test.go | 85 +++++++++ itest/test_manager.go | 2 +- service/types.go | 7 - service/validator_instance.go | 13 +- service/validator_manager.go | 11 +- testutil/datagen.go | 12 ++ types/randpair.go | 24 +++ val/valstore.go | 8 +- valcfg/config.go | 6 +- valcfg/eotsmanager.go | 45 +++++ 14 files changed, 584 insertions(+), 23 deletions(-) create mode 100644 eotsmanager/eotsmanager.go create mode 100644 eotsmanager/errors.go create mode 100644 eotsmanager/local/eotsstore.go create mode 100644 eotsmanager/local/localmanager.go create mode 100644 eotsmanager/local/localmanager_test.go create mode 100644 types/randpair.go create mode 100644 valcfg/eotsmanager.go diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go new file mode 100644 index 00000000..21362735 --- /dev/null +++ b/eotsmanager/eotsmanager.go @@ -0,0 +1,36 @@ +package eotsmanager + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" +) + +type EOTSManager interface { + // CreateValidator generates a key pair to create a unique validator object + // and persists it in storage. The key pair is formatted by BIP-340 (Schnorr Signatures) + // It fails if there is an existing key Info with the same name or public key. + CreateValidator(name, passPhrase string) ([]byte, error) + + // CreateRandomnessPairList generates and persists a list of Schnorr randomness pairs from + // startHeight to startHeight+(num-1)*step where step means the gap between each block height + // that the validator wants to finalize and num means the number of public randomness + // It fails if the validator does not exist or a randomness pair has been created before + // NOTE: it will overwrite the randomness regardless of whether there's one existed + CreateRandomnessPairList(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) + + // CreateRandomnessPairListWithExistenceCheck checks the existence of randomness by given height + // before calling CreateRandomnessPairList. + // It fails if there's randomness existed at a given height + CreateRandomnessPairListWithExistenceCheck(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) + + // SignEOTS signs an EOTS using the private key of the validator and the corresponding + // secret randomness of the give chain at the given height + // It fails if the validator does not exist or there's no randomness committed to the given height + SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64) (*btcec.ModNScalar, error) + + // SignSchnorrSig signs a Schnorr signature using the private key of the validator + // It fails if the validator does not exist or the message size is not 32 bytes + SignSchnorrSig(uid []byte, msg []byte) (*schnorr.Signature, error) + + Close() error +} diff --git a/eotsmanager/errors.go b/eotsmanager/errors.go new file mode 100644 index 00000000..5847d476 --- /dev/null +++ b/eotsmanager/errors.go @@ -0,0 +1,8 @@ +package eotsmanager + +import "errors" + +var ( + ErrValidatorAlreadyExisted = errors.New("the validator has already existed") + ErrSchnorrRandomnessALreadyCreated = errors.New("the Schnorr randomness has already been created") +) diff --git a/eotsmanager/local/eotsstore.go b/eotsmanager/local/eotsstore.go new file mode 100644 index 00000000..8afe0356 --- /dev/null +++ b/eotsmanager/local/eotsstore.go @@ -0,0 +1,118 @@ +package local + +import ( + "fmt" + + sdktypes "github.com/cosmos/cosmos-sdk/types" + gproto "google.golang.org/protobuf/proto" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/store" + "github.com/babylonchain/btc-validator/valcfg" +) + +const ( + randPairPrefix = "rand-pair" + validatorKeyNamePrefix = "val-key" +) + +type EOTSStore struct { + s store.Store +} + +func NewEOTSStore(cfg *valcfg.EOTSManagerConfig) (*EOTSStore, error) { + s, err := openStore(cfg) + 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) saveValidatorKey(pk []byte, keyName string) error { + k := getValidatorKeyNameKey(pk) + + exists, err := es.s.Exists(k) + if err != nil { + return nil + } + if exists { + return eotsmanager.ErrValidatorAlreadyExisted + } + + return es.s.Put(k, []byte(keyName)) +} + +func (es *EOTSStore) saveRandPair(pk []byte, chainID []byte, height uint64, randPair *proto.SchnorrRandPair) error { + k := getRandPairKey(pk, chainID, height) + v, err := gproto.Marshal(randPair) + if err != nil { + return fmt.Errorf("failed to marshal the Schnorr random pair: %w", err) + } + + if err := es.s.Put(k, v); err != nil { + return fmt.Errorf("failed to save the Schnorr random pair: %w", err) + } + + return nil +} + +func (es *EOTSStore) getRandPair(pk []byte, chainID []byte, height uint64) (*proto.SchnorrRandPair, error) { + k := getRandPairKey(pk, chainID, height) + v, err := es.s.Get(k) + if err != nil { + return nil, err + } + + pair := new(proto.SchnorrRandPair) + if err := gproto.Unmarshal(v, pair); err != nil { + return nil, err + } + + return pair, nil +} + +func (es *EOTSStore) randPairExists(pk []byte, chainID []byte, height uint64) (bool, error) { + k := getRandPairKey(pk, chainID, height) + return es.s.Exists(k) +} + +func getRandPairKey(pk []byte, chainID []byte, height uint64) []byte { + return append(getRandPairListKey(pk, chainID), sdktypes.Uint64ToBigEndian(height)...) +} + +func getRandPairListKey(pk []byte, chainID []byte) []byte { + return append(append([]byte(randPairPrefix), pk...), chainID...) +} + +func (es *EOTSStore) getValidatorKeyName(pk []byte) (string, error) { + k := getValidatorKeyNameKey(pk) + v, err := es.s.Get(k) + if err != nil { + return "", err + } + + return string(v), nil +} + +func getValidatorKeyNameKey(pk []byte) []byte { + return append([]byte(validatorKeyNamePrefix), pk...) +} + +func openStore(dbcfg *valcfg.EOTSManagerConfig) (store.Store, error) { + switch dbcfg.DBBackend { + case "bbolt": + return store.NewBboltStore(dbcfg.DBPath, dbcfg.DBName) + default: + return nil, fmt.Errorf("unsupported database type") + } +} diff --git a/eotsmanager/local/localmanager.go b/eotsmanager/local/localmanager.go new file mode 100644 index 00000000..ca27685a --- /dev/null +++ b/eotsmanager/local/localmanager.go @@ -0,0 +1,232 @@ +package local + +import ( + "fmt" + "math/rand" + "time" + + "github.com/babylonchain/babylon/crypto/eots" + bbntypes "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/go-bip39" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/valcfg" +) + +const ( + secp256k1Type = "secp256k1" + mnemonicEntropySize = 256 +) + +type LocalEOTSManager struct { + kr keyring.Keyring + es *EOTSStore +} + +func NewLocalEOTSManager(ctx client.Context, keyringBackend string, eotsCfg *valcfg.EOTSManagerConfig) (*LocalEOTSManager, error) { + if keyringBackend == "" { + return nil, fmt.Errorf("the keyring backend should not be empty") + } + + kr, err := keyring.New( + ctx.ChainID, + // TODO currently only support test backend + keyringBackend, + ctx.KeyringDir, + ctx.Input, + ctx.Codec, + ctx.KeyringOptions...) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + es, err := NewEOTSStore(eotsCfg) + if err != nil { + return nil, fmt.Errorf("failed to open the store for validators: %w", err) + } + + return &LocalEOTSManager{ + kr: kr, + es: es, + }, nil +} + +func (lm *LocalEOTSManager) CreateValidator(name, passPhrase string) ([]byte, error) { + if lm.keyExists(name) { + return nil, eotsmanager.ErrValidatorAlreadyExisted + } + + keyringAlgos, _ := lm.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 + } + + // TODO for now we leave and hdPath empty + record, err := lm.kr.NewAccount(name, mnemonic, passPhrase, "", algo) + if err != nil { + return nil, err + } + + pubKey, err := record.GetPubKey() + 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.saveValidatorKey(eotsPk.MustMarshal(), name); err != nil { + return nil, err + } + + return eotsPk.MustMarshal(), nil +} + +func (lm *LocalEOTSManager) CreateRandomnessPairListWithExistenceCheck(valPk []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { + // check whether the randomness is created already + for i := uint32(0); i < num; i++ { + height := startHeight + uint64(i) + exists, err := lm.es.randPairExists(valPk, chainID, height) + if err != nil { + return nil, err + } + if exists { + return nil, eotsmanager.ErrSchnorrRandomnessALreadyCreated + } + } + + return lm.CreateRandomnessPairList(valPk, chainID, startHeight, num) +} + +func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { + prList := make([]*btcec.FieldVal, 0, num) + + // TODO improve the security of randomness generation if concerned + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + for i := uint32(0); i < num; i++ { + // generate randomness pair + eotsSR, eotsPR, err := eots.RandGen(r) + if err != nil { + return nil, fmt.Errorf("failed to generate randomness pair: %w", err) + } + + // persists randomness pair + height := startHeight + uint64(i) + privRand := eotsSR.Bytes() + pubRand := eotsPR.Bytes() + randPair, err := types.NewSchnorrRandPair(privRand[:], pubRand[:]) + if err != nil { + return nil, fmt.Errorf("invalid Schnorr randomness") + } + if err := lm.es.saveRandPair(valPk, chainID, height, randPair); err != nil { + return nil, fmt.Errorf("failed to save randomness pair: %w", err) + } + + prList = append(prList, eotsPR) + } + + return prList, nil +} + +func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, height uint64) (*btcec.ModNScalar, error) { + privRand, err := lm.getPrivRandomness(valPk, chainID, height) + if err != nil { + return nil, fmt.Errorf("failed to get private randomness: %w", err) + } + + privKey, err := lm.getEOTSPrivKey(valPk) + if err != nil { + return nil, fmt.Errorf("failed to get EOTS private key: %w", err) + } + + return eots.Sign(privKey, privRand, msg) +} + +func (lm *LocalEOTSManager) SignSchnorrSig(valPk []byte, msg []byte) (*schnorr.Signature, error) { + privKey, err := lm.getEOTSPrivKey(valPk) + if err != nil { + return nil, fmt.Errorf("failed to get EOTS private key: %w", err) + } + + return schnorr.Sign(privKey, msg) +} + +func (lm *LocalEOTSManager) Close() error { + return lm.es.Close() +} + +func (lm *LocalEOTSManager) getPrivRandomness(valPk []byte, chainID []byte, height uint64) (*eots.PrivateRand, error) { + randPair, err := lm.es.getRandPair(valPk, chainID, height) + if err != nil { + return nil, err + } + + if len(randPair.SecRand) != types.SchnorrRandomnessLength { + return nil, fmt.Errorf("the private randomness should be 32 bytes") + } + + privRand := new(eots.PrivateRand) + privRand.SetByteSlice(randPair.SecRand) + + return privRand, nil +} + +func (lm *LocalEOTSManager) GetValidatorKeyName(valPk []byte) (string, error) { + return lm.es.getValidatorKeyName(valPk) +} + +func (lm *LocalEOTSManager) getEOTSPrivKey(valPk []byte) (*btcec.PrivateKey, error) { + keyName, err := lm.es.getValidatorKeyName(valPk) + if err != nil { + return nil, err + } + + k, err := lm.kr.Key(keyName) + if err != nil { + return nil, err + } + + privKeyCached := k.GetLocal().PrivKey.GetCachedValue() + + var privKey *btcec.PrivateKey + switch v := privKeyCached.(type) { + case *secp256k1.PrivKey: + privKey, _ = btcec.PrivKeyFromBytes(v.Key) + return privKey, nil + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } +} + +func (lm *LocalEOTSManager) keyExists(name string) bool { + _, err := lm.kr.Key(name) + return err == nil +} diff --git a/eotsmanager/local/localmanager_test.go b/eotsmanager/local/localmanager_test.go new file mode 100644 index 00000000..ffff08a2 --- /dev/null +++ b/eotsmanager/local/localmanager_test.go @@ -0,0 +1,85 @@ +package local_test + +import ( + "math/rand" + "os" + "testing" + + "github.com/babylonchain/babylon/testutil/datagen" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/local" + "github.com/babylonchain/btc-validator/testutil" +) + +// FuzzCreateValidator tests the creation of validator +func FuzzCreateValidator(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + valName := testutil.GenRandomHexStr(r, 4) + sdkCtx := testutil.GenSdkContext(r, t) + eotsCfg := testutil.GenEOTSConfig(r, t) + defer func() { + err := os.RemoveAll(sdkCtx.KeyringDir) + require.NoError(t, err) + err = os.RemoveAll(eotsCfg.DBPath) + require.NoError(t, err) + }() + + lm, err := local.NewLocalEOTSManager(sdkCtx, "test", eotsCfg) + require.NoError(t, err) + + valPk, err := lm.CreateValidator(valName, "") + require.NoError(t, err) + + storedKeyName, err := lm.GetValidatorKeyName(valPk) + require.NoError(t, err) + require.Equal(t, valName, storedKeyName) + + sig, err := lm.SignSchnorrSig(valPk, datagen.GenRandomByteArray(r, 32)) + require.NoError(t, err) + require.NotNil(t, sig) + + _, err = lm.CreateValidator(valName, "") + require.ErrorIs(t, err, eotsmanager.ErrValidatorAlreadyExisted) + }) +} + +func FuzzCreateRandomnessPairList(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + valName := testutil.GenRandomHexStr(r, 4) + sdkCtx := testutil.GenSdkContext(r, t) + eotsCfg := testutil.GenEOTSConfig(r, t) + defer func() { + err := os.RemoveAll(sdkCtx.KeyringDir) + require.NoError(t, err) + err = os.RemoveAll(eotsCfg.DBPath) + require.NoError(t, err) + }() + + lm, err := local.NewLocalEOTSManager(sdkCtx, "test", eotsCfg) + require.NoError(t, err) + + valPk, err := lm.CreateValidator(valName, "") + require.NoError(t, err) + + chainID := datagen.GenRandomByteArray(r, 10) + startHeight := datagen.RandomInt(r, 100) + num := r.Intn(10) + 1 + pubRandList, err := lm.CreateRandomnessPairList(valPk, chainID, startHeight, uint32(num)) + require.NoError(t, err) + require.Len(t, pubRandList, num) + + for i := 0; i < num; i++ { + sig, err := lm.SignEOTS(valPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i)) + require.NoError(t, err) + require.NotNil(t, sig) + } + }) +} diff --git a/itest/test_manager.go b/itest/test_manager.go index 47e875a2..497f4c64 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -531,7 +531,7 @@ func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Con // errors cfg.BabylonConfig.Key = "test-spending-key" // Big adjustment to make sure we have enough gas in our transactions - cfg.BabylonConfig.GasAdjustment = 10 + cfg.BabylonConfig.GasAdjustment = 20 cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") cfg.JuryMode = isJury cfg.JuryModeConfig.QueryInterval = 7 * time.Second diff --git a/service/types.go b/service/types.go index ee3f6006..647005bd 100644 --- a/service/types.go +++ b/service/types.go @@ -87,13 +87,6 @@ func (vs *valState) setStatus(s proto.ValidatorStatus) error { return vs.s.UpdateValidator(vs.v) } -func (vs *valState) setLastVotedHeight(height uint64) error { - vs.mu.Lock() - vs.v.LastVotedHeight = height - vs.mu.Unlock() - return vs.s.UpdateValidator(vs.v) -} - func (vs *valState) setLastProcessedHeight(height uint64) error { vs.mu.Lock() vs.v.LastProcessedHeight = height diff --git a/service/validator_instance.go b/service/validator_instance.go index 5a0871ae..de56b4d5 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -764,9 +764,12 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. for i, pr := range privRandList { height := startHeight + uint64(i) privRand := pr.Bytes() - randPair := &proto.SchnorrRandPair{ - SecRand: privRand[:], - PubRand: pubRandList[i].MustMarshal(), + randPair, err := types.NewSchnorrRandPair(privRand[:], pubRandList[i].MustMarshal()) + if err != nil { + v.logger.WithFields(logrus.Fields{ + "err": err, + "btc_pk_hex": v.GetBtcPkHex(), + }).Fatal("invalid Schnorr randomness") } err = v.state.s.SaveRandPair(v.GetBabylonPk().Key, height, randPair) if err != nil { @@ -957,8 +960,8 @@ func (v *ValidatorInstance) getCommittedPrivPubRand(height uint64) (*eots.Privat return nil, err } - if len(randPair.SecRand) != 32 { - return nil, fmt.Errorf("the private randomness should be 32 bytes") + if len(randPair.SecRand) != types.SchnorrRandomnessLength { + return nil, fmt.Errorf("the private randomness should be %v bytes", types.SchnorrRandomnessLength) } privRand := new(eots.PrivateRand) diff --git a/service/validator_manager.go b/service/validator_manager.go index ee084c3d..54e9df1d 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -32,6 +32,10 @@ type CriticalError struct { bbnPk *secp256k1.PubKey } +func (ce *CriticalError) Error() string { + return fmt.Sprintf("critical err on validator %s: %s", ce.valBtcPk.MarshalHex(), ce.err.Error()) +} + type ValidatorManager struct { isStarted *atomic.Bool @@ -90,15 +94,12 @@ func (vm *ValidatorManager) monitorCriticalErr() { if errors.Is(criticalErr.err, types.ErrValidatorSlashed) { vm.setValidatorSlashed(vi) vm.logger.WithFields(logrus.Fields{ - "err": err, - "val_btc_pk": vi.GetBtcPkHex(), - "old_status": vi.GetStatus(), + "err": criticalErr, }).Debug("the validator status has been slashed") continue } vi.logger.WithFields(logrus.Fields{ - "err": criticalErr.err, - "btc_pk_hex": vi.GetBtcPkHex(), + "err": criticalErr, }).Fatal(instanceTerminatingMsg) case <-vm.quit: return diff --git a/testutil/datagen.go b/testutil/datagen.go index 73808347..9c19d455 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -117,6 +117,18 @@ func GenDBConfig(r *rand.Rand, t *testing.T) *valcfg.DatabaseConfig { return dbcfg } +func GenEOTSConfig(r *rand.Rand, t *testing.T) *valcfg.EOTSManagerConfig { + bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" + path := filepath.Join(t.TempDir(), bucketName) + eotsCfg, err := valcfg.NewEOTSManagerConfig( + "bbolt", + path, + bucketName, + ) + require.NoError(t, err) + return eotsCfg +} + func GenSdkContext(r *rand.Rand, t *testing.T) client.Context { chainID := "testchain-" + GenRandomHexStr(r, 4) dir := t.TempDir() diff --git a/types/randpair.go b/types/randpair.go new file mode 100644 index 00000000..b883afd8 --- /dev/null +++ b/types/randpair.go @@ -0,0 +1,24 @@ +package types + +import ( + "fmt" + + "github.com/babylonchain/btc-validator/proto" +) + +const SchnorrRandomnessLength = 32 + +func NewSchnorrRandPair(privRand []byte, pubRand []byte) (*proto.SchnorrRandPair, error) { + if len(privRand) != SchnorrRandomnessLength { + return nil, fmt.Errorf("a private randomness should be %v bytes", SchnorrRandomnessLength) + } + + if len(pubRand) != SchnorrRandomnessLength { + return nil, fmt.Errorf("a public randomness should be %v bytes", SchnorrRandomnessLength) + } + + return &proto.SchnorrRandPair{ + PubRand: pubRand, + SecRand: privRand, + }, nil +} diff --git a/val/valstore.go b/val/valstore.go index b81570bb..9a9605e8 100644 --- a/val/valstore.go +++ b/val/valstore.go @@ -49,7 +49,7 @@ func NewValidatorStore(dbcfg *valcfg.DatabaseConfig) (*ValidatorStore, error) { return &ValidatorStore{s: s}, nil } -func (vs *ValidatorStore) getValidatorKey(pk []byte) []byte { +func getValidatorKey(pk []byte) []byte { return append([]byte(validatorPrefix), pk...) } @@ -66,7 +66,7 @@ func (vs *ValidatorStore) getRandPairListKey(pk []byte) []byte { } func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { - k := vs.getValidatorKey(val.BabylonPk) + k := getValidatorKey(val.BabylonPk) v, err := gproto.Marshal(val) if err != nil { return fmt.Errorf("failed to marshal the created validator object: %w", err) @@ -80,7 +80,7 @@ func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { } func (vs *ValidatorStore) UpdateValidator(val *proto.StoreValidator) error { - k := vs.getValidatorKey(val.BabylonPk) + k := getValidatorKey(val.BabylonPk) exists, err := vs.s.Exists(k) if err != nil { return err @@ -156,7 +156,7 @@ func (vs *ValidatorStore) GetRandPair(pk []byte, height uint64) (*proto.SchnorrR } func (vs *ValidatorStore) GetStoreValidator(pk []byte) (*proto.StoreValidator, error) { - k := vs.getValidatorKey(pk) + k := getValidatorKey(pk) valsBytes, err := vs.s.Get(k) if err != nil { return nil, err diff --git a/valcfg/config.go b/valcfg/config.go index 636400e4..723e750a 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -83,7 +83,9 @@ type Config struct { PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` - DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaserpcconfig"` + DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` + + EOTSManagerConfig *EOTSManagerConfig `group:"eotsmanagerconfig" namespace:"eotsmanagerconfig"` BabylonConfig *BBNConfig `group:"babylon" namespace:"babylon"` @@ -102,6 +104,7 @@ func DefaultConfig() Config { juryCfg := DefaultJuryConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() + eotsMngrCfg := DefaultEOTSManagerConfig() return Config{ ValdDir: DefaultValdDir, ChainName: defaultChainName, @@ -114,6 +117,7 @@ func DefaultConfig() Config { ValidatorModeConfig: &valCfg, JuryModeConfig: &juryCfg, PollerConfig: &pollerCfg, + EOTSManagerConfig: &eotsMngrCfg, NumPubRand: defaultNumPubRand, NumPubRandMax: defaultNumPubRandMax, MinRandHeightGap: defaultMinRandHeightGap, diff --git a/valcfg/eotsmanager.go b/valcfg/eotsmanager.go new file mode 100644 index 00000000..6c82e579 --- /dev/null +++ b/valcfg/eotsmanager.go @@ -0,0 +1,45 @@ +package valcfg + +import ( + "fmt" +) + +const ( + DefaultEOTSManagerDBBackend = "bbolt" + DefaultEOTSManagerDBPath = "bbolt-eots.db" + DefaultEOTSManagerDBName = "eots-default" +) + +type EOTSManagerConfig struct { + DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` + DBPath string `long:"dbpath" description:"The path that stores the database file"` + DBName string `long:"dbname" description:"The name of the database"` +} + +func NewEOTSManagerConfig(backend string, path string, name string) (*EOTSManagerConfig, error) { + if backend != DefaultEOTSManagerDBBackend { + return nil, fmt.Errorf("unsupported DB backend") + } + + if path == "" { + return nil, fmt.Errorf("DB path should not be empty") + } + + if name == "" { + return nil, fmt.Errorf("bucket name should not be empty") + } + + return &EOTSManagerConfig{ + DBBackend: backend, + DBPath: path, + DBName: name, + }, nil +} + +func DefaultEOTSManagerConfig() EOTSManagerConfig { + return EOTSManagerConfig{ + DBBackend: DefaultEOTSManagerDBBackend, + DBPath: DefaultEOTSManagerDBPath, + DBName: DefaultEOTSManagerDBName, + } +} From 4321d7fbc418af6d1e92d17d4218bcb45201cc51 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 11 Oct 2023 14:53:24 +0800 Subject: [PATCH 03/66] Integrate EOTS manager (#115) --- cmd/valcli/daemoncmd.go | 59 ++-- cmd/valcli/jury.go | 17 +- cmd/valcli/main.go | 1 - cmd/valcli/validators.go | 220 ------------- cmd/vald/main.go | 9 +- eotsmanager/config/config.go | 55 ++++ eotsmanager/eotsmanager.go | 42 ++- eotsmanager/local/eotsstore.go | 10 +- eotsmanager/local/localmanager.go | 33 +- eotsmanager/local/localmanager_test.go | 18 +- eotsmanager/types/errors.go | 8 + eotsmanager/types/val_record.go | 8 + go.mod | 2 +- itest/babylon_node_handler.go | 16 +- itest/e2e_test.go | 22 +- itest/test_manager.go | 38 ++- proto/validators.pb.go | 411 +++++++++++++------------ proto/validators.proto | 36 ++- service/app.go | 164 +++++----- service/app_test.go | 46 ++- service/client/rpcclient.go | 17 +- service/event_loop.go | 31 +- service/fastsync_test.go | 6 +- service/rpcserver.go | 32 +- service/types.go | 30 +- service/validator_instance.go | 104 +++---- service/validator_instance_test.go | 34 +- service/validator_manager.go | 39 +-- service/validator_manager_test.go | 26 +- testutil/datagen.go | 30 +- val/keyringcontroller.go | 193 +++--------- val/keyringcontroller_test.go | 27 +- val/valstore.go | 65 +--- val/valstore_test.go | 4 +- valcfg/eotsmanager.go | 16 + 35 files changed, 841 insertions(+), 1028 deletions(-) delete mode 100644 cmd/valcli/validators.go create mode 100644 eotsmanager/config/config.go create mode 100644 eotsmanager/types/errors.go create mode 100644 eotsmanager/types/val_record.go diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index 465ea5be..d41053c7 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -2,16 +2,15 @@ package main import ( "context" - "encoding/hex" "fmt" "strconv" "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" "github.com/babylonchain/babylon/x/checkpointing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" - "github.com/babylonchain/btc-validator/proto" dc "github.com/babylonchain/btc-validator/service/client" "github.com/babylonchain/btc-validator/valcfg" ) @@ -36,9 +35,15 @@ var daemonCommands = []cli.Command{ const ( valdDaemonAddressFlag = "daemon-address" keyNameFlag = "key-name" - valBabylonPkFlag = "babylon-pk" + valBTCPkFlag = "btc-pk" blockHeightFlag = "height" lastCommitHashFlag = "last-commit-hash" + passPhraseFlag = "pass-phrase" + chainIdFlag = "chain-id" + keyringDirFlag = "keyring-dir" + keyringBackendFlag = "keyring-backend" + defaultChainID = "chain-test" + defaultKeyringBackend = "test" // flags for description monikerFlag = "moniker" @@ -103,6 +108,15 @@ var createValDaemonCmd = cli.Command{ Usage: "The unique name of the validator key", Required: true, }, + cli.StringFlag{ + Name: chainIdFlag, + Usage: "The identifier of the consumer chain", + Required: true, + }, + cli.StringFlag{ + Name: passPhraseFlag, + Usage: "The pass phrase used to encrypt the keys", + }, cli.StringFlag{ Name: commissionRateFlag, Usage: "The commission rate for the validator, e.g., 0.05", @@ -157,7 +171,7 @@ func createValDaemon(ctx *cli.Context) error { } defer cleanUp() - info, err := client.CreateValidator(context.Background(), keyName, &description, &commissionRate) + info, err := client.CreateValidator(context.Background(), keyName, ctx.String(chainIdFlag), ctx.String(passPhraseFlag), &description, &commissionRate) if err != nil { return err @@ -169,7 +183,6 @@ func createValDaemon(ctx *cli.Context) error { } func getDesciptionFromContext(ctx *cli.Context) (stakingtypes.Description, error) { - // get information for description monikerStr := ctx.String(monikerFlag) identityStr := ctx.String(identityFlag) @@ -224,8 +237,8 @@ var valInfoDaemonCmd = cli.Command{ Value: defaultValdDaemonAddress, }, cli.StringFlag{ - Name: valBabylonPkFlag, - Usage: "The hex string of the Babylon public key", + Name: valBTCPkFlag, + Usage: "The hex string of the BTC public key", Required: true, }, }, @@ -240,12 +253,12 @@ func valInfoDaemon(ctx *cli.Context) error { } defer cleanUp() - bbnPkBytes, err := hex.DecodeString(ctx.String(valBabylonPkFlag)) + valPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(valBTCPkFlag)) if err != nil { return err } - resp, err := rpcClient.QueryValidatorInfo(context.Background(), bbnPkBytes) + resp, err := rpcClient.QueryValidatorInfo(context.Background(), valPk) if err != nil { return err } @@ -267,8 +280,8 @@ var registerValDaemonCmd = cli.Command{ Value: defaultValdDaemonAddress, }, cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the validator key", + Name: valBTCPkFlag, + Usage: "The hex string of the validator BTC public key", Required: true, }, }, @@ -276,7 +289,11 @@ var registerValDaemonCmd = cli.Command{ } func registerVal(ctx *cli.Context) error { - keyName := ctx.String(keyNameFlag) + valPkStr := ctx.String(valBTCPkFlag) + valPk, err := bbntypes.NewBIP340PubKeyFromHex(valPkStr) + if err != nil { + return fmt.Errorf("invalid BTC public key: %w", err) + } daemonAddress := ctx.String(valdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) @@ -285,7 +302,7 @@ func registerVal(ctx *cli.Context) error { } defer cleanUp() - res, err := rpcClient.RegisterValidator(context.Background(), keyName) + res, err := rpcClient.RegisterValidator(context.Background(), valPk) if err != nil { return err } @@ -300,8 +317,8 @@ func registerVal(ctx *cli.Context) error { var addFinalitySigDaemonCmd = cli.Command{ Name: "add-finality-sig", ShortName: "afs", - Usage: "Send a finality signature to Babylon. This command should only be used for presentation/testing purposes", - UsageText: fmt.Sprintf("add-finality-sig --%s [babylon_pk_hex]", valBabylonPkFlag), + Usage: "Send a finality signature to the consumer chain. This command should only be used for presentation/testing purposes", + UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", valBTCPkFlag), Flags: []cli.Flag{ cli.StringFlag{ Name: valdDaemonAddressFlag, @@ -309,18 +326,18 @@ var addFinalitySigDaemonCmd = cli.Command{ Value: defaultValdDaemonAddress, }, cli.StringFlag{ - Name: valBabylonPkFlag, - Usage: "The hex string of the Babylon public key", + Name: valBTCPkFlag, + Usage: "The hex string of the BTC public key", Required: true, }, cli.Uint64Flag{ Name: blockHeightFlag, - Usage: "The height of the Babylon block", + Usage: "The height of the chain block", Required: true, }, cli.StringFlag{ Name: lastCommitHashFlag, - Usage: "The last commit hash of the Babylon block", + Usage: "The last commit hash of the chain block", Value: defaultLastCommitHashStr, }, }, @@ -335,7 +352,7 @@ func addFinalitySig(ctx *cli.Context) error { } defer cleanUp() - bbnPk, err := proto.NewBabylonPkFromHex(ctx.String(valBabylonPkFlag)) + valPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(valBTCPkFlag)) if err != nil { return err } @@ -346,7 +363,7 @@ func addFinalitySig(ctx *cli.Context) error { } res, err := rpcClient.AddFinalitySignature( - context.Background(), bbnPk.Key, ctx.Uint64(blockHeightFlag), lch) + context.Background(), valPk.MarshalHex(), ctx.Uint64(blockHeightFlag), lch) if err != nil { return err } diff --git a/cmd/valcli/jury.go b/cmd/valcli/jury.go index 13a78c45..777ec0e5 100644 --- a/cmd/valcli/jury.go +++ b/cmd/valcli/jury.go @@ -2,7 +2,9 @@ package main import ( "fmt" + "github.com/babylonchain/babylon/types" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/urfave/cli" @@ -64,27 +66,28 @@ func createJuryKey(ctx *cli.Context) error { return err } - krController, err := val.NewKeyringController( + krController, err := val.NewChainKeyringController( sdkCtx, ctx.String(keyNameFlag), + ctx.String(chainIdFlag), ctx.String(keyringBackendFlag), ) if err != nil { return err } - if krController.JuryKeyTaken() { - return fmt.Errorf("the Jury key name %s is taken", krController.GetKeyName()) - } - - juryPk, err := krController.CreateJuryKey() + sdkJuryPk, err := krController.CreateChainKey() if err != nil { return fmt.Errorf("failed to create Jury key: %w", err) } + juryPk, err := secp256k1.ParsePubKey(sdkJuryPk.Key) + if err != nil { + return err + } bip340Key := types.NewBIP340PubKeyFromBTCPK(juryPk) printRespJSON(&juryKey{ - Name: krController.GetKeyName(), + Name: ctx.String(keyNameFlag), PublicKey: bip340Key.MarshalHex(), }) diff --git a/cmd/valcli/main.go b/cmd/valcli/main.go index a5a593db..ec06f622 100644 --- a/cmd/valcli/main.go +++ b/cmd/valcli/main.go @@ -54,7 +54,6 @@ func main() { } app.Commands = append(app.Commands, daemonCommands...) - app.Commands = append(app.Commands, validatorsCommands...) app.Commands = append(app.Commands, adminCommands...) app.Commands = append(app.Commands, juryCommands...) diff --git a/cmd/valcli/validators.go b/cmd/valcli/validators.go deleted file mode 100644 index a69accf9..00000000 --- a/cmd/valcli/validators.go +++ /dev/null @@ -1,220 +0,0 @@ -package main - -import ( - "encoding/hex" - "fmt" - - "cosmossdk.io/math" - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" -) - -const ( - chainIdFlag = "chain-id" - keyringDirFlag = "keyring-dir" - keyringBackendFlag = "keyring-backend" - defaultChainID = "chain-test" - defaultKeyringBackend = "test" -) - -var validatorsCommands = []cli.Command{ - { - Name: "validators", - ShortName: "vals", - Usage: "Control Bitcoin validators.", - Category: "Validators", - Subcommands: []cli.Command{ - createValCmd, listValCmd, importValCmd, - }, - }, -} - -var createValCmd = cli.Command{ - Name: "create-validator", - ShortName: "cv", - Usage: "Create a Bitcoin validator object and save it in database.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: chainIdFlag, - Usage: "The chainID of the Babylonchain", - Value: defaultChainID, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the validator key", - Required: true, - }, - cli.StringFlag{ - Name: keyringBackendFlag, - Usage: "Select keyring's backend (os|file|test)", - Value: defaultKeyringBackend, - }, - cli.StringFlag{ - Name: keyringDirFlag, - Usage: "The directory where the keyring is stored", - }, - cli.StringFlag{ - Name: commissionRateFlag, - Usage: "The commission rate for the validator, e.g., 0.05", - Value: "0.05", - }, - cli.StringFlag{ - Name: monikerFlag, - Usage: "A human-readable name for the validator", - Value: "", - }, - cli.StringFlag{ - Name: identityFlag, - Usage: "An optional identity signature (ex. UPort or Keybase)", - Value: "", - }, - cli.StringFlag{ - Name: websiteFlag, - Usage: "An optional website link", - Value: "", - }, - cli.StringFlag{ - Name: securityContractFlag, - Usage: "An optional email for security contact", - Value: "", - }, - cli.StringFlag{ - Name: detailsFlag, - Usage: "Other optional details", - Value: "", - }, - }, - Action: createVal, -} - -func createVal(ctx *cli.Context) error { - sdkCtx, err := service.CreateClientCtx( - ctx.String(keyringDirFlag), - ctx.String(chainIdFlag), - ) - if err != nil { - return err - } - - krController, err := val.NewKeyringController( - sdkCtx, - ctx.String(keyNameFlag), - ctx.String(keyringBackendFlag), - ) - if err != nil { - return err - } - - commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) - if err != nil { - return err - } - - if krController.ValidatorKeyNameTaken() { - return fmt.Errorf("the key name %s is taken", krController.GetKeyName()) - } - - description, err := getDesciptionFromContext(ctx) - if err != nil { - return err - } - - btcPk, bbnPk, err := krController.CreateValidatorKeys() - if err != nil { - return err - } - - pop, err := krController.CreatePop() - if err != nil { - return err - } - - validator := val.NewStoreValidator(bbnPk, btcPk, krController.GetKeyName(), pop, &description, &commissionRate) - - vs, err := getValStoreFromCtx(ctx) - if err != nil { - return err - } - defer func() { - err = vs.Close() - }() - - if err := vs.SaveValidator(validator); err != nil { - return err - } - - printRespJSON(&proto.CreateValidatorResponse{ - BabylonPk: hex.EncodeToString(validator.BabylonPk), - BtcPk: hex.EncodeToString(validator.BtcPk), - }) - - return err -} - -var listValCmd = cli.Command{ - Name: "list-validators", - ShortName: "ls", - Usage: "List validators stored in the database.", - Action: lsVal, -} - -func lsVal(ctx *cli.Context) error { - vs, err := getValStoreFromCtx(ctx) - if err != nil { - return err - } - defer func() { - err = vs.Close() - }() - - valList, err := vs.ListValidators() - if err != nil { - return err - } - - valsInfo := make([]*proto.ValidatorInfo, len(valList)) - for i, v := range valList { - valInfo := proto.NewValidatorInfo(v) - valsInfo[i] = valInfo - } - - printRespJSON(&proto.QueryValidatorListResponse{Validators: valsInfo}) - - return nil -} - -var importValCmd = cli.Command{ - Name: "import-validator", - ShortName: "iv", - Usage: "Import a Bitcoin validator object with given Bitcoin and Babylon addresses.", - Flags: []cli.Flag{ - // TODO: add flags - }, - Action: importVal, -} - -func importVal(ctx *cli.Context) error { - panic("implement me") -} - -func getValStoreFromCtx(ctx *cli.Context) (*val.ValidatorStore, error) { - dbcfg, err := valcfg.NewDatabaseConfig( - ctx.GlobalString(dbTypeFlag), - ctx.GlobalString(dbPathFlag), - ctx.GlobalString(dbNameFlag), - ) - if err != nil { - return nil, fmt.Errorf("invalid DB config: %w", err) - } - - valStore, err := val.NewValidatorStore(dbcfg) - if err != nil { - return nil, fmt.Errorf("failed to open the store: %w", err) - } - - return valStore, nil -} diff --git a/cmd/vald/main.go b/cmd/vald/main.go index 48afde5b..a2366ce6 100644 --- a/cmd/vald/main.go +++ b/cmd/vald/main.go @@ -7,7 +7,6 @@ import ( "github.com/jessevdk/go-flags" "github.com/lightningnetwork/lnd/signal" - "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/valcfg" ) @@ -33,13 +32,7 @@ func main() { os.Exit(0) } - cc, err := clientcontroller.NewClientController(cfg, cfgLogger) - if err != nil { - cfgLogger.Errorf("failed to create rpc client for the consumer chain %s: %v", cfg.ChainName, err) - os.Exit(1) - } - - valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger, cc) + valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger) if err != nil { cfgLogger.Errorf("failed to create validator app: %v", err) os.Exit(1) diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go new file mode 100644 index 00000000..3760ff11 --- /dev/null +++ b/eotsmanager/config/config.go @@ -0,0 +1,55 @@ +package config + +import "fmt" + +const ( + TypeLocal = "local" + + DefaultDBBackend = "bbolt" + DefaultDBPath = "bbolt-eots.db" + DefaultDBName = "eots-default" + DefaultKeyringBackend = "test" + DefaultMode = TypeLocal +) + +type Config struct { + Mode string `long:"mode" description:"Indicates in which mode the EOTS manager is running"` + DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` + DBPath string `long:"dbpath" description:"The path that stores the database file"` + DBName string `long:"dbname" description:"The name of the database"` + KeyDirectory string `long:"key-dir" description:"Directory to store keys in"` + KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` +} + +func NewConfig(mode, backend, path, name, keyDir, keyringBackend string) (*Config, error) { + if backend != DefaultDBBackend { + return nil, fmt.Errorf("unsupported DB backend") + } + + if path == "" { + return nil, fmt.Errorf("DB path should not be empty") + } + + if name == "" { + return nil, fmt.Errorf("bucket name should not be empty") + } + + return &Config{ + Mode: mode, + KeyDirectory: keyDir, + DBBackend: backend, + DBPath: path, + DBName: name, + KeyringBackend: keyringBackend, + }, nil +} + +func DefaultEOTSManagerConfig() Config { + return Config{ + DBBackend: DefaultDBBackend, + DBPath: DefaultDBPath, + DBName: DefaultDBName, + KeyringBackend: DefaultKeyringBackend, + Mode: DefaultMode, + } +} diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index 21362735..c1ade9c2 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -1,15 +1,25 @@ package eotsmanager import ( + "fmt" + "os" + "path" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/cosmos/cosmos-sdk/client" + + "github.com/babylonchain/btc-validator/codec" + "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/eotsmanager/local" + "github.com/babylonchain/btc-validator/eotsmanager/types" ) type EOTSManager interface { - // CreateValidator generates a key pair to create a unique validator object - // and persists it in storage. The key pair is formatted by BIP-340 (Schnorr Signatures) + // CreateKey generates a key pair at the given name and persists it in storage. + // The key pair is formatted by BIP-340 (Schnorr Signatures) // It fails if there is an existing key Info with the same name or public key. - CreateValidator(name, passPhrase string) ([]byte, error) + CreateKey(name, passPhrase string) ([]byte, error) // CreateRandomnessPairList generates and persists a list of Schnorr randomness pairs from // startHeight to startHeight+(num-1)*step where step means the gap between each block height @@ -23,6 +33,10 @@ type EOTSManager interface { // It fails if there's randomness existed at a given height CreateRandomnessPairListWithExistenceCheck(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) + // KeyRecord returns the validator record + // It fails if the validator does not exist or passPhrase is incorrect + KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) + // SignEOTS signs an EOTS using the private key of the validator and the corresponding // secret randomness of the give chain at the given height // It fails if the validator does not exist or there's no randomness committed to the given height @@ -34,3 +48,25 @@ type EOTSManager interface { Close() error } + +func NewEOTSManager(cfg *config.Config) (EOTSManager, error) { + switch cfg.Mode { + case config.TypeLocal: + keyringDir := cfg.KeyDirectory + if keyringDir == "" { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, err + } + keyringDir = path.Join(homeDir, ".btc-validator") + } + + sdkCtx := client.Context{}. + WithCodec(codec.MakeCodec()). + WithKeyringDir(keyringDir) + + return local.NewLocalEOTSManager(sdkCtx, cfg) + default: + return nil, fmt.Errorf("unsupported EOTS manager mode") + } +} diff --git a/eotsmanager/local/eotsstore.go b/eotsmanager/local/eotsstore.go index 8afe0356..574e0450 100644 --- a/eotsmanager/local/eotsstore.go +++ b/eotsmanager/local/eotsstore.go @@ -6,10 +6,10 @@ import ( sdktypes "github.com/cosmos/cosmos-sdk/types" gproto "google.golang.org/protobuf/proto" - "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/valcfg" ) const ( @@ -21,7 +21,7 @@ type EOTSStore struct { s store.Store } -func NewEOTSStore(cfg *valcfg.EOTSManagerConfig) (*EOTSStore, error) { +func NewEOTSStore(cfg *config.Config) (*EOTSStore, error) { s, err := openStore(cfg) if err != nil { return nil, err @@ -46,7 +46,7 @@ func (es *EOTSStore) saveValidatorKey(pk []byte, keyName string) error { return nil } if exists { - return eotsmanager.ErrValidatorAlreadyExisted + return types.ErrValidatorAlreadyExisted } return es.s.Put(k, []byte(keyName)) @@ -108,7 +108,7 @@ func getValidatorKeyNameKey(pk []byte) []byte { return append([]byte(validatorKeyNamePrefix), pk...) } -func openStore(dbcfg *valcfg.EOTSManagerConfig) (store.Store, error) { +func openStore(dbcfg *config.Config) (store.Store, error) { switch dbcfg.DBBackend { case "bbolt": return store.NewBboltStore(dbcfg.DBPath, dbcfg.DBName) diff --git a/eotsmanager/local/localmanager.go b/eotsmanager/local/localmanager.go index ca27685a..419da5cc 100644 --- a/eotsmanager/local/localmanager.go +++ b/eotsmanager/local/localmanager.go @@ -14,9 +14,9 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" - "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" + eotstypes "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" ) const ( @@ -29,15 +29,15 @@ type LocalEOTSManager struct { es *EOTSStore } -func NewLocalEOTSManager(ctx client.Context, keyringBackend string, eotsCfg *valcfg.EOTSManagerConfig) (*LocalEOTSManager, error) { - if keyringBackend == "" { +func NewLocalEOTSManager(ctx client.Context, eotsCfg *config.Config) (*LocalEOTSManager, error) { + if eotsCfg.KeyringBackend == "" { return nil, fmt.Errorf("the keyring backend should not be empty") } kr, err := keyring.New( ctx.ChainID, // TODO currently only support test backend - keyringBackend, + eotsCfg.KeyringBackend, ctx.KeyringDir, ctx.Input, ctx.Codec, @@ -57,9 +57,9 @@ func NewLocalEOTSManager(ctx client.Context, keyringBackend string, eotsCfg *val }, nil } -func (lm *LocalEOTSManager) CreateValidator(name, passPhrase string) ([]byte, error) { +func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { if lm.keyExists(name) { - return nil, eotsmanager.ErrValidatorAlreadyExisted + return nil, eotstypes.ErrValidatorAlreadyExisted } keyringAlgos, _ := lm.kr.SupportedAlgorithms() @@ -118,7 +118,7 @@ func (lm *LocalEOTSManager) CreateRandomnessPairListWithExistenceCheck(valPk []b return nil, err } if exists { - return nil, eotsmanager.ErrSchnorrRandomnessALreadyCreated + return nil, eotstypes.ErrSchnorrRandomnessAlreadyCreated } } @@ -199,8 +199,21 @@ func (lm *LocalEOTSManager) getPrivRandomness(valPk []byte, chainID []byte, heig return privRand, nil } -func (lm *LocalEOTSManager) GetValidatorKeyName(valPk []byte) (string, error) { - return lm.es.getValidatorKeyName(valPk) +// TODO: we ignore passPhrase in local implementation for now +func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passPhrase string) (*eotstypes.KeyRecord, error) { + name, err := lm.es.getValidatorKeyName(valPk) + if err != nil { + return nil, err + } + privKey, err := lm.getEOTSPrivKey(valPk) + if err != nil { + return nil, err + } + + return &eotstypes.KeyRecord{ + Name: name, + PrivKey: privKey, + }, nil } func (lm *LocalEOTSManager) getEOTSPrivKey(valPk []byte) (*btcec.PrivateKey, error) { diff --git a/eotsmanager/local/localmanager_test.go b/eotsmanager/local/localmanager_test.go index ffff08a2..74ec0165 100644 --- a/eotsmanager/local/localmanager_test.go +++ b/eotsmanager/local/localmanager_test.go @@ -8,8 +8,8 @@ import ( "github.com/babylonchain/babylon/testutil/datagen" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/local" + "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/testutil" ) @@ -29,22 +29,22 @@ func FuzzCreateValidator(f *testing.F) { require.NoError(t, err) }() - lm, err := local.NewLocalEOTSManager(sdkCtx, "test", eotsCfg) + lm, err := local.NewLocalEOTSManager(sdkCtx, eotsCfg) require.NoError(t, err) - valPk, err := lm.CreateValidator(valName, "") + valPk, err := lm.CreateKey(valName, "") require.NoError(t, err) - storedKeyName, err := lm.GetValidatorKeyName(valPk) + valRecord, err := lm.KeyRecord(valPk, "") require.NoError(t, err) - require.Equal(t, valName, storedKeyName) + require.Equal(t, valName, valRecord.Name) sig, err := lm.SignSchnorrSig(valPk, datagen.GenRandomByteArray(r, 32)) require.NoError(t, err) require.NotNil(t, sig) - _, err = lm.CreateValidator(valName, "") - require.ErrorIs(t, err, eotsmanager.ErrValidatorAlreadyExisted) + _, err = lm.CreateKey(valName, "") + require.ErrorIs(t, err, types.ErrValidatorAlreadyExisted) }) } @@ -63,10 +63,10 @@ func FuzzCreateRandomnessPairList(f *testing.F) { require.NoError(t, err) }() - lm, err := local.NewLocalEOTSManager(sdkCtx, "test", eotsCfg) + lm, err := local.NewLocalEOTSManager(sdkCtx, eotsCfg) require.NoError(t, err) - valPk, err := lm.CreateValidator(valName, "") + valPk, err := lm.CreateKey(valName, "") require.NoError(t, err) chainID := datagen.GenRandomByteArray(r, 10) diff --git a/eotsmanager/types/errors.go b/eotsmanager/types/errors.go new file mode 100644 index 00000000..12176765 --- /dev/null +++ b/eotsmanager/types/errors.go @@ -0,0 +1,8 @@ +package types + +import "errors" + +var ( + ErrValidatorAlreadyExisted = errors.New("the validator has already existed") + ErrSchnorrRandomnessAlreadyCreated = errors.New("the Schnorr randomness has already been created") +) diff --git a/eotsmanager/types/val_record.go b/eotsmanager/types/val_record.go new file mode 100644 index 00000000..44a0c77c --- /dev/null +++ b/eotsmanager/types/val_record.go @@ -0,0 +1,8 @@ +package types + +import "github.com/btcsuite/btcd/btcec/v2" + +type KeyRecord struct { + Name string + PrivKey *btcec.PrivateKey +} diff --git a/go.mod b/go.mod index afddf9d5..a7836e3d 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/relayer/v2 v2.4.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 github.com/jessevdk/go-flags v1.5.0 @@ -95,7 +96,6 @@ require ( github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/decred/dcrd/lru v1.0.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index e7caaef9..573059cf 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/babylonchain/babylon/types" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/service" @@ -39,14 +40,16 @@ type babylonNode struct { pidFile string dataDir string juryKeyName string + chainID string slashingAddr string } -func newBabylonNode(dataDir string, cmd *exec.Cmd, juryKeyName, slashingAddr string) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd, juryKeyName, chainID string, slashingAddr string) *babylonNode { return &babylonNode{ dataDir: dataDir, cmd: cmd, juryKeyName: juryKeyName, + chainID: chainID, slashingAddr: slashingAddr, } } @@ -145,13 +148,16 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { ) require.NoError(t, err) juryKeyName := "jury-key" - krController, err := val.NewKeyringController( + krController, err := val.NewChainKeyringController( sdkCtx, juryKeyName, + chainID, "test", ) require.NoError(t, err) - juryPk, err := krController.CreateJuryKey() + sdkJuryPk, err := krController.CreateChainKey() + require.NoError(t, err) + juryPk, err := secp256k1.ParsePubKey(sdkJuryPk.Key) require.NoError(t, err) juryPkBip340 := types.NewBIP340PubKeyFromBTCPK(juryPk) @@ -192,7 +198,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, juryKeyName, slashingAddr), + babylonNode: newBabylonNode(testDir, startCmd, juryKeyName, chainID, slashingAddr), } } @@ -219,7 +225,7 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { } func (w *BabylonNodeHandler) GetJuryKeyName() string { - return w.babylonNode.juryKeyName + return val.GetKeyName(w.babylonNode.chainID, w.babylonNode.juryKeyName) } func (w *BabylonNodeHandler) GetSlashingAddress() string { diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 10251ae3..f4979658 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -11,16 +11,12 @@ import ( "github.com/babylonchain/babylon/testutil/datagen" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -216,28 +212,12 @@ func TestDoubleSigning(t *testing.T) { _, extractedKey, err := valIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) require.NotNil(t, extractedKey) - localKey, err := getBtcPrivKey(app.GetKeyring(), val.KeyName(valIns.GetStoreValidator().KeyName)) - require.NoError(t, err) + localKey := tm.GetValPrivKey(t, valIns.GetBtcPkBIP340().MustMarshal()) require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) t.Logf("the equivocation attack is successful") } -func getBtcPrivKey(kr keyring.Keyring, keyName val.KeyName) (*btcec.PrivateKey, error) { - k, err := kr.Key(keyName.GetBtcKeyName()) - if err != nil { - return nil, err - } - localKey := k.GetLocal().PrivKey.GetCachedValue() - switch v := localKey.(type) { - case *secp256k1.PrivKey: - privKey, _ := btcec.PrivKeyFromBytes(v.Key) - return privKey, nil - default: - return nil, err - } -} - // TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync func TestFastSync(t *testing.T) { tm := StartManagerWithValidator(t, 1, false) diff --git a/itest/test_manager.go b/itest/test_manager.go index 497f4c64..83e993e7 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" @@ -45,6 +46,7 @@ type TestManager struct { BabylonHandler *BabylonNodeHandler Config *valcfg.Config Va *service.ValidatorApp + Em eotsmanager.EOTSManager BabylonClient *clientcontroller.BabylonController } @@ -82,7 +84,13 @@ func StartManager(t *testing.T, isJury bool) *TestManager { bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) - valApp, err := service.NewValidatorAppFromConfig(cfg, logger, bc) + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(cfg) + require.NoError(t, err) + + em, err := eotsmanager.NewEOTSManager(eotsCfg) + require.NoError(t, err) + + valApp, err := service.NewValidatorApp(cfg, bc, em, logger) require.NoError(t, err) err = valApp.Start() @@ -92,6 +100,7 @@ func StartManager(t *testing.T, isJury bool) *TestManager { BabylonHandler: bh, Config: cfg, Va: valApp, + Em: em, BabylonClient: bc, } @@ -116,18 +125,19 @@ func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { var ( valNamePrefix = "test-val-" monikerPrefix = "moniker-" + chainID = "chain-test" ) for i := 0; i < n; i++ { valName := valNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) commission := sdktypes.OneDec() - _, err := app.CreateValidator(valName, newDescription(moniker), &commission) + res, err := app.CreateValidator(valName, chainID, "", newDescription(moniker), &commission) require.NoError(t, err) - _, bbnPk, err := app.RegisterValidator(valName) + _, err = app.RegisterValidator(res.ValPk.MarshalHex()) require.NoError(t, err) - err = app.StartHandlingValidator(bbnPk) + err = app.StartHandlingValidator(res.ValPk) require.NoError(t, err) - valIns, err := app.GetValidatorInstance(bbnPk) + valIns, err := app.GetValidatorInstance(res.ValPk) require.NoError(t, err) require.True(t, valIns.IsRunning()) require.NoError(t, err) @@ -189,11 +199,7 @@ func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKe func (tm *TestManager) WaitForValPubRandCommitted(t *testing.T, valIns *service.ValidatorInstance) { require.Eventually(t, func() bool { - randPairs, err := valIns.GetCommittedPubRandPairList() - if err != nil { - return false - } - return int(tm.Config.NumPubRand) == len(randPairs) + return valIns.GetLastCommittedHeight() > 0 }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("public randomness is successfully committed") @@ -288,9 +294,9 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo return blocks } -func (tm *TestManager) WaitForValStopped(t *testing.T, bbnPk *secp256k1.PubKey) { +func (tm *TestManager) WaitForValStopped(t *testing.T, valPk *bbntypes.BIP340PubKey) { require.Eventually(t, func() bool { - _, err := tm.Va.GetValidatorInstance(bbnPk) + _, err := tm.Va.GetValidatorInstance(valPk) return err != nil }, eventuallyWaitTimeOut, eventuallyPollTime) } @@ -382,6 +388,12 @@ func (tm *TestManager) GetJuryPrivKey(t *testing.T) *btcec.PrivateKey { return juryPrivKey } +func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { + record, err := tm.Em.KeyRecord(valPk, "") + require.NoError(t, err) + return record.PrivKey +} + func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData { r := rand.New(rand.NewSource(time.Now().UnixNano())) @@ -391,7 +403,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK require.NoError(t, err) require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - juryPk, err := tm.Va.GetJuryPk() + juryPk := tm.GetJuryPrivKey(t).PubKey() require.NoError(t, err) require.Equal(t, params.JuryPk.SerializeCompressed()[1:], juryPk.SerializeCompressed()[1:]) diff --git a/proto/validators.pb.go b/proto/validators.pb.go index ba2522ef..d00ecf48 100644 --- a/proto/validators.pb.go +++ b/proto/validators.pb.go @@ -191,11 +191,15 @@ type CreateValidatorRequest struct { // key_name is the identifier key in keyring KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // pass_phrase is used to encrypt the keys + PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` + // chain_id is the identifier of the consumer chain that the validator connected to + ChainId string `protobuf:"bytes,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Description *types.Description `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the validator // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - Commission string `protobuf:"bytes,3,opt,name=commission,proto3" json:"commission,omitempty"` + Commission string `protobuf:"bytes,5,opt,name=commission,proto3" json:"commission,omitempty"` } func (x *CreateValidatorRequest) Reset() { @@ -237,6 +241,20 @@ func (x *CreateValidatorRequest) GetKeyName() string { return "" } +func (x *CreateValidatorRequest) GetPassPhrase() string { + if x != nil { + return x.PassPhrase + } + return "" +} + +func (x *CreateValidatorRequest) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + func (x *CreateValidatorRequest) GetDescription() *types.Description { if x != nil { return x.Description @@ -256,10 +274,8 @@ type CreateValidatorResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk string `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - BtcPk string `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` + // btc_pk is the hex string of BTC secp256k1 public key of the validator encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` } func (x *CreateValidatorResponse) Reset() { @@ -294,13 +310,6 @@ func (*CreateValidatorResponse) Descriptor() ([]byte, []int) { return file_validators_proto_rawDescGZIP(), []int{3} } -func (x *CreateValidatorResponse) GetBabylonPk() string { - if x != nil { - return x.BabylonPk - } - return "" -} - func (x *CreateValidatorResponse) GetBtcPk() string { if x != nil { return x.BtcPk @@ -313,8 +322,8 @@ type RegisterValidatorRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // the key name of the BTC validator - KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` } func (x *RegisterValidatorRequest) Reset() { @@ -349,9 +358,9 @@ func (*RegisterValidatorRequest) Descriptor() ([]byte, []int) { return file_validators_proto_rawDescGZIP(), []int{4} } -func (x *RegisterValidatorRequest) GetKeyName() string { +func (x *RegisterValidatorRequest) GetBtcPk() string { if x != nil { - return x.KeyName + return x.BtcPk } return "" } @@ -409,8 +418,8 @@ type AddFinalitySignatureRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` + // btc_pk is hex string of the BTC secp256k1 public key of the validator 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 uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` // last_commit_hash is the last commit hash of the Babylon block @@ -449,11 +458,11 @@ func (*AddFinalitySignatureRequest) Descriptor() ([]byte, []int) { return file_validators_proto_rawDescGZIP(), []int{6} } -func (x *AddFinalitySignatureRequest) GetBabylonPk() []byte { +func (x *AddFinalitySignatureRequest) GetBtcPk() string { if x != nil { - return x.BabylonPk + return x.BtcPk } - return nil + return "" } func (x *AddFinalitySignatureRequest) GetHeight() uint64 { @@ -541,8 +550,8 @@ type QueryValidatorRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` + // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` } func (x *QueryValidatorRequest) Reset() { @@ -577,11 +586,11 @@ func (*QueryValidatorRequest) Descriptor() ([]byte, []int) { return file_validators_proto_rawDescGZIP(), []int{8} } -func (x *QueryValidatorRequest) GetBabylonPk() []byte { +func (x *QueryValidatorRequest) GetBtcPk() string { if x != nil { - return x.BabylonPk + return x.BtcPk } - return nil + return "" } type QueryValidatorResponse struct { @@ -734,16 +743,18 @@ type StoreValidator struct { Pop *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,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"` + // chain_id is the identifier of the consumer chain that the validator 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,7,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` + LastVotedHeight uint64 `protobuf:"varint,8,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` // last_committed_height defines the height of the last Babylon block // to which the validator committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,8,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` + LastCommittedHeight uint64 `protobuf:"varint,9,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_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,10,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` // status defines the current validator status - Status ValidatorStatus `protobuf:"varint,10,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` + Status ValidatorStatus `protobuf:"varint,11,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` } func (x *StoreValidator) Reset() { @@ -820,6 +831,13 @@ func (x *StoreValidator) GetKeyName() string { return "" } +func (x *StoreValidator) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + func (x *StoreValidator) GetLastVotedHeight() uint64 { if x != nil { return x.LastVotedHeight @@ -1083,174 +1101,177 @@ var file_validators_proto_rawDesc = []byte{ 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xd4, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x90, 0x02, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, - 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, + 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, + 0x50, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, + 0x64, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, + 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, + 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, + 0x74, 0x63, 0x50, 0x6b, 0x22, 0x31, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x76, 0x0a, + 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, + 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, + 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, + 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x53, + 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, + 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, + 0x0a, 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, 0x2e, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, + 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, + 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 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, 0x32, 0x0a, + 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 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, 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, + 0x42, 0x74, 0x63, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 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, 0x09, - 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x35, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x34, - 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, - 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, - 0x48, 0x61, 0x73, 0x68, 0x22, 0x7e, 0x0a, 0x1b, 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, 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, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, - 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, - 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x36, 0x0a, 0x15, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 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, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, - 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x22, 0xf2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, - 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 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, 0x32, - 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, - 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, - 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 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, + 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, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, - 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, - 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x4d, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x59, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, + 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, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/proto/validators.proto b/proto/validators.proto index ae79fb41..f461b2e7 100644 --- a/proto/validators.proto +++ b/proto/validators.proto @@ -43,26 +43,28 @@ message GetInfoResponse { message CreateValidatorRequest { // key_name is the identifier key in keyring string key_name = 1; + // pass_phrase is used to encrypt the keys + string pass_phrase = 2; + // chain_id is the identifier of the consumer chain that the validator connected to + string chain_id = 3; // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 2; + cosmos.staking.v1beta1.Description description = 4; // commission defines the commission rate for the validator // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 3 [ + string commission = 5 [ (cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" ]; } message CreateValidatorResponse { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - string babylon_pk = 1; - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - string btc_pk = 2; + // btc_pk is the hex string of BTC secp256k1 public key of the validator encoded in BIP-340 spec + string btc_pk = 1; } message RegisterValidatorRequest { - // the key name of the BTC validator - string key_name = 1; + // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + string btc_pk = 1; } message RegisterValidatorResponse { @@ -71,8 +73,8 @@ message RegisterValidatorResponse { } message AddFinalitySignatureRequest { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - bytes babylon_pk = 1; + // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + string btc_pk = 1; // height is the height of the Babylon block uint64 height = 2; // last_commit_hash is the last commit hash of the Babylon block @@ -89,8 +91,8 @@ message AddFinalitySignatureResponse { } message QueryValidatorRequest { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - bytes babylon_pk = 1; + // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + string btc_pk = 1; } message QueryValidatorResponse { @@ -123,16 +125,18 @@ message StoreValidator { ProofOfPossession pop = 5; // key_name is the identifier of the keyring string key_name = 6; + // chain_id is the identifier of the consumer chain that the validator connected to + string chain_id = 7; // last_voted_height defines the height of the last voted Babylon block - uint64 last_voted_height = 7; + uint64 last_voted_height = 8; // last_committed_height defines the height of the last Babylon block // to which the validator committed a randomness pair - uint64 last_committed_height = 8; + uint64 last_committed_height = 9; // 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 = 10; // status defines the current validator status - ValidatorStatus status = 10; + ValidatorStatus status = 11; } // ValidatorInfo is the basic information of a validator mainly for external usage diff --git a/service/app.go b/service/app.go index a9e7599c..a5b66c3e 100644 --- a/service/app.go +++ b/service/app.go @@ -9,12 +9,12 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/valcfg" @@ -41,6 +41,7 @@ type ValidatorApp struct { logger *logrus.Logger validatorManager *ValidatorManager + eotsManager eotsmanager.EOTSManager createValidatorRequestChan chan *createValidatorRequest registerValidatorRequestChan chan *registerValidatorRequest @@ -50,9 +51,30 @@ type ValidatorApp struct { func NewValidatorAppFromConfig( config *valcfg.Config, logger *logrus.Logger, - cc clientcontroller.ClientController, ) (*ValidatorApp, error) { + cc, err := clientcontroller.NewClientController(config, logger) + if err != nil { + return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) + } + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(config) + if err != nil { + return nil, err + } + em, err := eotsmanager.NewEOTSManager(eotsCfg) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager: %w", err) + } + + return NewValidatorApp(config, cc, em, logger) +} + +func NewValidatorApp( + config *valcfg.Config, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + logger *logrus.Logger, +) (*ValidatorApp, error) { kr, err := CreateKeyring(config.BabylonConfig.KeyDirectory, config.BabylonConfig.ChainID, config.BabylonConfig.KeyringBackend) @@ -66,13 +88,17 @@ func NewValidatorAppFromConfig( } if config.JuryMode { - if _, err := kr.Key(config.JuryModeConfig.JuryKeyName); err != nil { + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.JuryModeConfig.JuryKeyName, config.BabylonConfig.ChainID) + if err != nil { + return nil, err + } + if _, err := kc.GetChainPrivKey(); err != nil { return nil, fmt.Errorf("the program is running in Jury mode but the Jury key %s is not found: %w", config.JuryModeConfig.JuryKeyName, err) } } - vm, err := NewValidatorManager(valStore, config, kr, cc, logger) + vm, err := NewValidatorManager(valStore, config, cc, em, logger) if err != nil { return nil, fmt.Errorf("failed to create validator manager: %w", err) } @@ -84,6 +110,7 @@ func NewValidatorAppFromConfig( config: config, logger: logger, validatorManager: vm, + eotsManager: em, quit: make(chan struct{}), sentQuit: make(chan struct{}), eventQuit: make(chan struct{}), @@ -105,47 +132,33 @@ func (app *ValidatorApp) GetKeyring() keyring.Keyring { return app.kr } -func (app *ValidatorApp) GetJuryPk() (*btcec.PublicKey, error) { - juryPrivKey, err := app.getJuryPrivKey() - if err != nil { - return nil, err - } - return juryPrivKey.PubKey(), nil -} - func (app *ValidatorApp) ListValidatorInstances() []*ValidatorInstance { return app.validatorManager.ListValidatorInstances() } // GetValidatorInstance returns the validator instance with the given Babylon public key -func (app *ValidatorApp) GetValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { - return app.validatorManager.GetValidatorInstance(babylonPk) +func (app *ValidatorApp) GetValidatorInstance(valPk *bbntypes.BIP340PubKey) (*ValidatorInstance, error) { + return app.validatorManager.GetValidatorInstance(valPk) } -func (app *ValidatorApp) RegisterValidator(keyName string) (*RegisterValidatorResponse, *secp256k1.PubKey, error) { - kc, err := val.NewKeyringControllerWithKeyring(app.kr, keyName) +func (app *ValidatorApp) RegisterValidator(valPkStr string) (*RegisterValidatorResponse, error) { + valPk, err := bbntypes.NewBIP340PubKeyFromHex(valPkStr) if err != nil { - return nil, nil, err - } - if !kc.ValidatorKeyExists() { - return nil, nil, fmt.Errorf("key name %s does not exist", keyName) - } - babylonPublicKeyBytes, err := kc.GetBabylonPublicKeyBytes() - if err != nil { - return nil, nil, err + return nil, err } - validator, err := app.vs.GetStoreValidator(babylonPublicKeyBytes) + + validator, err := app.vs.GetStoreValidator(valPk.MustMarshal()) if err != nil { - return nil, nil, err + return nil, err } if validator.Status != proto.ValidatorStatus_CREATED { - return nil, nil, fmt.Errorf("validator is already registered") + return nil, fmt.Errorf("validator is already registered") } btcSig, err := bbntypes.NewBIP340Signature(validator.Pop.BtcSig) if err != nil { - return nil, nil, err + return nil, err } pop := &bstypes.ProofOfPossession{ @@ -156,7 +169,7 @@ func (app *ValidatorApp) RegisterValidator(keyName string) (*RegisterValidatorRe commissionRate, err := math.LegacyNewDecFromStr(validator.Commission) if err != nil { - return nil, nil, err + return nil, err } request := ®isterValidatorRequest{ @@ -173,18 +186,18 @@ func (app *ValidatorApp) RegisterValidator(keyName string) (*RegisterValidatorRe select { case err := <-request.errResponse: - return nil, nil, err + return nil, err case successResponse := <-request.successResponse: - return successResponse, validator.GetBabylonPK(), nil + return successResponse, nil case <-app.quit: - return nil, nil, fmt.Errorf("validator app is shutting down") + return nil, fmt.Errorf("validator app is shutting down") } } // StartHandlingValidator starts a validator instance with the given Babylon public key // Note: this should be called right after the validator is registered -func (app *ValidatorApp) StartHandlingValidator(bbnPk *secp256k1.PubKey) error { - return app.validatorManager.addValidatorInstance(bbnPk) +func (app *ValidatorApp) StartHandlingValidator(valPk *bbntypes.BIP340PubKey) error { + return app.validatorManager.addValidatorInstance(valPk) } func (app *ValidatorApp) StartHandlingValidators() error { @@ -348,26 +361,28 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio } func (app *ValidatorApp) getJuryPrivKey() (*btcec.PrivateKey, error) { - return app.getPrivKey(app.config.JuryModeConfig.JuryKeyName) -} + kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.JuryModeConfig.JuryKeyName, app.config.BabylonConfig.ChainID) + if err != nil { + return nil, err + } -func (app *ValidatorApp) getBtcPrivKey(name string) (*btcec.PrivateKey, error) { - return app.getPrivKey(val.KeyName(name).GetBtcKeyName()) + sdkPrivKey, err := kc.GetChainPrivKey() + if err != nil { + return nil, err + } + + privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) + + return privKey, nil } -func (app *ValidatorApp) getPrivKey(name string) (*btcec.PrivateKey, error) { - k, err := app.kr.Key(name) +func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) { + record, err := app.eotsManager.KeyRecord(valPk, "") if err != nil { - return nil, fmt.Errorf("failed to get key %s from the keyring: %w", name, err) - } - localKey := k.GetLocal().PrivKey.GetCachedValue() - switch v := localKey.(type) { - case *secp256k1.PrivKey: - privKey, _ := btcec.PrivKeyFromBytes(v.Key) - return privKey, nil - default: - return nil, fmt.Errorf("unsupported key type in keyring") + return nil, err } + + return record.PrivKey, nil } func (app *ValidatorApp) Start() error { @@ -379,7 +394,7 @@ func (app *ValidatorApp) Start() error { go app.eventLoop() app.sentWg.Add(1) - go app.handleSentToBabylonLoop() + go app.registrationLoop() if app.IsJury() { app.wg.Add(1) @@ -428,15 +443,23 @@ func (app *ValidatorApp) Stop() error { return } + app.logger.Debug("Stopping EOTS manager") + if err := app.eotsManager.Close(); err != nil { + stopErr = err + return + } + app.logger.Debug("ValidatorApp successfully stopped") }) return stopErr } -func (app *ValidatorApp) CreateValidator(keyName string, description *stakingtypes.Description, commission *sdktypes.Dec) (*CreateValidatorResult, error) { +func (app *ValidatorApp) CreateValidator(keyName, chainID, passPhrase string, description *stakingtypes.Description, commission *sdktypes.Dec) (*CreateValidatorResult, error) { req := &createValidatorRequest{ keyName: keyName, + chainID: chainID, + passPhrase: passPhrase, description: description, commission: commission, errResponse: make(chan error, 1), @@ -450,8 +473,7 @@ func (app *ValidatorApp) CreateValidator(keyName string, description *stakingtyp return nil, err case successResponse := <-req.successResponse: return &CreateValidatorResult{ - BtcValidatorPk: successResponse.BtcValidatorPk, - BabylonValidatorPk: successResponse.BabylonValidatorPk, + ValPk: successResponse.ValPk, }, nil case <-app.quit: return nil, fmt.Errorf("validator app is shutting down") @@ -463,44 +485,48 @@ func (app *ValidatorApp) IsJury() bool { } func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { + valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase) + if err != nil { + return nil, err + } - app.logger.Debug("handling CreateValidator request") - - kr, err := val.NewKeyringControllerWithKeyring(app.kr, req.keyName) + valPk, err := bbntypes.NewBIP340PubKey(valPkBytes) + if err != nil { + return nil, err + } + kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, req.chainID) if err != nil { - return nil, fmt.Errorf("failed to create keyring controller: %w", err) + return nil, err } - if kr.ValidatorKeyNameTaken() { - return nil, fmt.Errorf("the key name %s is taken", kr.GetKeyName()) + bbnPk, err := kr.CreateChainKey() + if err != nil { + return nil, fmt.Errorf("failed to create chain key for the validator: %w", err) } - // TODO should not expose direct proto here, as this is internal db representation - // connected to serialization - btcPk, bbnPk, err := kr.CreateValidatorKeys() + valRecord, err := app.eotsManager.KeyRecord(valPk.MustMarshal(), req.passPhrase) if err != nil { - return nil, fmt.Errorf("failed to create validator: %w", err) + return nil, fmt.Errorf("failed to get validator record: %w", err) } - pop, err := kr.CreatePop() + pop, err := kr.CreatePop(valRecord.PrivKey) if err != nil { return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) } - validator := val.NewStoreValidator(bbnPk, btcPk, kr.GetKeyName(), pop, req.description, req.commission) + validator := val.NewStoreValidator(bbnPk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) if err := app.vs.SaveValidator(validator); err != nil { return nil, fmt.Errorf("failed to save validator: %w", err) } app.logger.WithFields(logrus.Fields{ - "btc_pub_key": validator.MustGetBIP340BTCPK().MarshalHex(), - "babylon_pub_key": validator.GetBabylonPkHexString(), + "btc_pub_key": valPk.MarshalHex(), + "name": req.keyName, }).Debug("successfully created a validator") return &createValidatorResponse{ - BtcValidatorPk: *validator.MustGetBTCPK(), - BabylonValidatorPk: *validator.GetBabylonPK(), + ValPk: valPk, }, nil } diff --git a/service/app_test.go b/service/app_test.go index 411b0bcf..04c668b3 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -11,10 +11,12 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/relayer/v2/relayer/provider" + secp256k12 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" @@ -33,6 +35,10 @@ func FuzzRegisterValidator(f *testing.F) { defer func() { err := os.RemoveAll(cfg.DatabaseConfig.Path) require.NoError(t, err) + err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) + require.NoError(t, err) + err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) + require.NoError(t, err) }() randomStartingHeight := uint64(r.Int63n(100) + 1) cfg.ValidatorModeConfig.AutoChainScanningMode = false @@ -40,7 +46,11 @@ func FuzzRegisterValidator(f *testing.F) { currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, err := service.NewValidatorAppFromConfig(&cfg, logrus.New(), mockClientController) + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + require.NoError(t, err) + em, err := eotsmanager.NewEOTSManager(eotsCfg) + require.NoError(t, err) + app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) require.NoError(t, err) err = app.Start() @@ -71,14 +81,14 @@ func FuzzRegisterValidator(f *testing.F) { testutil.EmptyDescription(), ).Return(&provider.RelayerTxResponse{TxHash: txHash}, nil).AnyTimes() - res, _, err := app.RegisterValidator(validator.KeyName) + res, err := app.RegisterValidator(validator.MustGetBIP340BTCPK().MarshalHex()) require.NoError(t, err) require.Equal(t, txHash, res.TxHash) - err = app.StartHandlingValidator(validator.GetBabylonPK()) + err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK()) require.NoError(t, err) - valAfterReg, err := app.GetValidatorInstance(validator.GetBabylonPK()) + valAfterReg, err := app.GetValidatorInstance(validator.MustGetBIP340BTCPK()) require.NoError(t, err) require.Equal(t, valAfterReg.GetStoreValidator().Status, proto.ValidatorStatus_REGISTERED) }) @@ -96,6 +106,8 @@ func FuzzAddJurySig(f *testing.F) { defer func() { err := os.RemoveAll(cfg.DatabaseConfig.Path) require.NoError(t, err) + err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) + require.NoError(t, err) err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) require.NoError(t, err) }() @@ -103,20 +115,21 @@ func FuzzAddJurySig(f *testing.F) { finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) - app, err := service.NewValidatorAppFromConfig(&cfg, logrus.New(), mockClientController) + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + require.NoError(t, err) + em, err := eotsmanager.NewEOTSManager(eotsCfg) + require.NoError(t, err) + app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) require.NoError(t, err) - - // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app) - btcPkBIP340 := validator.MustGetBIP340BTCPK() - btcPk := validator.MustGetBTCPK() // create a Jury key pair in the keyring - juryKc, err := val.NewKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName) + juryKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName, cfg.BabylonConfig.ChainID) require.NoError(t, err) - jurPk, err := juryKc.CreateJuryKey() + sdkJurPk, err := juryKc.CreateChainKey() require.NoError(t, err) - require.NotNil(t, jurPk) + juryPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) + require.NoError(t, err) + require.NotNil(t, juryPk) cfg.JuryMode = true err = app.Start() @@ -126,6 +139,11 @@ func FuzzAddJurySig(f *testing.F) { require.NoError(t, err) }() + // create a validator object and save it to db + validator := testutil.GenStoredValidator(r, t, app) + btcPkBIP340 := validator.MustGetBIP340BTCPK() + btcPk := validator.MustGetBTCPK() + // generate BTC delegation slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) require.NoError(t, err) @@ -133,7 +151,7 @@ func FuzzAddJurySig(f *testing.F) { require.NoError(t, err) stakingTimeBlocks := uint16(5) stakingValue := int64(2 * 10e8) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, jurPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) + stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, juryPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) require.NoError(t, err) delBabylonSK, delBabylonPK, err := datagen.GenRandomSecp256k1KeyPair(r) require.NoError(t, err) diff --git a/service/client/rpcclient.go b/service/client/rpcclient.go index fa2b2777..e262bdda 100644 --- a/service/client/rpcclient.go +++ b/service/client/rpcclient.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + bbntypes "github.com/babylonchain/babylon/types" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "google.golang.org/grpc" @@ -41,8 +42,8 @@ func (c *ValidatorServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInf return res, nil } -func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, keyName string) (*proto.RegisterValidatorResponse, error) { - req := &proto.RegisterValidatorRequest{KeyName: keyName} +func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, valPk *bbntypes.BIP340PubKey) (*proto.RegisterValidatorResponse, error) { + req := &proto.RegisterValidatorRequest{BtcPk: valPk.MarshalHex()} res, err := c.client.RegisterValidator(ctx, req) if err != nil { return nil, err @@ -51,8 +52,8 @@ func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, keyN return res, nil } -func (c *ValidatorServiceGRpcClient) CreateValidator(ctx context.Context, keyName string, description *stakingtypes.Description, commission *sdktypes.Dec) (*proto.CreateValidatorResponse, error) { - req := &proto.CreateValidatorRequest{KeyName: keyName, Description: description, Commission: commission.String()} +func (c *ValidatorServiceGRpcClient) CreateValidator(ctx context.Context, keyName, chainID, passPhrase string, description *stakingtypes.Description, commission *sdktypes.Dec) (*proto.CreateValidatorResponse, error) { + req := &proto.CreateValidatorRequest{KeyName: keyName, ChainId: chainID, PassPhrase: passPhrase, Description: description, Commission: commission.String()} res, err := c.client.CreateValidator(ctx, req) if err != nil { return nil, err @@ -61,9 +62,9 @@ func (c *ValidatorServiceGRpcClient) CreateValidator(ctx context.Context, keyNam return res, nil } -func (c *ValidatorServiceGRpcClient) AddFinalitySignature(ctx context.Context, bbnPk []byte, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { +func (c *ValidatorServiceGRpcClient) AddFinalitySignature(ctx context.Context, valPk string, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { req := &proto.AddFinalitySignatureRequest{ - BabylonPk: bbnPk, + BtcPk: valPk, Height: height, LastCommitHash: lch, } @@ -86,8 +87,8 @@ func (c *ValidatorServiceGRpcClient) QueryValidatorList(ctx context.Context) (*p return res, nil } -func (c *ValidatorServiceGRpcClient) QueryValidatorInfo(ctx context.Context, bbnPk []byte) (*proto.QueryValidatorResponse, error) { - req := &proto.QueryValidatorRequest{BabylonPk: bbnPk} +func (c *ValidatorServiceGRpcClient) QueryValidatorInfo(ctx context.Context, valPk *bbntypes.BIP340PubKey) (*proto.QueryValidatorResponse, error) { + req := &proto.QueryValidatorRequest{BtcPk: valPk.MarshalHex()} res, err := c.client.QueryValidator(ctx, req) if err != nil { return nil, err diff --git a/service/event_loop.go b/service/event_loop.go index afd0e7ba..3b53b9a6 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -79,22 +79,22 @@ func (app *ValidatorApp) eventLoop() { for { select { case req := <-app.createValidatorRequestChan: - resp, err := app.handleCreateValidatorRequest(req) - + res, err := app.handleCreateValidatorRequest(req) if err != nil { req.errResponse <- err continue } - req.successResponse <- resp + req.successResponse <- &createValidatorResponse{ValPk: res.ValPk} case ev := <-app.validatorRegisteredEventChan: - valStored, err := app.vs.GetStoreValidator(ev.bbnPubKey.Key) + valStored, err := app.vs.GetStoreValidator(ev.btcPubKey.MustMarshal()) if err != nil { // we always check if the validator is in the DB before sending the registration request app.logger.WithFields(logrus.Fields{ - "bbn_pk": ev.bbnPubKey, + "btc_pk": ev.btcPubKey.MarshalHex(), + "babylon_pk": hex.EncodeToString(ev.bbnPubKey.Key), }).Fatal("registered validator not found in DB") } @@ -119,13 +119,7 @@ func (app *ValidatorApp) eventLoop() { } } -// Loop for handling requests to send stuff to babylon. It is necessart to properly -// serialize bayblon sends as otherwise we would keep hitting sequence mismatch errors. -// This could be done either by send loop or by lock. We choose send loop as it is -// more flexible. -// TODO: This could be probably separate component responsible for queuing stuff -// and sending it to babylon. -func (app *ValidatorApp) handleSentToBabylonLoop() { +func (app *ValidatorApp) registrationLoop() { defer app.sentWg.Done() for { select { @@ -137,21 +131,22 @@ func (app *ValidatorApp) handleSentToBabylonLoop() { if err != nil { app.logger.WithFields(logrus.Fields{ - "err": err, - "bbnPubKey": hex.EncodeToString(req.bbnPubKey.Key), - "btcPubKey": req.btcPubKey.MarshalHex(), + "err": err, + "btc_pk": req.btcPubKey.MarshalHex(), + "babylon_pk": hex.EncodeToString(req.bbnPubKey.Key), }).Error("failed to register validator") req.errResponse <- err continue } app.logger.WithFields(logrus.Fields{ - "bbnPk": hex.EncodeToString(req.bbnPubKey.Key), - "btcPubKey": req.btcPubKey.MarshalHex(), - "txHash": res.TxHash, + "btc_pk": req.btcPubKey.MarshalHex(), + "babylon_pk": hex.EncodeToString(req.bbnPubKey.Key), + "txHash": res.TxHash, }).Info("successfully registered validator on babylon") app.validatorRegisteredEventChan <- &validatorRegisteredEvent{ + btcPubKey: req.btcPubKey, bbnPubKey: req.bbnPubKey, txHash: res.TxHash, // pass the channel to the event so that we can send the response to the user which requested diff --git a/service/fastsync_test.go b/service/fastsync_test.go index 54800e4e..72bdf54f 100644 --- a/service/fastsync_test.go +++ b/service/fastsync_test.go @@ -22,11 +22,9 @@ func FuzzFastSync(f *testing.F) { currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() - err := app.Start() - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) + valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) require.NoError(t, err) // commit public randomness diff --git a/service/rpcserver.go b/service/rpcserver.go index f6c449fb..ed93ed73 100644 --- a/service/rpcserver.go +++ b/service/rpcserver.go @@ -9,8 +9,6 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/lightningnetwork/lnd/signal" "github.com/sirupsen/logrus" "google.golang.org/grpc" @@ -109,17 +107,14 @@ func (r *rpcServer) CreateValidator(ctx context.Context, req *proto.CreateValida if err != nil { return nil, err } - result, err := r.app.CreateValidator(req.KeyName, req.Description, &commissionRate) + result, err := r.app.CreateValidator(req.KeyName, req.ChainId, req.PassPhrase, req.Description, &commissionRate) if err != nil { return nil, err } - btcPk := bbntypes.BIP340PubKey(schnorr.SerializePubKey(&result.BtcValidatorPk)) - return &proto.CreateValidatorResponse{ - BtcPk: btcPk.MarshalHex(), - BabylonPk: hex.EncodeToString(result.BabylonValidatorPk.Key), + BtcPk: result.ValPk.MarshalHex(), }, nil } @@ -128,14 +123,14 @@ func (r *rpcServer) CreateValidator(ctx context.Context, req *proto.CreateValida func (r *rpcServer) RegisterValidator(ctx context.Context, req *proto.RegisterValidatorRequest) ( *proto.RegisterValidatorResponse, error) { - txRes, bbnPk, err := r.app.RegisterValidator(req.KeyName) + txRes, err := r.app.RegisterValidator(req.BtcPk) if err != nil { return nil, fmt.Errorf("failed to register the validator to Babylon: %w", err) } // the validator instance should be started right after registration - if err := r.app.StartHandlingValidator(bbnPk); err != nil { - return nil, fmt.Errorf("failed to start the registered validator %s: %w", hex.EncodeToString(bbnPk.Key), err) + if err := r.app.StartHandlingValidator(txRes.btcPubKey); err != nil { + return nil, fmt.Errorf("failed to start the registered validator %s: %w", hex.EncodeToString(txRes.bbnPubKey.Key), err) } return &proto.RegisterValidatorResponse{TxHash: txRes.TxHash}, nil @@ -146,8 +141,12 @@ func (r *rpcServer) RegisterValidator(ctx context.Context, req *proto.RegisterVa func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFinalitySignatureRequest) ( *proto.AddFinalitySignatureResponse, error) { - bbnPk := &secp256k1.PubKey{Key: req.BabylonPk} - v, err := r.app.GetValidatorInstance(bbnPk) + valPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + + v, err := r.app.GetValidatorInstance(valPk) if err != nil { return nil, err } @@ -167,7 +166,7 @@ func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFina // if privKey is not empty, then this BTC validator // has voted for a fork and will be slashed if privKey != nil { - localPrivKey, err := r.app.getBtcPrivKey(v.GetStoreValidator().KeyName) + localPrivKey, err := r.app.getValPrivKey(valPk.MustMarshal()) res.ExtractedSkHex = privKey.Key.String() if err != nil { return nil, err @@ -192,8 +191,11 @@ func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFina func (r *rpcServer) QueryValidator(ctx context.Context, req *proto.QueryValidatorRequest) ( *proto.QueryValidatorResponse, error) { - bbnPk := &secp256k1.PubKey{Key: req.BabylonPk} - val, err := r.app.GetValidatorInstance(bbnPk) + valPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + val, err := r.app.GetValidatorInstance(valPk) if err != nil { return nil, err } diff --git a/service/types.go b/service/types.go index 647005bd..a912ce8f 100644 --- a/service/types.go +++ b/service/types.go @@ -16,11 +16,12 @@ import ( ) type createValidatorResponse struct { - BtcValidatorPk btcec.PublicKey - BabylonValidatorPk secp256k1.PubKey + ValPk *bbntypes.BIP340PubKey } type createValidatorRequest struct { keyName string + passPhrase string + chainID string description *stakingtypes.Description commission *sdktypes.Dec errResponse chan error @@ -40,12 +41,15 @@ type registerValidatorRequest struct { type validatorRegisteredEvent struct { bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey txHash string successResponse chan *RegisterValidatorResponse } type RegisterValidatorResponse struct { - TxHash string + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + TxHash string } type AddJurySigResponse struct { @@ -53,8 +57,7 @@ type AddJurySigResponse struct { } type CreateValidatorResult struct { - BtcValidatorPk btcec.PublicKey - BabylonValidatorPk secp256k1.PubKey + ValPk *bbntypes.BIP340PubKey } type unbondingTxSigData struct { @@ -149,6 +152,10 @@ func (v *ValidatorInstance) GetLastCommittedHeight() uint64 { return v.state.getStoreValidator().LastCommittedHeight } +func (v *ValidatorInstance) GetChainID() []byte { + return []byte(v.state.getStoreValidator().ChainId) +} + func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { return v.state.setStatus(s) } @@ -205,12 +212,17 @@ func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uin } } -// only used for testing purpose -func (v *ValidatorInstance) GetCommittedPubRandPairList() ([]*proto.SchnorrRandPair, error) { - return v.state.s.GetRandPairList(v.bbnPk.Key) +func (v *ValidatorInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { + // TODO ignore pass phrase for now + record, err := v.em.KeyRecord(v.btcPk.MustMarshal(), "") + if err != nil { + return nil, err + } + + return record.PrivKey, nil } // only used for testing purposes func (v *ValidatorInstance) BtcPrivKey() (*btcec.PrivateKey, error) { - return v.kc.GetBtcPrivKey() + return v.getEOTSPrivKey() } diff --git a/service/validator_instance.go b/service/validator_instance.go index de56b4d5..c5ff074a 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -8,12 +8,10 @@ import ( "time" "github.com/avast/retry-go/v4" - "github.com/babylonchain/babylon/crypto/eots" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" ftypes "github.com/babylonchain/babylon/x/finality/types" "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/relayer/v2/relayer/provider" "github.com/gogo/protobuf/jsonpb" @@ -22,6 +20,7 @@ import ( "golang.org/x/sync/errgroup" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/val" @@ -36,7 +35,7 @@ type ValidatorInstance struct { cfg *valcfg.Config logger *logrus.Logger - kc *val.KeyringController + em eotsmanager.EOTSManager cc clientcontroller.ClientController poller *ChainPoller @@ -54,15 +53,15 @@ type ValidatorInstance struct { // NewValidatorInstance returns a ValidatorInstance instance with the given Babylon public key // the validator should be registered before func NewValidatorInstance( - bbnPk *secp256k1.PubKey, + valPk *bbntypes.BIP340PubKey, cfg *valcfg.Config, s *val.ValidatorStore, - kr keyring.Keyring, cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, errChan chan<- *CriticalError, logger *logrus.Logger, ) (*ValidatorInstance, error) { - v, err := s.GetStoreValidator(bbnPk.Key) + v, err := s.GetStoreValidator(valPk.MustMarshal()) if err != nil { return nil, fmt.Errorf("failed to retrive the validator %s from DB: %w", v.GetBabylonPkHexString(), err) } @@ -72,14 +71,9 @@ func NewValidatorInstance( return nil, fmt.Errorf("the validator %s has not been registered", v.KeyName) } - kc, err := val.NewKeyringControllerWithKeyring(kr, v.KeyName) - if err != nil { - return nil, err - } - return &ValidatorInstance{ - bbnPk: bbnPk, btcPk: v.MustGetBIP340BTCPK(), + bbnPk: v.GetBabylonPK(), state: &valState{ v: v, s: s, @@ -90,7 +84,7 @@ func NewValidatorInstance( inSync: atomic.NewBool(false), isLagging: atomic.NewBool(false), criticalErrChan: errChan, - kc: kc, + em: em, cc: cc, }, nil } @@ -168,7 +162,7 @@ func (v *ValidatorInstance) Stop() error { close(v.quit) v.wg.Wait() - v.logger.Debugf("The thread handling validator %s is successfully stopped", v.GetBtcPkHex()) + v.logger.Debugf("the thread handling validator %s is successfully stopped", v.GetBtcPkHex()) return nil } @@ -291,7 +285,7 @@ func (v *ValidatorInstance) unbondindSigSubmissionLoop() { "btc_pk_hex": v.GetBtcPkHex(), }).Debug("Retrieved delegations which need unbonding signatures") - validatorPrivKey, err := v.kc.GetBtcPrivKey() + validatorPrivKey, err := v.getEOTSPrivKey() if err != nil { // Kill the app, if we can't recover our private key, then we have some bug @@ -585,7 +579,6 @@ func (v *ValidatorInstance) reportCriticalErr(err error) { v.criticalErrChan <- &CriticalError{ err: err, valBtcPk: v.GetBtcPkBIP340(), - bbnPk: v.GetBabylonPk(), } } @@ -704,6 +697,9 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. return nil, fmt.Errorf("failed to query the consumer chain for the last committed height: %w", err) } + // NOTE: this check will cause failure to the case when the program dies + // after committing randomness to babylon but before we update the last_committed_height + // TODO: consider remove this check if v.GetLastCommittedHeight() != lastCommittedHeight { // for some reason number of random numbers locally does not match the chain node // log it and try to recover somehow @@ -729,7 +725,12 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. } // generate a list of Schnorr randomness pairs - privRandList, pubRandList, err := GenerateRandPairList(v.cfg.NumPubRand) + // 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 := v.createPubRandList(startHeight) if err != nil { return nil, fmt.Errorf("failed to generate randomness: %w", err) } @@ -746,7 +747,7 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. } // sign the message hash using the validator's BTC private key - schnorrSig, err := v.kc.SchnorrSign(hash) + schnorrSig, err := v.em.SignSchnorrSig(v.btcPk.MustMarshal(), hash) if err != nil { return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) } @@ -758,28 +759,6 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) } - // save the committed random list to DB - // TODO 1: Optimize the db interface to batch the saving operations - // TODO 2: Consider safety after recovery - for i, pr := range privRandList { - height := startHeight + uint64(i) - privRand := pr.Bytes() - randPair, err := types.NewSchnorrRandPair(privRand[:], pubRandList[i].MustMarshal()) - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Fatal("invalid Schnorr randomness") - } - err = v.state.s.SaveRandPair(v.GetBabylonPk().Key, height, randPair) - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Fatal("err while saving committed random pair to DB") - } - } - newLastCommittedHeight := startHeight + uint64(len(pubRandList)-1) v.MustSetLastCommittedHeight(newLastCommittedHeight) @@ -787,6 +766,25 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. return res, nil } +func (v *ValidatorInstance) createPubRandList(startHeight uint64) ([]bbntypes.SchnorrPubRand, error) { + pubRandList, err := v.em.CreateRandomnessPairList( + v.btcPk.MustMarshal(), + v.GetChainID(), + startHeight, + uint32(v.cfg.NumPubRand), + ) + 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 (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*provider.RelayerTxResponse, error) { eotsSig, err := v.signEotsSig(b) @@ -837,21 +835,13 @@ func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockI func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { // build proper finality signature request - privRand, err := v.getCommittedPrivPubRand(b.Height) - if err != nil { - return nil, fmt.Errorf("failed to get the randomness pair from DB: %w", err) - } - btcPrivKey, err := v.kc.GetBtcPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get BTC private key from the keyring: %w", err) - } msg := &ftypes.MsgAddFinalitySig{ ValBtcPk: v.btcPk, BlockHeight: b.Height, BlockLastCommitHash: b.LastCommitHash, } msgToSign := msg.MsgToSign() - sig, err := eots.Sign(btcPrivKey, privRand, msgToSign) + sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height) if err != nil { return nil, fmt.Errorf("failed to sign EOTS: %w", err) } @@ -954,22 +944,6 @@ func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*typ return response, nil } -func (v *ValidatorInstance) getCommittedPrivPubRand(height uint64) (*eots.PrivateRand, error) { - randPair, err := v.state.s.GetRandPair(v.bbnPk.Key, height) - if err != nil { - return nil, err - } - - if len(randPair.SecRand) != types.SchnorrRandomnessLength { - return nil, fmt.Errorf("the private randomness should be %v bytes", types.SchnorrRandomnessLength) - } - - privRand := new(eots.PrivateRand) - privRand.SetByteSlice(randPair.SecRand) - - return privRand, nil -} - func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { var latestBlock *types.BlockInfo diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go index f4c28b5a..7ab54f09 100644 --- a/service/validator_instance_test.go +++ b/service/validator_instance_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" @@ -28,14 +29,12 @@ func FuzzCommitPubRandList(f *testing.F) { startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() - err := app.Start() - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) + valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) require.NoError(t, err) expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). @@ -50,11 +49,6 @@ func FuzzCommitPubRandList(f *testing.F) { // check the last_committed_height numPubRand := app.GetConfig().NumPubRand require.Equal(t, startingBlock.Height+numPubRand, valIns.GetStoreValidator().LastCommittedHeight) - - // check the committed pub rand - randPairs, err := valIns.GetCommittedPubRandPairList() - require.NoError(t, err) - require.Equal(t, int(numPubRand), len(randPairs)) }) } @@ -68,13 +62,11 @@ func FuzzSubmitFinalitySig(f *testing.F) { startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() - err := app.Start() - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) + valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) require.NoError(t, err) // commit public randomness @@ -109,7 +101,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { }) } -func newValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.ValidatorApp, *proto.StoreValidator, func()) { +func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.ValidatorApp, *proto.StoreValidator, func()) { // create validator app with config cfg := valcfg.DefaultConfig() cfg.DatabaseConfig = testutil.GenDBConfig(r, t) @@ -118,15 +110,23 @@ func newValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clien cfg.ValidatorModeConfig.AutoChainScanningMode = false cfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight logger := logrus.New() - app, err := service.NewValidatorAppFromConfig(&cfg, logger, cc) + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + require.NoError(t, err) + em, err := eotsmanager.NewEOTSManager(eotsCfg) + require.NoError(t, err) + app, err := service.NewValidatorApp(&cfg, cc, em, logger) + require.NoError(t, err) + err = app.Start() require.NoError(t, err) // create registered validator validator := testutil.GenStoredValidator(r, t, app) err = app.GetValidatorStore().SetValidatorStatus(validator, proto.ValidatorStatus_REGISTERED) require.NoError(t, err) - config := app.GetConfig() + err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK()) + require.NoError(t, err) + config := app.GetConfig() cleanUp := func() { err = app.Stop() require.NoError(t, err) @@ -134,6 +134,8 @@ func newValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clien require.NoError(t, err) err = os.RemoveAll(config.BabylonConfig.KeyDirectory) require.NoError(t, err) + err = os.RemoveAll(config.EOTSManagerConfig.DBPath) + require.NoError(t, err) } return app, validator, cleanUp diff --git a/service/validator_manager.go b/service/validator_manager.go index 54e9df1d..420a5961 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -1,7 +1,6 @@ package service import ( - "encoding/hex" "errors" "fmt" "sync" @@ -9,12 +8,11 @@ import ( "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/sirupsen/logrus" "go.uber.org/atomic" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/val" @@ -24,12 +22,8 @@ import ( const instanceTerminatingMsg = "terminating the validator instance due to critical error" type CriticalError struct { - err error - // TODO use validator BTC key as the unique id of - // the validator; currently, the storage is keyed - // the babylon public key + err error valBtcPk *bbntypes.BIP340PubKey - bbnPk *secp256k1.PubKey } func (ce *CriticalError) Error() string { @@ -48,8 +42,8 @@ type ValidatorManager struct { // needed for initiating validator instances vs *val.ValidatorStore config *valcfg.Config - kr keyring.Keyring cc clientcontroller.ClientController + em eotsmanager.EOTSManager logger *logrus.Logger criticalErrChan chan *CriticalError @@ -59,8 +53,8 @@ type ValidatorManager struct { func NewValidatorManager(vs *val.ValidatorStore, config *valcfg.Config, - kr keyring.Keyring, cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, logger *logrus.Logger, ) (*ValidatorManager, error) { return &ValidatorManager{ @@ -69,8 +63,8 @@ func NewValidatorManager(vs *val.ValidatorStore, isStarted: atomic.NewBool(false), vs: vs, config: config, - kr: kr, cc: cc, + em: em, logger: logger, quit: make(chan struct{}), }, nil @@ -87,7 +81,7 @@ func (vm *ValidatorManager) monitorCriticalErr() { for { select { case criticalErr = <-vm.criticalErrChan: - vi, err := vm.GetValidatorInstance(criticalErr.bbnPk) + vi, err := vm.GetValidatorInstance(criticalErr.valBtcPk) if err != nil { panic(fmt.Errorf("failed to get the validator instance: %w", err)) } @@ -151,7 +145,6 @@ func (vm *ValidatorManager) monitorStatusUpdate() { if v.GetStatus() != proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_ACTIVE) vm.logger.WithFields(logrus.Fields{ - "err": err, "val_btc_pk": v.GetBtcPkHex(), "old_status": v.GetStatus(), "power": power, @@ -171,7 +164,6 @@ func (vm *ValidatorManager) monitorStatusUpdate() { if slashedHeight > 0 { vm.setValidatorSlashed(v) vm.logger.WithFields(logrus.Fields{ - "err": err, "val_btc_pk": v.GetBtcPkHex(), "old_status": v.GetStatus(), "slashed_height": slashedHeight, @@ -182,7 +174,6 @@ func (vm *ValidatorManager) monitorStatusUpdate() { if v.GetStatus() == proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_INACTIVE) vm.logger.WithFields(logrus.Fields{ - "err": err, "val_btc_pk": v.GetBtcPkHex(), "old_status": v.GetStatus(), }).Debug("the validator status has changed to INACTIVE") @@ -196,7 +187,7 @@ func (vm *ValidatorManager) monitorStatusUpdate() { func (vm *ValidatorManager) setValidatorSlashed(vi *ValidatorInstance) { vi.MustSetStatus(proto.ValidatorStatus_SLASHED) - if err := vm.removeValidatorInstance(vi.GetBabylonPk()); err != nil { + if err := vm.removeValidatorInstance(vi.GetBtcPkBIP340()); err != nil { panic(fmt.Errorf("failed to terminate a slashed validator %s: %w", vi.GetBtcPkHex(), err)) } } @@ -218,7 +209,7 @@ func (vm *ValidatorManager) Start() error { go vm.monitorStatusUpdate() for _, v := range storedValidators { - if err := vm.addValidatorInstance(v.GetBabylonPK()); err != nil { + if err := vm.addValidatorInstance(v.MustGetBIP340BTCPK()); err != nil { return err } } @@ -261,11 +252,11 @@ func (vm *ValidatorManager) ListValidatorInstances() []*ValidatorInstance { return valsList } -func (vm *ValidatorManager) GetValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { +func (vm *ValidatorManager) GetValidatorInstance(valPk *bbntypes.BIP340PubKey) (*ValidatorInstance, error) { vm.mu.Lock() defer vm.mu.Unlock() - keyHex := hex.EncodeToString(babylonPk.Key) + keyHex := valPk.MarshalHex() v, exists := vm.vals[keyHex] if !exists { return nil, fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) @@ -274,11 +265,11 @@ func (vm *ValidatorManager) GetValidatorInstance(babylonPk *secp256k1.PubKey) (* return v, nil } -func (vm *ValidatorManager) removeValidatorInstance(babylonPk *secp256k1.PubKey) error { +func (vm *ValidatorManager) removeValidatorInstance(valPk *bbntypes.BIP340PubKey) error { vm.mu.Lock() defer vm.mu.Unlock() - keyHex := hex.EncodeToString(babylonPk.Key) + keyHex := valPk.MarshalHex() v, exists := vm.vals[keyHex] if !exists { return fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) @@ -295,17 +286,17 @@ func (vm *ValidatorManager) removeValidatorInstance(babylonPk *secp256k1.PubKey) // addValidatorInstance creates a validator instance, starts it and adds it into the validator manager func (vm *ValidatorManager) addValidatorInstance( - pk *secp256k1.PubKey, + pk *bbntypes.BIP340PubKey, ) error { vm.mu.Lock() defer vm.mu.Unlock() - pkHex := hex.EncodeToString(pk.Key) + pkHex := pk.MarshalHex() if _, exists := vm.vals[pkHex]; exists { return fmt.Errorf("validator instance already exists") } - valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.kr, vm.cc, vm.criticalErrChan, vm.logger) + valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.cc, vm.em, vm.criticalErrChan, vm.logger) if err != nil { return fmt.Errorf("failed to create validator %s instance: %w", pkHex, err) } diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index 3f4ce5fd..c117c994 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/babylonchain/babylon/testutil/datagen" + "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" coretypes "github.com/cometbft/cometbft/rpc/core/types" cometbfttypes "github.com/cometbft/cometbft/types" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" @@ -107,19 +109,31 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c valStore, err := val.NewValidatorStore(cfg.DatabaseConfig) require.NoError(t, err) - vm, err := service.NewValidatorManager(valStore, &cfg, kr, cc, logger) + eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + require.NoError(t, err) + em, err := eotsmanager.NewEOTSManager(eotsCfg) + require.NoError(t, err) + + vm, err := service.NewValidatorManager(valStore, &cfg, cc, em, logger) require.NoError(t, err) // create registered validator keyName := datagen.GenRandomHexStr(r, 10) - kc, err := val.NewKeyringControllerWithKeyring(kr, keyName) + chainID := datagen.GenRandomHexStr(r, 10) + kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName, chainID) + require.NoError(t, err) + btcPkBytes, err := em.CreateKey(keyName, "") require.NoError(t, err) - btcPk, bbnPk, err := kc.CreateValidatorKeys() + btcPk, err := types.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - pop, err := kc.CreatePop() + bbnPk, err := kc.CreateChainKey() + require.NoError(t, err) + valRecord, err := em.KeyRecord(btcPk.MustMarshal(), "") + require.NoError(t, err) + pop, err := kc.CreatePop(valRecord.PrivKey) require.NoError(t, err) - storedValidator := val.NewStoreValidator(bbnPk, btcPk, keyName, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + storedValidator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) storedValidator.Status = proto.ValidatorStatus_REGISTERED err = valStore.SaveValidator(storedValidator) require.NoError(t, err) @@ -131,6 +145,8 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) require.NoError(t, err) + err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) + require.NoError(t, err) } return vm, cleanUp diff --git a/testutil/datagen.go b/testutil/datagen.go index 9c19d455..20fac727 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -14,10 +14,10 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/codec" + "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -85,24 +85,14 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp) *proto.StoreValidator { // generate keyring keyName := GenRandomHexStr(r, 4) - kc, err := val.NewKeyringControllerWithKeyring(app.GetKeyring(), keyName) - require.NoError(t, err) - - // create validator using the keyring - btcPk, bbnPk, err := kc.CreateValidatorKeys() - require.NoError(t, err) + chainID := GenRandomHexStr(r, 4) - pop, err := kc.CreatePop() + res, err := app.CreateValidator(keyName, chainID, "", EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) - validator := val.NewStoreValidator(bbnPk, btcPk, kc.GetKeyName(), pop, EmptyDescription(), ZeroCommissionRate()) - - // save the validator - s := app.GetValidatorStore() - err = s.SaveValidator(validator) + storedVal, err := app.GetValidatorStore().GetStoreValidator(res.ValPk.MustMarshal()) require.NoError(t, err) - - return validator + return storedVal } func GenDBConfig(r *rand.Rand, t *testing.T) *valcfg.DatabaseConfig { @@ -117,13 +107,17 @@ func GenDBConfig(r *rand.Rand, t *testing.T) *valcfg.DatabaseConfig { return dbcfg } -func GenEOTSConfig(r *rand.Rand, t *testing.T) *valcfg.EOTSManagerConfig { +func GenEOTSConfig(r *rand.Rand, t *testing.T) *config.Config { bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - path := filepath.Join(t.TempDir(), bucketName) - eotsCfg, err := valcfg.NewEOTSManagerConfig( + dir := t.TempDir() + path := filepath.Join(dir, bucketName) + eotsCfg, err := config.NewConfig( + "local", "bbolt", path, bucketName, + dir, + "test", ) require.NoError(t, err) return eotsCfg diff --git a/val/keyringcontroller.go b/val/keyringcontroller.go index e2a71341..acb6bc4d 100644 --- a/val/keyringcontroller.go +++ b/val/keyringcontroller.go @@ -3,10 +3,8 @@ package val import ( "fmt" - "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/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -14,31 +12,23 @@ import ( ) const ( - btcPrefix = "btc-" - bbnPrefix = "bbn-" secp256k1Type = "secp256k1" mnemonicEntropySize = 256 ) -type KeyName string - -func (kn KeyName) GetBabylonKeyName() string { - return bbnPrefix + string(kn) -} - -func (kn KeyName) GetBtcKeyName() string { - return btcPrefix + string(kn) -} - -type KeyringController struct { - kr keyring.Keyring - name KeyName +type ChainKeyringController struct { + kr keyring.Keyring + valName string + chainID string } -func NewKeyringController(ctx client.Context, name string, keyringBackend string) (*KeyringController, error) { +func NewChainKeyringController(ctx client.Context, name, chainID, keyringBackend string) (*ChainKeyringController, error) { if name == "" { return nil, fmt.Errorf("the key name should not be empty") } + if chainID == "" { + return nil, fmt.Errorf("the chainID should not be empty") + } if keyringBackend == "" { return nil, fmt.Errorf("the keyring backend should not be empty") } @@ -54,105 +44,33 @@ func NewKeyringController(ctx client.Context, name string, keyringBackend string return nil, fmt.Errorf("failed to create keyring: %w", err) } - return &KeyringController{ - name: KeyName(name), - kr: kr, + return &ChainKeyringController{ + valName: name, + kr: kr, + chainID: chainID, }, nil } -func NewKeyringControllerWithKeyring(kr keyring.Keyring, name string) (*KeyringController, error) { +func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name, chainID string) (*ChainKeyringController, error) { if name == "" { return nil, fmt.Errorf("the key name should not be empty") } - return &KeyringController{ - kr: kr, - name: KeyName(name), - }, nil -} - -// CreateValidatorKeys creates a BTC validator object using the keyring -func (kc *KeyringController) CreateValidatorKeys() (*types.BIP340PubKey, *secp256k1.PubKey, error) { - // create babylon key pair stored in the keyring - babylonPubKey, err := kc.createBabylonKeyPair() - if err != nil { - return nil, nil, err - } - - // create BTC key pair stored in the keyring - btcPubKey, err := kc.createBIP340KeyPair() - if err != nil { - return nil, nil, err - } - - return btcPubKey, babylonPubKey, nil -} - -func (kc *KeyringController) GetKeyName() string { - return string(kc.name) -} - -func (kc *KeyringController) GetBabylonPublicKeyBytes() ([]byte, error) { - k, err := kc.kr.Key(kc.name.GetBabylonKeyName()) - if err != nil { - return nil, err - } - pubKey, err := k.GetPubKey() - if err != nil { - return nil, err + if chainID == "" { + return nil, fmt.Errorf("the chainID should not be empty") } - return pubKey.Bytes(), err -} - -func (kc *KeyringController) ValidatorKeyExists() bool { - return kc.keyExists(kc.name.GetBabylonKeyName()) && kc.keyExists(kc.name.GetBtcKeyName()) -} - -func (kc *KeyringController) ValidatorKeyNameTaken() bool { - return kc.keyExists(kc.name.GetBabylonKeyName()) || kc.keyExists(kc.name.GetBtcKeyName()) -} - -func (kc *KeyringController) JuryKeyTaken() bool { - return kc.keyExists(kc.GetKeyName()) -} -func (kc *KeyringController) keyExists(name string) bool { - _, err := kc.kr.Key(name) - return err == nil + return &ChainKeyringController{ + kr: kr, + valName: name, + chainID: chainID, + }, nil } -func (kc *KeyringController) GetKeyring() keyring.Keyring { +func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { return kc.kr } -// createBabylonKeyPair creates a babylon key pair stored in the keyring -func (kc *KeyringController) createBabylonKeyPair() (*secp256k1.PubKey, error) { - return kc.createKey(kc.name.GetBabylonKeyName()) -} - -// createBIP340KeyPair creates a BIP340 key pair stored in the keyring -func (kc *KeyringController) createBIP340KeyPair() (*types.BIP340PubKey, error) { - sdkPk, err := kc.createKey(kc.name.GetBtcKeyName()) - if err != nil { - return nil, err - } - - btcPk, err := btcec.ParsePubKey(sdkPk.Key) - if err != nil { - return nil, err - } - return types.NewBIP340PubKeyFromBTCPK(btcPk), nil -} - -func (kc *KeyringController) CreateJuryKey() (*btcec.PublicKey, error) { - sdkPk, err := kc.createKey(string(kc.name)) - if err != nil { - return nil, err - } - - return btcec.ParsePubKey(sdkPk.Key) -} - -func (kc *KeyringController) createKey(name string) (*secp256k1.PubKey, error) { +func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { keyringAlgos, _ := kc.kr.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { @@ -169,11 +87,12 @@ func (kc *KeyringController) createKey(name string) (*secp256k1.PubKey, error) { if err != nil { return nil, err } + // TODO use a better way to remind the user to keep it - fmt.Printf("Generated mnemonic for key %s is %s\n", name, mnemonic) + fmt.Printf("Generated mnemonic for the validator %s connected to chain %s is:\n%s\n", kc.valName, kc.chainID, mnemonic) // TODO for now we leave bip39Passphrase and hdPath empty - record, err := kc.kr.NewAccount(name, mnemonic, "", "", algo) + record, err := kc.kr.NewAccount(GetKeyName(kc.chainID, kc.valName), mnemonic, "", "", algo) if err != nil { return nil, err } @@ -191,74 +110,34 @@ func (kc *KeyringController) createKey(name string) (*secp256k1.PubKey, error) { } } +func GetKeyName(chainID, valName string) string { + return chainID + "-" + valName +} + // CreatePop creates proof-of-possession of Babylon and BTC public keys // the input is the bytes of BTC public key used to sign // this requires both keys created beforehand -func (kc *KeyringController) CreatePop() (*bstypes.ProofOfPossession, error) { - if !kc.ValidatorKeyExists() { - return nil, fmt.Errorf("the keys do not exist") - } - - btcPrivKey, err := kc.GetBtcPrivKey() +func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey) (*bstypes.ProofOfPossession, error) { + bbnPrivKey, err := kc.GetChainPrivKey() if err != nil { return nil, err } - bbnPrivKey, err := kc.GetBabylonPrivKey() - if err != nil { - return nil, err - } return bstypes.NewPoP(bbnPrivKey, btcPrivKey) } -func (kc *KeyringController) GetBabylonPrivKey() (*secp256k1.PrivKey, error) { - bbnName := kc.name.GetBabylonKeyName() - - bbnPrivKey, _, err := kc.getKey(bbnName) - if err != nil { - return nil, err - } - - sdkPrivKey := &secp256k1.PrivKey{Key: bbnPrivKey.Serialize()} - - return sdkPrivKey, nil -} - -func (kc *KeyringController) GetBtcPrivKey() (*btcec.PrivateKey, error) { - btcName := kc.name.GetBtcKeyName() - - btcPrivKey, _, err := kc.getKey(btcName) - if err != nil { - return nil, err - } - - return btcPrivKey, nil -} - -func (kc *KeyringController) getKey(name string) (*btcec.PrivateKey, *btcec.PublicKey, error) { - k, err := kc.kr.Key(name) +func (kc *ChainKeyringController) GetChainPrivKey() (*secp256k1.PrivKey, error) { + k, err := kc.kr.Key(GetKeyName(kc.chainID, kc.valName)) if err != nil { - return nil, nil, fmt.Errorf("failed to get private key by name %s: %w", name, err) + return nil, fmt.Errorf("failed to get private key: %w", err) } privKeyCached := k.GetLocal().PrivKey.GetCachedValue() - var privKey *btcec.PrivateKey - var pubKey *btcec.PublicKey switch v := privKeyCached.(type) { case *secp256k1.PrivKey: - privKey, pubKey = btcec.PrivKeyFromBytes(v.Key) - return privKey, pubKey, nil + return v, nil default: - return nil, nil, fmt.Errorf("unsupported key type in keyring") - } -} - -func (kc *KeyringController) SchnorrSign(msg []byte) (*schnorr.Signature, error) { - btcPrivKey, _, err := kc.getKey(kc.name.GetBtcKeyName()) - if err != nil { - return nil, err + return nil, fmt.Errorf("unsupported key type in keyring") } - - return schnorr.Sign(btcPrivKey, msg) } diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index 424cfb4a..d046674c 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -8,6 +8,7 @@ import ( "github.com/babylonchain/babylon/types" "github.com/stretchr/testify/require" + "github.com/babylonchain/btc-validator/eotsmanager/local" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/val" ) @@ -20,22 +21,32 @@ func FuzzCreatePoP(f *testing.F) { keyName := testutil.GenRandomHexStr(r, 4) sdkCtx := testutil.GenSdkContext(r, t) + + chainID := testutil.GenRandomHexStr(r, 4) + kc, err := val.NewChainKeyringController(sdkCtx, keyName, chainID, "test") + require.NoError(t, err) + + cfg := testutil.GenEOTSConfig(r, t) + em, err := local.NewLocalEOTSManager(sdkCtx, cfg) defer func() { err := os.RemoveAll(sdkCtx.KeyringDir) require.NoError(t, err) + err = os.RemoveAll(cfg.DBPath) + require.NoError(t, err) }() - kc, err := val.NewKeyringController(sdkCtx, keyName, "test") require.NoError(t, err) - require.False(t, kc.ValidatorKeyExists()) - - btcPk, bbnPk, err := kc.CreateValidatorKeys() + btcPkBytes, err := em.CreateKey(keyName, "") require.NoError(t, err) - require.True(t, kc.ValidatorKeyExists() && kc.ValidatorKeyNameTaken()) - - pop, err := kc.CreatePop() + btcPk, err := types.NewBIP340PubKey(btcPkBytes) + require.NoError(t, err) + bbnPk, err := kc.CreateChainKey() + require.NoError(t, err) + valRecord, err := em.KeyRecord(btcPk.MustMarshal(), "") + require.NoError(t, err) + pop, err := kc.CreatePop(valRecord.PrivKey) require.NoError(t, err) - validator := val.NewStoreValidator(bbnPk, btcPk, kc.GetKeyName(), pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + validator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) btcSig := new(types.BIP340Signature) err = btcSig.Unmarshal(validator.Pop.BtcSig) diff --git a/val/valstore.go b/val/valstore.go index 9a9605e8..2ee40e2b 100644 --- a/val/valstore.go +++ b/val/valstore.go @@ -18,10 +18,9 @@ import ( const ( validatorPrefix = "validator" - randPairPrefix = "rand-pair" ) -func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName string, pop *bstypes.ProofOfPossession, des *stakingtypes.Description, com *sdktypes.Dec) *proto.StoreValidator { +func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des *stakingtypes.Description, com *sdktypes.Dec) *proto.StoreValidator { return &proto.StoreValidator{ KeyName: keyName, BabylonPk: babylonPk.Bytes(), @@ -30,6 +29,7 @@ func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, k BabylonSig: pop.BabylonSig, BtcSig: pop.BtcSig, }, + ChainId: chainID, Status: proto.ValidatorStatus_CREATED, Description: des, Commission: com.String(), @@ -57,16 +57,8 @@ func (vs *ValidatorStore) getValidatorListKey() []byte { return []byte(validatorPrefix) } -func (vs *ValidatorStore) getRandPairKey(pk []byte, height uint64) []byte { - return append(vs.getRandPairListKey(pk), sdktypes.Uint64ToBigEndian(height)...) -} - -func (vs *ValidatorStore) getRandPairListKey(pk []byte) []byte { - return append([]byte(randPairPrefix), pk...) -} - func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { - k := getValidatorKey(val.BabylonPk) + k := getValidatorKey(val.BtcPk) v, err := gproto.Marshal(val) if err != nil { return fmt.Errorf("failed to marshal the created validator object: %w", err) @@ -80,7 +72,7 @@ func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { } func (vs *ValidatorStore) UpdateValidator(val *proto.StoreValidator) error { - k := getValidatorKey(val.BabylonPk) + k := getValidatorKey(val.BtcPk) exists, err := vs.s.Exists(k) if err != nil { return err @@ -106,55 +98,6 @@ func (vs *ValidatorStore) SetValidatorStatus(val *proto.StoreValidator, status p return vs.UpdateValidator(val) } -func (vs *ValidatorStore) SaveRandPair(pk []byte, height uint64, randPair *proto.SchnorrRandPair) error { - k := vs.getRandPairKey(pk, height) - v, err := gproto.Marshal(randPair) - if err != nil { - return fmt.Errorf("failed to marshal the Schnorr random pair: %w", err) - } - - if err := vs.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the Schnorr random pair: %w", err) - } - - return nil -} - -func (vs *ValidatorStore) GetRandPairList(pk []byte) ([]*proto.SchnorrRandPair, error) { - k := vs.getRandPairListKey(pk) - pairsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - pairList := make([]*proto.SchnorrRandPair, len(pairsBytes)) - for i := 0; i < len(pairsBytes); i++ { - pair := new(proto.SchnorrRandPair) - err := gproto.Unmarshal(pairsBytes[i].Value, pair) - if err != nil { - panic(fmt.Errorf("failed to unmarshal Schnorr randomness pair from the database: %w", err)) - } - pairList[i] = pair - } - - return pairList, nil -} - -func (vs *ValidatorStore) GetRandPair(pk []byte, height uint64) (*proto.SchnorrRandPair, error) { - k := vs.getRandPairKey(pk, height) - v, err := vs.s.Get(k) - if err != nil { - return nil, fmt.Errorf("failed to get the randomness pair from DB: %w", err) - } - pair := new(proto.SchnorrRandPair) - err = gproto.Unmarshal(v, pair) - if err != nil { - panic(fmt.Errorf("unable to unmarshal Schnorr randomness pair: %w", err)) - } - - return pair, nil -} - func (vs *ValidatorStore) GetStoreValidator(pk []byte) (*proto.StoreValidator, error) { k := getValidatorKey(pk) valsBytes, err := vs.s.Get(k) diff --git a/val/valstore_test.go b/val/valstore_test.go index 33cd0ff1..dadce32b 100644 --- a/val/valstore_test.go +++ b/val/valstore_test.go @@ -32,9 +32,9 @@ func FuzzValidatorStore(f *testing.F) { valList, err := vs.ListValidators() require.NoError(t, err) - require.Equal(t, validator.BabylonPk, valList[0].BabylonPk) + require.Equal(t, validator.BtcPk, valList[0].BtcPk) - actualVal, err := vs.GetStoreValidator(validator.BabylonPk) + actualVal, err := vs.GetStoreValidator(validator.BtcPk) require.NoError(t, err) require.Equal(t, validator.BabylonPk, actualVal.BabylonPk) require.Equal(t, validator.BtcPk, actualVal.BtcPk) diff --git a/valcfg/eotsmanager.go b/valcfg/eotsmanager.go index 6c82e579..5cc2a527 100644 --- a/valcfg/eotsmanager.go +++ b/valcfg/eotsmanager.go @@ -2,15 +2,19 @@ package valcfg import ( "fmt" + + "github.com/babylonchain/btc-validator/eotsmanager/config" ) const ( DefaultEOTSManagerDBBackend = "bbolt" DefaultEOTSManagerDBPath = "bbolt-eots.db" DefaultEOTSManagerDBName = "eots-default" + DefaultEOTSManagerMode = "local" ) type EOTSManagerConfig struct { + Mode string `long:"mode" description:"Indicates in which mode the EOTS manager is running" choice:"local" choice:"remote"` DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` DBPath string `long:"dbpath" description:"The path that stores the database file"` DBName string `long:"dbname" description:"The name of the database"` @@ -36,10 +40,22 @@ func NewEOTSManagerConfig(backend string, path string, name string) (*EOTSManage }, nil } +func AppConfigToEOTSManagerConfig(appCfg *Config) (*config.Config, error) { + return config.NewConfig( + appCfg.EOTSManagerConfig.Mode, + appCfg.EOTSManagerConfig.DBBackend, + appCfg.EOTSManagerConfig.DBPath, + appCfg.EOTSManagerConfig.DBName, + appCfg.BabylonConfig.KeyDirectory, + appCfg.BabylonConfig.KeyringBackend, + ) +} + func DefaultEOTSManagerConfig() EOTSManagerConfig { return EOTSManagerConfig{ DBBackend: DefaultEOTSManagerDBBackend, DBPath: DefaultEOTSManagerDBPath, DBName: DefaultEOTSManagerDBName, + Mode: DefaultEOTSManagerMode, } } From ec5953989618b12577e00d54c6b02b5c79850534 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 16 Oct 2023 14:46:58 +0800 Subject: [PATCH 04/66] chore: Bump babylon version (#117) --- clientcontroller/babylon.go | 33 ++++++++----------------- clientcontroller/interface.go | 8 +++---- go.mod | 2 +- go.sum | 4 ++-- itest/e2e_test.go | 5 +++- itest/test_manager.go | 11 +++++---- service/app_test.go | 2 +- service/event_loop.go | 6 +++-- service/validator_manager.go | 11 +++++---- testutil/datagen.go | 3 ++- testutil/mocks/babylon.go | 45 ++++++++++++----------------------- tools/go.mod | 2 +- tools/go.sum | 4 ++-- val/keyringcontroller_test.go | 3 ++- valcfg/jury.go | 15 +++++++----- 15 files changed, 68 insertions(+), 86 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 580256af..c2688b4b 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -533,39 +533,26 @@ func (bc *BabylonController) QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP3 return ks[0], nil } -// QueryPendingBTCDelegations queries BTC delegations that need a Jury sig +// QueryBTCDelegations queries BTC delegations that need a Jury signature +// with the given status (either pending or unbonding) // it is only used when the program is running in Jury mode -func (bc *BabylonController) QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) QueryBTCDelegations(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryPendingBTCDelegationsRequest{} - res, err := queryClient.PendingBTCDelegations(ctx, queryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %v", err) + pagination := &sdkquery.PageRequest{ + Limit: limit, } - return res.BtcDelegations, nil -} - -// QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning -// it is only used when the program is running in Jury mode -func (bc *BabylonController) QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} queryClient := btcstakingtypes.NewQueryClient(clientCtx) // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryUnbondingBTCDelegationsRequest{} - res, err := queryClient.UnbondingBTCDelegations(ctx, queryRequest) + queryRequest := &btcstakingtypes.QueryBTCDelegationsRequest{ + Status: status, + Pagination: pagination, + } + res, err := queryClient.BTCDelegations(ctx, queryRequest) if err != nil { return nil, fmt.Errorf("failed to query BTC delegations: %v", err) } diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 63a66ce4..2e5424bd 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -86,13 +86,11 @@ type ClientController interface { // QueryHeightWithLastPubRand queries the height of the last block with public randomness QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP340PubKey) (uint64, error) - // QueryPendingBTCDelegations queries BTC delegations that need a Jury signature - // it is only used when the program is running in Jury mode - QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) - // QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning + // QueryBTCDelegations queries BTC delegations that need a Jury signature + // with the given status (either pending or unbonding) // it is only used when the program is running in Jury mode - QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) + QueryBTCDelegations(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) // QueryValidatorVotingPower queries the voting power of the validator at a given height QueryValidatorVotingPower(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64) (uint64, error) diff --git a/go.mod b/go.mod index a7836e3d..54f09d55 100644 --- a/go.mod +++ b/go.mod @@ -303,7 +303,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 6e657cdf..c841c93d 100644 --- a/go.sum +++ b/go.sum @@ -269,8 +269,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20230914082434-aece8a12b91c h1:n4XLSd0DZapEdoiekdwlDvhjknaSG/7AOLhg8eW53Wg= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 h1:o5a+fpqjWNpZQMWE22vW8Aqj6csIlTGDp0SXH4SDyYc= +github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index f4979658..8ff9f81d 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -304,7 +304,10 @@ func TestJuryUnbondingSigSubmission(t *testing.T) { err error ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryPendingBTCDelegations() + dels, err = tm.BabylonClient.QueryBTCDelegations( + btcstakingtypes.BTCDelegationStatus_PENDING, + tm.Config.JuryModeConfig.DelegationLimit, + ) if err != nil { return false } diff --git a/itest/test_manager.go b/itest/test_manager.go index 83e993e7..38f64ed3 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -18,7 +18,6 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdktypes "github.com/cosmos/cosmos-sdk/types" @@ -211,7 +210,10 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe err error ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryPendingBTCDelegations() + dels, err = tm.BabylonClient.QueryBTCDelegations( + bstypes.BTCDelegationStatus_PENDING, + tm.Config.JuryModeConfig.DelegationLimit, + ) if err != nil { return false } @@ -491,8 +493,7 @@ func (tm *TestManager) InsertBTCUnbonding( slashingAddr := params.SlashingAddress stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) - stakingTxHash := stakingTx.MustGetTxHash() - stakingTxChainHash, err := chainhash.NewHashFromStr(stakingTxHash) + stakingTxChainHash := stakingTx.MustGetTxHash() require.NoError(t, err) stakingOutputIdx, err := btcstaking.GetIdxOutputCommitingToScript( @@ -509,7 +510,7 @@ func (tm *TestManager) InsertBTCUnbonding( stakerPrivKey, validatorPk, params.JuryPk, - wire.NewOutPoint(stakingTxChainHash, uint32(stakingOutputIdx)), + wire.NewOutPoint(&stakingTxChainHash, uint32(stakingOutputIdx)), uint16(params.FinalizationTimeoutBlocks)+1, stakingValue-fee, slashingAddr, diff --git a/service/app_test.go b/service/app_test.go index 04c668b3..b95c2c8f 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -170,7 +170,7 @@ func FuzzAddJurySig(f *testing.F) { stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryPendingBTCDelegations(). + mockClientController.EXPECT().QueryBTCDelegations(bstypes.BTCDelegationStatus_PENDING, gomock.Any()). Return([]*bstypes.BTCDelegation{delegation}, nil).AnyTimes() mockClientController.EXPECT().SubmitJurySig(delegation.ValBtcPk, delegation.BtcPk, stakingMsgTx.TxHash().String(), gomock.Any()). Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() diff --git a/service/event_loop.go b/service/event_loop.go index 3b53b9a6..3d083de2 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "time" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" @@ -14,13 +15,14 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { defer app.wg.Done() interval := app.config.JuryModeConfig.QueryInterval + limit := app.config.JuryModeConfig.DelegationLimit jurySigTicker := time.NewTicker(interval) for { select { case <-jurySigTicker.C: // 1. Get all pending delegations first, this are more important than the unbonding ones - dels, err := app.cc.QueryPendingBTCDelegations() + dels, err := app.cc.QueryBTCDelegations(btcstakingtypes.BTCDelegationStatus_PENDING, limit) if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, @@ -41,7 +43,7 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { } } // 2. Get all unbonding delegations - unbondingDels, err := app.cc.QueryUnbondindBTCDelegations() + unbondingDels, err := app.cc.QueryBTCDelegations(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) if err != nil { app.logger.WithFields(logrus.Fields{ diff --git a/service/validator_manager.go b/service/validator_manager.go index 420a5961..a1da37ea 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -131,6 +131,7 @@ func (vm *ValidatorManager) monitorStatusUpdate() { } vals := vm.ListValidatorInstances() for _, v := range vals { + oldStatus := v.GetStatus() power, err := v.GetVotingPowerWithRetry(latestBlock.Height) if err != nil { vm.logger.WithFields(logrus.Fields{ @@ -142,11 +143,11 @@ func (vm *ValidatorManager) monitorStatusUpdate() { } // power > 0 (slashed_height must > 0), set status to ACTIVE if power > 0 { - if v.GetStatus() != proto.ValidatorStatus_ACTIVE { + if oldStatus != proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_ACTIVE) vm.logger.WithFields(logrus.Fields{ "val_btc_pk": v.GetBtcPkHex(), - "old_status": v.GetStatus(), + "old_status": oldStatus, "power": power, }).Debug("the validator status has changed to ACTIVE") } @@ -165,17 +166,17 @@ func (vm *ValidatorManager) monitorStatusUpdate() { vm.setValidatorSlashed(v) vm.logger.WithFields(logrus.Fields{ "val_btc_pk": v.GetBtcPkHex(), - "old_status": v.GetStatus(), + "old_status": oldStatus, "slashed_height": slashedHeight, }).Debug("the validator status has been slashed") continue } // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE - if v.GetStatus() == proto.ValidatorStatus_ACTIVE { + if oldStatus == proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_INACTIVE) vm.logger.WithFields(logrus.Fields{ "val_btc_pk": v.GetBtcPkHex(), - "old_status": v.GetStatus(), + "old_status": oldStatus, }).Debug("the validator status has changed to INACTIVE") } } diff --git a/testutil/datagen.go b/testutil/datagen.go index 20fac727..2b50a7ed 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -10,6 +10,7 @@ import ( "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" "github.com/stretchr/testify/require" @@ -54,7 +55,7 @@ func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { // generate and verify PoP, correct case pop, err := bstypes.NewPoP(babylonSK, btcSK) require.NoError(t, err) - err = pop.Verify(babylonPK, bip340PK) + err = pop.Verify(babylonPK, bip340PK, &chaincfg.SigNetParams) require.NoError(t, err) return &proto.StoreValidator{ diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 301fa30e..d489fa55 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -86,6 +86,21 @@ func (mr *MockClientControllerMockRecorder) GetStakingParams() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakingParams", reflect.TypeOf((*MockClientController)(nil).GetStakingParams)) } +// QueryBTCDelegations mocks base method. +func (m *MockClientController) QueryBTCDelegations(status types0.BTCDelegationStatus, limit uint64) ([]*types0.BTCDelegation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryBTCDelegations", status, limit) + ret0, _ := ret[0].([]*types0.BTCDelegation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryBTCDelegations indicates an expected call of QueryBTCDelegations. +func (mr *MockClientControllerMockRecorder) QueryBTCDelegations(status, limit interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCDelegations), status, limit) +} + // QueryBTCValidatorUnbondingDelegations mocks base method. func (m *MockClientController) QueryBTCValidatorUnbondingDelegations(valBtcPk *types.BIP340PubKey, max uint64) ([]*types0.BTCDelegation, error) { m.ctrl.T.Helper() @@ -206,36 +221,6 @@ func (mr *MockClientControllerMockRecorder) QueryNodeStatus() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryNodeStatus", reflect.TypeOf((*MockClientController)(nil).QueryNodeStatus)) } -// QueryPendingBTCDelegations mocks base method. -func (m *MockClientController) QueryPendingBTCDelegations() ([]*types0.BTCDelegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryPendingBTCDelegations") - ret0, _ := ret[0].([]*types0.BTCDelegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryPendingBTCDelegations indicates an expected call of QueryPendingBTCDelegations. -func (mr *MockClientControllerMockRecorder) QueryPendingBTCDelegations() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryPendingBTCDelegations)) -} - -// QueryUnbondindBTCDelegations mocks base method. -func (m *MockClientController) QueryUnbondindBTCDelegations() ([]*types0.BTCDelegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondindBTCDelegations") - ret0, _ := ret[0].([]*types0.BTCDelegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryUnbondindBTCDelegations indicates an expected call of QueryUnbondindBTCDelegations. -func (mr *MockClientControllerMockRecorder) QueryUnbondindBTCDelegations() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondindBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondindBTCDelegations)) -} - // QueryValidator mocks base method. func (m *MockClientController) QueryValidator(btcPk *types.BIP340PubKey) (*types0.BTCValidator, error) { m.ctrl.T.Helper() diff --git a/tools/go.mod b/tools/go.mod index c7194f76..bb4fd595 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -179,7 +179,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 diff --git a/tools/go.sum b/tools/go.sum index 3dab178b..7cdc3b7a 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -253,8 +253,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20230914082434-aece8a12b91c h1:n4XLSd0DZapEdoiekdwlDvhjknaSG/7AOLhg8eW53Wg= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 h1:o5a+fpqjWNpZQMWE22vW8Aqj6csIlTGDp0SXH4SDyYc= +github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index d046674c..acd6fe0c 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/chaincfg" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/eotsmanager/local" @@ -51,7 +52,7 @@ func FuzzCreatePoP(f *testing.F) { btcSig := new(types.BIP340Signature) err = btcSig.Unmarshal(validator.Pop.BtcSig) require.NoError(t, err) - err = pop.Verify(bbnPk, btcPk) + err = pop.Verify(bbnPk, btcPk, &chaincfg.SimNetParams) require.NoError(t, err) }) } diff --git a/valcfg/jury.go b/valcfg/jury.go index 462d6605..22e17ea2 100644 --- a/valcfg/jury.go +++ b/valcfg/jury.go @@ -5,18 +5,21 @@ import ( ) var ( - defaultJuryKeyName = "jury-key" - defaultQueryInterval = 15 * time.Second + defaultJuryKeyName = "jury-key" + defaultQueryInterval = 15 * time.Second + defaultDelegationLimit = uint64(100) ) type JuryConfig struct { - JuryKeyName string `long:"jurykeyname" description:"The key name of the Jury if the program is running in Jury mode"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` + JuryKeyName string `long:"jurykeyname" description:"The key name of the Jury if the program is running in Jury mode"` + QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` + DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Jury processes each time"` } func DefaultJuryConfig() JuryConfig { return JuryConfig{ - JuryKeyName: defaultJuryKeyName, - QueryInterval: defaultQueryInterval, + JuryKeyName: defaultJuryKeyName, + QueryInterval: defaultQueryInterval, + DelegationLimit: defaultDelegationLimit, } } From 6a0a8437eeb041a6cd63babd97c1b725404fd692 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 16 Oct 2023 20:44:32 +0800 Subject: [PATCH 05/66] Fix: bug when a validator is registered using rpc (#119) --- service/event_loop.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/event_loop.go b/service/event_loop.go index 3d083de2..8171343b 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -111,7 +111,9 @@ func (app *ValidatorApp) eventLoop() { // return to the caller ev.successResponse <- &RegisterValidatorResponse{ - TxHash: ev.txHash, + bbnPubKey: valStored.GetBabylonPK(), + btcPubKey: valStored.MustGetBIP340BTCPK(), + TxHash: ev.txHash, } case <-app.eventQuit: From 6858a1b70e3f7db5bfb52f429d7f355cd26f889d Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 17 Oct 2023 15:56:06 +0800 Subject: [PATCH 06/66] feat: Add remote eots manager (#116) --- Makefile | 1 + eotsmanager/Makefile | 10 + eotsmanager/client/rpcclient.go | 124 +++ eotsmanager/cmd/eotscli/admin.go | 66 ++ eotsmanager/cmd/eotscli/main.go | 24 + eotsmanager/cmd/eotsd/main.go | 48 ++ eotsmanager/config/config.go | 279 +++++- eotsmanager/config/db.go | 44 + eotsmanager/eotsmanager.go | 30 - eotsmanager/{local => }/eotsstore.go | 10 +- eotsmanager/errors.go | 8 - eotsmanager/{local => }/localmanager.go | 37 +- eotsmanager/{local => }/localmanager_test.go | 23 +- eotsmanager/proto/.clang-format | 7 + eotsmanager/proto/buf.gen.yaml | 8 + eotsmanager/proto/buf.lock | 2 + eotsmanager/proto/buf.yaml | 24 + eotsmanager/proto/eotsmanager.pb.go | 861 +++++++++++++++++++ eotsmanager/proto/eotsmanager.proto | 97 +++ eotsmanager/proto/eotsmanager_grpc.pb.go | 267 ++++++ eotsmanager/proto/scripts/protocgen.sh | 10 + eotsmanager/service/rpcserver.go | 112 +++ eotsmanager/service/server.go | 109 +++ go.mod | 2 +- itest/test_manager.go | 4 +- service/app.go | 29 +- service/app_test.go | 12 +- service/validator_instance_test.go | 4 +- service/validator_manager_test.go | 4 +- testutil/datagen.go | 14 +- val/keyringcontroller_test.go | 9 +- valcfg/config.go | 30 +- valcfg/eotsmanager.go | 40 - 33 files changed, 2183 insertions(+), 166 deletions(-) create mode 100644 eotsmanager/Makefile create mode 100644 eotsmanager/client/rpcclient.go create mode 100644 eotsmanager/cmd/eotscli/admin.go create mode 100644 eotsmanager/cmd/eotscli/main.go create mode 100644 eotsmanager/cmd/eotsd/main.go create mode 100644 eotsmanager/config/db.go rename eotsmanager/{local => }/eotsstore.go (91%) delete mode 100644 eotsmanager/errors.go rename eotsmanager/{local => }/localmanager.go (88%) rename eotsmanager/{local => }/localmanager_test.go (77%) create mode 100644 eotsmanager/proto/.clang-format create mode 100644 eotsmanager/proto/buf.gen.yaml create mode 100644 eotsmanager/proto/buf.lock create mode 100644 eotsmanager/proto/buf.yaml create mode 100644 eotsmanager/proto/eotsmanager.pb.go create mode 100644 eotsmanager/proto/eotsmanager.proto create mode 100644 eotsmanager/proto/eotsmanager_grpc.pb.go create mode 100755 eotsmanager/proto/scripts/protocgen.sh create mode 100644 eotsmanager/service/rpcserver.go create mode 100644 eotsmanager/service/server.go diff --git a/Makefile b/Makefile index c89cb271..7ffbe17c 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,7 @@ proto-all: proto-gen proto-gen: ./proto/scripts/protocgen.sh + make -C eotsmanager proto-gen .PHONY: proto-gen diff --git a/eotsmanager/Makefile b/eotsmanager/Makefile new file mode 100644 index 00000000..abc4da72 --- /dev/null +++ b/eotsmanager/Makefile @@ -0,0 +1,10 @@ +############################################################################### +### Protobuf ### +############################################################################### + +proto-all: proto-gen + +proto-gen: + ./proto/scripts/protocgen.sh + +.PHONY: proto-gen diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go new file mode 100644 index 00000000..4dbac51b --- /dev/null +++ b/eotsmanager/client/rpcclient.go @@ -0,0 +1,124 @@ +package client + +import ( + "context" + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/proto" + "github.com/babylonchain/btc-validator/eotsmanager/types" +) + +var _ eotsmanager.EOTSManager = &EOTSManagerGRpcClient{} + +type EOTSManagerGRpcClient struct { + client proto.EOTSManagerClient + conn *grpc.ClientConn +} + +func NewEOTSManagerGRpcClient(remoteAddr string) (*EOTSManagerGRpcClient, error) { + conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) + } + + return &EOTSManagerGRpcClient{ + client: proto.NewEOTSManagerClient(conn), + conn: conn, + }, nil +} + +func (c *EOTSManagerGRpcClient) CreateKey(name, passPhrase string) ([]byte, error) { + req := &proto.CreateKeyRequest{Name: name, PassPhrase: passPhrase} + res, err := c.client.CreateKey(context.Background(), req) + if err != nil { + return nil, err + } + + return res.Pk, nil +} + +func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { + req := &proto.CreateRandomnessPairListRequest{ + Uid: uid, + ChainId: chainID, + StartHeight: startHeight, + Num: num, + } + res, err := c.client.CreateRandomnessPairList(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 pubRandFieldValList, nil +} + +func (c *EOTSManagerGRpcClient) CreateRandomnessPairListWithExistenceCheck(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { + // TODO consider remove this API when we no longer store randomness + return c.CreateRandomnessPairList(uid, chainID, startHeight, num) +} + +func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) { + req := &proto.KeyRecordRequest{Uid: uid, PassPhrase: passPhrase} + + res, err := c.client.KeyRecord(context.Background(), req) + if err != nil { + return nil, err + } + + privKey, _ := btcec.PrivKeyFromBytes(res.PrivateKey) + + return &types.KeyRecord{ + Name: res.Name, + PrivKey: privKey, + }, nil +} + +func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64) (*btcec.ModNScalar, error) { + req := &proto.SignEOTSRequest{ + Uid: uid, + ChainId: chaiID, + Msg: msg, + Height: height, + } + res, err := c.client.SignEOTS(context.Background(), req) + if err != nil { + return nil, err + } + + var s *btcec.ModNScalar + s.SetByteSlice(res.Sig) + + return s, nil +} + +func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte) (*schnorr.Signature, error) { + req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg} + res, err := c.client.SignSchnorrSig(context.Background(), req) + if err != nil { + return nil, err + } + + sig, err := schnorr.ParseSignature(res.Sig) + if err != nil { + return nil, err + } + + return sig, nil +} + +func (c *EOTSManagerGRpcClient) Close() error { + return c.conn.Close() +} diff --git a/eotsmanager/cmd/eotscli/admin.go b/eotsmanager/cmd/eotscli/admin.go new file mode 100644 index 00000000..bb04aa00 --- /dev/null +++ b/eotsmanager/cmd/eotscli/admin.go @@ -0,0 +1,66 @@ +package main + +import ( + "fmt" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" +) + +var adminCommands = []cli.Command{ + { + Name: "admin", + ShortName: "ad", + Usage: "Different utility and admin commands.", + Category: "Admin", + Subcommands: []cli.Command{ + dumpCfgCommand, + }, + }, +} + +const ( + configFileDirFlag = "config-file-dir" +) + +var ( + defaultConfigPath = eotscfg.DefaultConfigFile +) + +var dumpCfgCommand = cli.Command{ + Name: "dump-config", + ShortName: "dc", + Usage: "Dump default configuration file.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: configFileDirFlag, + Usage: "Path to where the default config file will be dumped", + Value: defaultConfigPath, + }, + }, + Action: dumpCfg, +} + +func dumpCfg(c *cli.Context) error { + configPath := c.String(configFileDirFlag) + + if eotscfg.FileExists(configPath) { + return cli.NewExitError( + fmt.Sprintf("config already exists under provided path: %s", configPath), + 1, + ) + } + + defaultConfig := eotscfg.DefaultConfig() + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) + + if err != nil { + return err + } + + return nil +} diff --git a/eotsmanager/cmd/eotscli/main.go b/eotsmanager/cmd/eotscli/main.go new file mode 100644 index 00000000..fe31581c --- /dev/null +++ b/eotsmanager/cmd/eotscli/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "eotscli" + app.Usage = "Control plane for the EOTS Manager Daemon (eotsd)." + app.Commands = append(app.Commands, adminCommands...) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/eotsmanager/cmd/eotsd/main.go b/eotsmanager/cmd/eotsd/main.go new file mode 100644 index 00000000..e5795b57 --- /dev/null +++ b/eotsmanager/cmd/eotsd/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "fmt" + "os" + + "github.com/jessevdk/go-flags" + "github.com/lightningnetwork/lnd/signal" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" + eotsservice "github.com/babylonchain/btc-validator/eotsmanager/service" +) + +func main() { + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + cfg, cfgLogger, err := config.LoadConfig() + if err != nil { + if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { + // Print error if not due to help request. + err = fmt.Errorf("failed to load config: %w", err) + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + // Help was requested, exit normally. + os.Exit(0) + } + + eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, cfgLogger) + if err != nil { + cfgLogger.Errorf("failed to create EOTS manager: %v", err) + os.Exit(1) + } + + eotsServer := eotsservice.NewEOTSManagerServer(cfg, cfgLogger, eotsManager, shutdownInterceptor) + + if err := eotsServer.RunUntilShutdown(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 3760ff11..088c2c8e 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -1,55 +1,272 @@ package config -import "fmt" +import ( + "fmt" + "io" + "net" + "os" + "os/user" + "path/filepath" + "strconv" + "strings" + + "github.com/btcsuite/btcd/btcutil" + "github.com/jessevdk/go-flags" + "github.com/sirupsen/logrus" +) const ( - TypeLocal = "local" + defaultLogLevel = "debug" + defaultDataDirname = "data" + defaultLogDirname = "logs" + defaultLogFilename = "eotsd.log" + defaultConfigFileName = "eotsd.conf" + DefaultRPCPort = 15813 + defaultKeyringBackend = "test" +) - DefaultDBBackend = "bbolt" - DefaultDBPath = "bbolt-eots.db" - DefaultDBName = "eots-default" - DefaultKeyringBackend = "test" - DefaultMode = TypeLocal +var ( + // C:\Users\\AppData\Local\ on Windows + // ~/.vald on Linux + // ~/Library/Application Support/Eotsd on MacOS + DefaultEOTSDir = btcutil.AppDataDir("eotsd", false) + + DefaultConfigFile = filepath.Join(DefaultEOTSDir, defaultConfigFileName) + + defaultDataDir = filepath.Join(DefaultEOTSDir, defaultDataDirname) + defaultLogDir = filepath.Join(DefaultEOTSDir, defaultLogDirname) + defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) ) type Config struct { - Mode string `long:"mode" description:"Indicates in which mode the EOTS manager is running"` - DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` - DBPath string `long:"dbpath" description:"The path that stores the database file"` - DBName string `long:"dbname" description:"The name of the database"` + LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` + EOTSDir string `long:"workdir" description:"The base directory that contains the EOTS manager's data, logs, configuration file, etc."` + ConfigFile string `long:"configfile" description:"Path to configuration file"` + DataDir string `long:"datadir" description:"The directory to store validator's data within"` + LogDir string `long:"logdir" description:"Directory to log output."` + DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` KeyDirectory string `long:"key-dir" description:"Directory to store keys in"` KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` + + DatabaseConfig *DatabaseConfig + + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` +} + +// LoadConfig initializes and parses the config using a config file and command +// line options. +// +// The configuration proceeds as follows: +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options +func LoadConfig() (*Config, *logrus.Logger, error) { + // Pre-parse the command line options to pick up an alternative config + // file. + preCfg := DefaultConfig() + if _, err := flags.Parse(&preCfg); err != nil { + return nil, nil, err + } + + // If the config file path has not been modified by the user, then + // we'll use the default config file path. However, if the user has + // modified their default dir, then we should assume they intend to use + // the config file within it. + configFileDir := cleanAndExpandPath(preCfg.EOTSDir) + configFilePath := cleanAndExpandPath(preCfg.ConfigFile) + switch { + case configFileDir != DefaultEOTSDir && + configFilePath == DefaultConfigFile: + + configFilePath = filepath.Join( + configFileDir, defaultConfigFileName, + ) + + // User did specify an explicit --configfile, so we check that it does + // exist under that path to avoid surprises. + case configFilePath != DefaultConfigFile: + if !FileExists(configFilePath) { + return nil, nil, fmt.Errorf("specified config file does "+ + "not exist in %s", configFilePath) + } + } + + // Next, load any additional configuration options from the file. + var configFileError error + cfg := preCfg + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).ParseFile(configFilePath) + if err != nil { + // If it's a parsing related error, then we'll return + // immediately, otherwise we can proceed as possibly the config + // file doesn't exist which is OK. + if _, ok := err.(*flags.IniError); ok { + return nil, nil, err + } + + configFileError = err + } + + // Finally, parse the remaining command line options again to ensure + // they take precedence. + flagParser := flags.NewParser(&cfg, flags.Default) + if _, err := flagParser.Parse(); err != nil { + return nil, nil, err + } + + cfgLogger := logrus.New() + cfgLogger.Out = os.Stdout + // Make sure everything we just loaded makes sense. + if err := cfg.Validate(); err != nil { + return nil, nil, err + } + + logRuslLevel, err := logrus.ParseLevel(cfg.LogLevel) + if err != nil { + return nil, nil, err + } + + // TODO: Add log rotation + // At this point we know config is valid, create logger which also log to file + logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) + f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, nil, err + } + mw := io.MultiWriter(os.Stdout, f) + + cfgLogger.SetOutput(mw) + cfgLogger.SetLevel(logRuslLevel) + + // Warn about missing config file only after all other configuration is + // done. This prevents the warning on help messages and invalid + // options. Note this should go directly before the return. + if configFileError != nil { + cfgLogger.Warnf("%v", configFileError) + if cfg.DumpCfg { + cfgLogger.Infof("Writing configuration file to %s", configFilePath) + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).WriteFile(configFilePath, flags.IniIncludeComments|flags.IniIncludeDefaults) + if err != nil { + cfgLogger.Warnf("Error writing configuration file: %v", err) + return nil, nil, err + } + } + } + + return &cfg, cfgLogger, nil +} + +// Validate check the given configuration to be sane. This makes sure no +// illegal values or combination of values are set. All file system paths are +// normalized. The cleaned up config is returned on success. +func (cfg *Config) Validate() error { + // If the provided eotsd directory is not the default, we'll modify the + // path to all the files and directories that will live within it. + eotsdDir := cleanAndExpandPath(cfg.EOTSDir) + if eotsdDir != DefaultEOTSDir { + cfg.DataDir = filepath.Join(eotsdDir, defaultDataDirname) + cfg.LogDir = filepath.Join(eotsdDir, defaultLogDirname) + } + + makeDirectory := func(dir string) error { + err := os.MkdirAll(dir, 0700) + if err != nil { + // Show a nicer error message if it's because a symlink + // is linked to a directory that does not exist + // (probably because it's not mounted). + if e, ok := err.(*os.PathError); ok && os.IsExist(err) { + link, lerr := os.Readlink(e.Path) + if lerr == nil { + str := "is symlink %s -> %s mounted?" + err = fmt.Errorf(str, e.Path, link) + } + } + + return fmt.Errorf("failed to create eotsd directory '%s': %w", dir, err) + } + + return nil + } + + // As soon as we're done parsing configuration options, ensure all + // paths to directories and files are cleaned and expanded before + // attempting to use them later on. + cfg.DataDir = cleanAndExpandPath(cfg.DataDir) + cfg.LogDir = cleanAndExpandPath(cfg.LogDir) + + // Create the eotsd directory and all other subdirectories if they + // don't already exist. This makes sure that directory trees are also + // created for files that point to outside the eotsd dir. + dirs := []string{ + eotsdDir, cfg.DataDir, cfg.LogDir, + } + for _, dir := range dirs { + if err := makeDirectory(dir); err != nil { + return err + } + } + + _, err := logrus.ParseLevel(cfg.LogLevel) + + if err != nil { + return err + } + + _, err = net.ResolveTCPAddr("tcp", cfg.RpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) + } + + return nil } -func NewConfig(mode, backend, path, name, keyDir, keyringBackend string) (*Config, error) { - if backend != DefaultDBBackend { - return nil, fmt.Errorf("unsupported DB backend") +func FileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } } + return true +} +// cleanAndExpandPath expands environment variables and leading ~ in the +// passed path, cleans the result, and returns it. +func cleanAndExpandPath(path string) string { if path == "" { - return nil, fmt.Errorf("DB path should not be empty") + return "" } - if name == "" { - return nil, fmt.Errorf("bucket name should not be empty") + // Expand initial ~ to OS specific home directory. + if strings.HasPrefix(path, "~") { + var homeDir string + u, err := user.Current() + if err == nil { + homeDir = u.HomeDir + } else { + homeDir = os.Getenv("HOME") + } + + path = strings.Replace(path, "~", homeDir, 1) } - return &Config{ - Mode: mode, - KeyDirectory: keyDir, - DBBackend: backend, - DBPath: path, - DBName: name, - KeyringBackend: keyringBackend, - }, nil + // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, + // but the variables can still be expanded via POSIX-style $VARIABLE. + return filepath.Clean(os.ExpandEnv(path)) } -func DefaultEOTSManagerConfig() Config { +func DefaultConfig() Config { + dbCfg := DefaultDatabaseConfig() return Config{ - DBBackend: DefaultDBBackend, - DBPath: DefaultDBPath, - DBName: DefaultDBName, - KeyringBackend: DefaultKeyringBackend, - Mode: DefaultMode, + LogLevel: defaultLogLevel, + EOTSDir: DefaultEOTSDir, + ConfigFile: DefaultConfigFile, + DataDir: defaultDataDir, + LogDir: defaultLogDir, + KeyringBackend: defaultKeyringBackend, + KeyDirectory: defaultDataDir, + DatabaseConfig: &dbCfg, + RpcListener: defaultRpcListener, } } diff --git a/eotsmanager/config/db.go b/eotsmanager/config/db.go new file mode 100644 index 00000000..acaac42f --- /dev/null +++ b/eotsmanager/config/db.go @@ -0,0 +1,44 @@ +package config + +import "fmt" + +const ( + DefaultBackend = "bbolt" + DefaultDBPath = "bbolt-eots.db" + DefaultDBName = "default" +) + +type DatabaseConfig struct { + Backend string `long:"backend" description:"Possible database to choose as backend"` + Path string `long:"path" description:"The path that stores the database file"` + Name string `long:"name" description:"The name of the database"` +} + +func NewDatabaseConfig(backend string, path 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 path == "" { + return nil, fmt.Errorf("DB path should not be empty") + } + + if name == "" { + return nil, fmt.Errorf("bucket name should not be empty") + } + + return &DatabaseConfig{ + Backend: backend, + Path: path, + Name: name, + }, nil +} + +func DefaultDatabaseConfig() DatabaseConfig { + return DatabaseConfig{ + Backend: DefaultBackend, + Path: DefaultDBPath, + Name: DefaultDBName, + } +} diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index c1ade9c2..f6c6a3fe 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -1,17 +1,9 @@ package eotsmanager import ( - "fmt" - "os" - "path" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/client" - "github.com/babylonchain/btc-validator/codec" - "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/eotsmanager/local" "github.com/babylonchain/btc-validator/eotsmanager/types" ) @@ -48,25 +40,3 @@ type EOTSManager interface { Close() error } - -func NewEOTSManager(cfg *config.Config) (EOTSManager, error) { - switch cfg.Mode { - case config.TypeLocal: - keyringDir := cfg.KeyDirectory - if keyringDir == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, err - } - keyringDir = path.Join(homeDir, ".btc-validator") - } - - sdkCtx := client.Context{}. - WithCodec(codec.MakeCodec()). - WithKeyringDir(keyringDir) - - return local.NewLocalEOTSManager(sdkCtx, cfg) - default: - return nil, fmt.Errorf("unsupported EOTS manager mode") - } -} diff --git a/eotsmanager/local/eotsstore.go b/eotsmanager/eotsstore.go similarity index 91% rename from eotsmanager/local/eotsstore.go rename to eotsmanager/eotsstore.go index 574e0450..87780b92 100644 --- a/eotsmanager/local/eotsstore.go +++ b/eotsmanager/eotsstore.go @@ -1,4 +1,4 @@ -package local +package eotsmanager import ( "fmt" @@ -21,7 +21,7 @@ type EOTSStore struct { s store.Store } -func NewEOTSStore(cfg *config.Config) (*EOTSStore, error) { +func NewEOTSStore(cfg *config.DatabaseConfig) (*EOTSStore, error) { s, err := openStore(cfg) if err != nil { return nil, err @@ -108,10 +108,10 @@ func getValidatorKeyNameKey(pk []byte) []byte { return append([]byte(validatorKeyNamePrefix), pk...) } -func openStore(dbcfg *config.Config) (store.Store, error) { - switch dbcfg.DBBackend { +func openStore(dbcfg *config.DatabaseConfig) (store.Store, error) { + switch dbcfg.Backend { case "bbolt": - return store.NewBboltStore(dbcfg.DBPath, dbcfg.DBName) + return store.NewBboltStore(dbcfg.Path, dbcfg.Name) default: return nil, fmt.Errorf("unsupported database type") } diff --git a/eotsmanager/errors.go b/eotsmanager/errors.go deleted file mode 100644 index 5847d476..00000000 --- a/eotsmanager/errors.go +++ /dev/null @@ -1,8 +0,0 @@ -package eotsmanager - -import "errors" - -var ( - ErrValidatorAlreadyExisted = errors.New("the validator has already existed") - ErrSchnorrRandomnessALreadyCreated = errors.New("the Schnorr randomness has already been created") -) diff --git a/eotsmanager/local/localmanager.go b/eotsmanager/localmanager.go similarity index 88% rename from eotsmanager/local/localmanager.go rename to eotsmanager/localmanager.go index 419da5cc..265764aa 100644 --- a/eotsmanager/local/localmanager.go +++ b/eotsmanager/localmanager.go @@ -1,8 +1,10 @@ -package local +package eotsmanager import ( "fmt" "math/rand" + "os" + "path" "time" "github.com/babylonchain/babylon/crypto/eots" @@ -13,7 +15,9 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" + "github.com/sirupsen/logrus" + "github.com/babylonchain/btc-validator/codec" "github.com/babylonchain/btc-validator/eotsmanager/config" eotstypes "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/types" @@ -24,12 +28,28 @@ const ( mnemonicEntropySize = 256 ) +var _ EOTSManager = &LocalEOTSManager{} + type LocalEOTSManager struct { - kr keyring.Keyring - es *EOTSStore + kr keyring.Keyring + es *EOTSStore + logger *logrus.Logger } -func NewLocalEOTSManager(ctx client.Context, eotsCfg *config.Config) (*LocalEOTSManager, error) { +func NewLocalEOTSManager(eotsCfg *config.Config, logger *logrus.Logger) (*LocalEOTSManager, error) { + keyringDir := eotsCfg.KeyDirectory + if keyringDir == "" { + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, err + } + keyringDir = path.Join(homeDir, ".eots-manager") + } + + ctx := client.Context{}. + WithCodec(codec.MakeCodec()). + WithKeyringDir(keyringDir) + if eotsCfg.KeyringBackend == "" { return nil, fmt.Errorf("the keyring backend should not be empty") } @@ -46,14 +66,15 @@ func NewLocalEOTSManager(ctx client.Context, eotsCfg *config.Config) (*LocalEOTS return nil, fmt.Errorf("failed to create keyring: %w", err) } - es, err := NewEOTSStore(eotsCfg) + es, err := NewEOTSStore(eotsCfg.DatabaseConfig) if err != nil { return nil, fmt.Errorf("failed to open the store for validators: %w", err) } return &LocalEOTSManager{ - kr: kr, - es: es, + kr: kr, + es: es, + logger: logger, }, nil } @@ -106,6 +127,8 @@ func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { return nil, err } + lm.logger.Infof("successfully created an EOTS key %s: %s", name, eotsPk.MarshalHex()) + return eotsPk.MustMarshal(), nil } diff --git a/eotsmanager/local/localmanager_test.go b/eotsmanager/localmanager_test.go similarity index 77% rename from eotsmanager/local/localmanager_test.go rename to eotsmanager/localmanager_test.go index 74ec0165..3928a508 100644 --- a/eotsmanager/local/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -1,4 +1,4 @@ -package local_test +package eotsmanager_test import ( "math/rand" @@ -6,30 +6,30 @@ import ( "testing" "github.com/babylonchain/babylon/testutil/datagen" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/eotsmanager/local" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/testutil" ) -// FuzzCreateValidator tests the creation of validator -func FuzzCreateValidator(f *testing.F) { +// FuzzCreateKey tests the creation of an EOTS key +func FuzzCreateKey(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) valName := testutil.GenRandomHexStr(r, 4) - sdkCtx := testutil.GenSdkContext(r, t) eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { - err := os.RemoveAll(sdkCtx.KeyringDir) + err := os.RemoveAll(eotsCfg.KeyDirectory) require.NoError(t, err) - err = os.RemoveAll(eotsCfg.DBPath) + err = os.RemoveAll(eotsCfg.DatabaseConfig.Path) require.NoError(t, err) }() - lm, err := local.NewLocalEOTSManager(sdkCtx, eotsCfg) + lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, "") @@ -54,16 +54,15 @@ func FuzzCreateRandomnessPairList(f *testing.F) { r := rand.New(rand.NewSource(seed)) valName := testutil.GenRandomHexStr(r, 4) - sdkCtx := testutil.GenSdkContext(r, t) eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { - err := os.RemoveAll(sdkCtx.KeyringDir) + err := os.RemoveAll(eotsCfg.KeyDirectory) require.NoError(t, err) - err = os.RemoveAll(eotsCfg.DBPath) + err = os.RemoveAll(eotsCfg.DatabaseConfig.Path) require.NoError(t, err) }() - lm, err := local.NewLocalEOTSManager(sdkCtx, eotsCfg) + lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, "") diff --git a/eotsmanager/proto/.clang-format b/eotsmanager/proto/.clang-format new file mode 100644 index 00000000..f1914278 --- /dev/null +++ b/eotsmanager/proto/.clang-format @@ -0,0 +1,7 @@ +--- +Language: Proto +BasedOnStyle: Google +IndentWidth: 4 +AllowShortFunctionsOnASingleLine: None +SpaceBeforeParens: Always +CompactNamespaces: false diff --git a/eotsmanager/proto/buf.gen.yaml b/eotsmanager/proto/buf.gen.yaml new file mode 100644 index 00000000..7461833c --- /dev/null +++ b/eotsmanager/proto/buf.gen.yaml @@ -0,0 +1,8 @@ +version: v1 +plugins: + - plugin: go + out: . + opt: paths=source_relative + - name: go-grpc + out: . + opt: paths=source_relative diff --git a/eotsmanager/proto/buf.lock b/eotsmanager/proto/buf.lock new file mode 100644 index 00000000..c91b5810 --- /dev/null +++ b/eotsmanager/proto/buf.lock @@ -0,0 +1,2 @@ +# Generated by buf. DO NOT EDIT. +version: v1 diff --git a/eotsmanager/proto/buf.yaml b/eotsmanager/proto/buf.yaml new file mode 100644 index 00000000..5ab32f06 --- /dev/null +++ b/eotsmanager/proto/buf.yaml @@ -0,0 +1,24 @@ +version: v1 +name: buf.build/babylonchain/eotsmanager +deps: +breaking: + use: + - FILE +lint: + use: + - DEFAULT + - COMMENTS + - FILE_LOWER_SNAKE_CASE + - COMMENT_MESSAGE + - COMMENT_ENUM_VALUE + - COMMENT_ENUM + - COMMENT_RPC + - COMMENT_ONEOF + except: + - UNARY_RPC + - COMMENT_FIELD + - SERVICE_SUFFIX + - PACKAGE_VERSION_SUFFIX + - RPC_REQUEST_STANDARD_NAME + - ENUM_VALUE_PREFIX + - ENUM_ZERO_VALUE_SUFFIX diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go new file mode 100644 index 00000000..f4bba528 --- /dev/null +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -0,0 +1,861 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: eotsmanager.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CreateKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name is the identifier key in keyring + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // pass_phrase is used to encrypt the keys + PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` +} + +func (x *CreateKeyRequest) Reset() { + *x = CreateKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateKeyRequest) ProtoMessage() {} + +func (x *CreateKeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[0] + 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 CreateKeyRequest.ProtoReflect.Descriptor instead. +func (*CreateKeyRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateKeyRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreateKeyRequest) GetPassPhrase() string { + if x != nil { + return x.PassPhrase + } + return "" +} + +type CreateKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // pk is the EOTS public key following BIP-340 spec + Pk []byte `protobuf:"bytes,1,opt,name=pk,proto3" json:"pk,omitempty"` +} + +func (x *CreateKeyResponse) Reset() { + *x = CreateKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateKeyResponse) ProtoMessage() {} + +func (x *CreateKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[1] + 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 CreateKeyResponse.ProtoReflect.Descriptor instead. +func (*CreateKeyResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateKeyResponse) GetPk() []byte { + if x != nil { + return x.Pk + } + return nil +} + +type CreateRandomnessPairListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + 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"` +} + +func (x *CreateRandomnessPairListRequest) Reset() { + *x = CreateRandomnessPairListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRandomnessPairListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRandomnessPairListRequest) ProtoMessage() {} + +func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[2] + 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 CreateRandomnessPairListRequest.ProtoReflect.Descriptor instead. +func (*CreateRandomnessPairListRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateRandomnessPairListRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *CreateRandomnessPairListRequest) 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 +} + +type CreateRandomnessPairListResponse 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"` +} + +func (x *CreateRandomnessPairListResponse) Reset() { + *x = CreateRandomnessPairListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRandomnessPairListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRandomnessPairListResponse) ProtoMessage() {} + +func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[3] + 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 CreateRandomnessPairListResponse.ProtoReflect.Descriptor instead. +func (*CreateRandomnessPairListResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateRandomnessPairListResponse) GetPubRandList() [][]byte { + if x != nil { + return x.PubRandList + } + return nil +} + +type KeyRecordRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // pass_phrase is used to decrypt the keys + PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` +} + +func (x *KeyRecordRequest) Reset() { + *x = KeyRecordRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyRecordRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyRecordRequest) ProtoMessage() {} + +func (x *KeyRecordRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[4] + 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 KeyRecordRequest.ProtoReflect.Descriptor instead. +func (*KeyRecordRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{4} +} + +func (x *KeyRecordRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *KeyRecordRequest) GetPassPhrase() string { + if x != nil { + return x.PassPhrase + } + return "" +} + +type KeyRecordResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name is the identifier key in keyring + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // private_key is the private EOTS key encoded in secp256k1 spec + PrivateKey []byte `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` +} + +func (x *KeyRecordResponse) Reset() { + *x = KeyRecordResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyRecordResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyRecordResponse) ProtoMessage() {} + +func (x *KeyRecordResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[5] + 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 KeyRecordResponse.ProtoReflect.Descriptor instead. +func (*KeyRecordResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{5} +} + +func (x *KeyRecordResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *KeyRecordResponse) GetPrivateKey() []byte { + if x != nil { + return x.PrivateKey + } + return nil +} + +type SignEOTSRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + 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"` + // the message which the EOTS signs + Msg []byte `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` + // the block height which the EOTS signs + Height uint64 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` +} + +func (x *SignEOTSRequest) Reset() { + *x = SignEOTSRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignEOTSRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignEOTSRequest) ProtoMessage() {} + +func (x *SignEOTSRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[6] + 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 SignEOTSRequest.ProtoReflect.Descriptor instead. +func (*SignEOTSRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{6} +} + +func (x *SignEOTSRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *SignEOTSRequest) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} + +func (x *SignEOTSRequest) GetMsg() []byte { + if x != nil { + return x.Msg + } + return nil +} + +func (x *SignEOTSRequest) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +type SignEOTSResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sig is the EOTS signature + Sig []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (x *SignEOTSResponse) Reset() { + *x = SignEOTSResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignEOTSResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignEOTSResponse) ProtoMessage() {} + +func (x *SignEOTSResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[7] + 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 SignEOTSResponse.ProtoReflect.Descriptor instead. +func (*SignEOTSResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{7} +} + +func (x *SignEOTSResponse) GetSig() []byte { + if x != nil { + return x.Sig + } + return nil +} + +type SignSchnorrSigRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // the message which the Schnorr signature signs + Msg []byte `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (x *SignSchnorrSigRequest) Reset() { + *x = SignSchnorrSigRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignSchnorrSigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignSchnorrSigRequest) ProtoMessage() {} + +func (x *SignSchnorrSigRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[8] + 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 SignSchnorrSigRequest.ProtoReflect.Descriptor instead. +func (*SignSchnorrSigRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{8} +} + +func (x *SignSchnorrSigRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *SignSchnorrSigRequest) GetMsg() []byte { + if x != nil { + return x.Msg + } + return nil +} + +type SignSchnorrSigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sig is the Schnorr signature + Sig []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (x *SignSchnorrSigResponse) Reset() { + *x = SignSchnorrSigResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignSchnorrSigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignSchnorrSigResponse) ProtoMessage() {} + +func (x *SignSchnorrSigResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[9] + 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 SignSchnorrSigResponse.ProtoReflect.Descriptor instead. +func (*SignSchnorrSigResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{9} +} + +func (x *SignSchnorrSigResponse) GetSig() []byte { + if x != nil { + return x.Sig + } + return nil +} + +var File_eotsmanager_proto protoreflect.FileDescriptor + +var file_eotsmanager_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x47, 0x0a, 0x10, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 0x68, 0x72, + 0x61, 0x73, 0x65, 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, 0x83, 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, 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, 0x45, 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, 0x1f, 0x0a, 0x0b, + 0x70, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 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, 0x68, 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, 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, 0x3b, 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, 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, 0x86, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 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, 0x39, 0x5a, 0x37, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 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 ( + file_eotsmanager_proto_rawDescOnce sync.Once + file_eotsmanager_proto_rawDescData = file_eotsmanager_proto_rawDesc +) + +func file_eotsmanager_proto_rawDescGZIP() []byte { + file_eotsmanager_proto_rawDescOnce.Do(func() { + file_eotsmanager_proto_rawDescData = protoimpl.X.CompressGZIP(file_eotsmanager_proto_rawDescData) + }) + return file_eotsmanager_proto_rawDescData +} + +var file_eotsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_eotsmanager_proto_goTypes = []interface{}{ + (*CreateKeyRequest)(nil), // 0: proto.CreateKeyRequest + (*CreateKeyResponse)(nil), // 1: proto.CreateKeyResponse + (*CreateRandomnessPairListRequest)(nil), // 2: proto.CreateRandomnessPairListRequest + (*CreateRandomnessPairListResponse)(nil), // 3: proto.CreateRandomnessPairListResponse + (*KeyRecordRequest)(nil), // 4: proto.KeyRecordRequest + (*KeyRecordResponse)(nil), // 5: proto.KeyRecordResponse + (*SignEOTSRequest)(nil), // 6: proto.SignEOTSRequest + (*SignEOTSResponse)(nil), // 7: proto.SignEOTSResponse + (*SignSchnorrSigRequest)(nil), // 8: proto.SignSchnorrSigRequest + (*SignSchnorrSigResponse)(nil), // 9: proto.SignSchnorrSigResponse +} +var file_eotsmanager_proto_depIdxs = []int32{ + 0, // 0: proto.EOTSManager.CreateKey:input_type -> proto.CreateKeyRequest + 2, // 1: proto.EOTSManager.CreateRandomnessPairList:input_type -> proto.CreateRandomnessPairListRequest + 4, // 2: proto.EOTSManager.KeyRecord:input_type -> proto.KeyRecordRequest + 6, // 3: proto.EOTSManager.SignEOTS:input_type -> proto.SignEOTSRequest + 8, // 4: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest + 1, // 5: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse + 3, // 6: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse + 5, // 7: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse + 7, // 8: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse + 9, // 9: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse + 5, // [5:10] is the sub-list for method output_type + 0, // [0:5] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_eotsmanager_proto_init() } +func file_eotsmanager_proto_init() { + if File_eotsmanager_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_eotsmanager_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRandomnessPairListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRandomnessPairListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KeyRecordRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KeyRecordResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignEOTSRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignEOTSResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignSchnorrSigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignSchnorrSigResponse); 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{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_eotsmanager_proto_rawDesc, + NumEnums: 0, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_eotsmanager_proto_goTypes, + DependencyIndexes: file_eotsmanager_proto_depIdxs, + MessageInfos: file_eotsmanager_proto_msgTypes, + }.Build() + File_eotsmanager_proto = out.File + file_eotsmanager_proto_rawDesc = nil + file_eotsmanager_proto_goTypes = nil + file_eotsmanager_proto_depIdxs = nil +} diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto new file mode 100644 index 00000000..bf9af3d7 --- /dev/null +++ b/eotsmanager/proto/eotsmanager.proto @@ -0,0 +1,97 @@ +syntax = "proto3"; + +package proto; + +option go_package = "github.com/babylonchain/btc-validator/eotsmanager/proto"; + +service EOTSManager { + // CreateKey generates and saves an EOTS key + rpc CreateKey (CreateKeyRequest) + returns (CreateKeyResponse); + + // CreateRandomnessPairList returns a list of Schnorr randomness pairs + rpc CreateRandomnessPairList (CreateRandomnessPairListRequest) + returns (CreateRandomnessPairListResponse); + + // KeyRecord returns the key record + rpc KeyRecord(KeyRecordRequest) + returns (KeyRecordResponse); + + // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness + rpc SignEOTS (SignEOTSRequest) + returns (SignEOTSResponse); + + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + rpc SignSchnorrSig (SignSchnorrSigRequest) + returns (SignSchnorrSigResponse); +} + +message CreateKeyRequest { + // name is the identifier key in keyring + string name = 1; + // pass_phrase is used to encrypt the keys + string pass_phrase = 2; +} + +message CreateKeyResponse { + // pk is the EOTS public key following BIP-340 spec + bytes pk = 1; +} + +message CreateRandomnessPairListRequest { + // 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; +} + +message CreateRandomnessPairListResponse { + // pub_rand_list is a list of Schnorr public randomness + repeated bytes pub_rand_list = 1; +} + +message KeyRecordRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // pass_phrase is used to decrypt the keys + string pass_phrase = 2; +} + +message KeyRecordResponse { + // name is the identifier key in keyring + string name = 1; + // private_key is the private EOTS key encoded in secp256k1 spec + bytes private_key = 2; +} + +message SignEOTSRequest { + // 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; + // the message which the EOTS signs + bytes msg = 3; + // the block height which the EOTS signs + uint64 height = 4; +} + +message SignEOTSResponse { + // sig is the EOTS signature + bytes sig = 1; +} + +message SignSchnorrSigRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // the message which the Schnorr signature signs + bytes msg = 2; +} + +message SignSchnorrSigResponse { + // sig is the Schnorr signature + bytes sig = 1; +} diff --git a/eotsmanager/proto/eotsmanager_grpc.pb.go b/eotsmanager/proto/eotsmanager_grpc.pb.go new file mode 100644 index 00000000..876dfcb4 --- /dev/null +++ b/eotsmanager/proto/eotsmanager_grpc.pb.go @@ -0,0 +1,267 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: eotsmanager.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + 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" +) + +// EOTSManagerClient is the client API for EOTSManager service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type EOTSManagerClient interface { + // 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) + // 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 + SignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) +} + +type eOTSManagerClient struct { + cc grpc.ClientConnInterface +} + +func NewEOTSManagerClient(cc grpc.ClientConnInterface) EOTSManagerClient { + return &eOTSManagerClient{cc} +} + +func (c *eOTSManagerClient) CreateKey(ctx context.Context, in *CreateKeyRequest, opts ...grpc.CallOption) (*CreateKeyResponse, error) { + out := new(CreateKeyResponse) + err := c.cc.Invoke(ctx, EOTSManager_CreateKey_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + 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...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) KeyRecord(ctx context.Context, in *KeyRecordRequest, opts ...grpc.CallOption) (*KeyRecordResponse, error) { + out := new(KeyRecordResponse) + err := c.cc.Invoke(ctx, EOTSManager_KeyRecord_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) SignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) { + out := new(SignEOTSResponse) + err := c.cc.Invoke(ctx, EOTSManager_SignEOTS_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) { + out := new(SignSchnorrSigResponse) + err := c.cc.Invoke(ctx, EOTSManager_SignSchnorrSig_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// EOTSManagerServer is the server API for EOTSManager service. +// All implementations must embed UnimplementedEOTSManagerServer +// for forward compatibility +type EOTSManagerServer interface { + // 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) + // KeyRecord returns the key record + KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) + // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness + SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) + mustEmbedUnimplementedEOTSManagerServer() +} + +// UnimplementedEOTSManagerServer must be embedded to have forward compatible implementations. +type UnimplementedEOTSManagerServer struct { +} + +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) KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method KeyRecord not implemented") +} +func (UnimplementedEOTSManagerServer) SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignEOTS not implemented") +} +func (UnimplementedEOTSManagerServer) SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignSchnorrSig not implemented") +} +func (UnimplementedEOTSManagerServer) mustEmbedUnimplementedEOTSManagerServer() {} + +// UnsafeEOTSManagerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to EOTSManagerServer will +// result in compilation errors. +type UnsafeEOTSManagerServer interface { + mustEmbedUnimplementedEOTSManagerServer() +} + +func RegisterEOTSManagerServer(s grpc.ServiceRegistrar, srv EOTSManagerServer) { + s.RegisterService(&EOTSManager_ServiceDesc, srv) +} + +func _EOTSManager_CreateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).CreateKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_CreateKey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).CreateKey(ctx, req.(*CreateKeyRequest)) + } + 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) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_CreateRandomnessPairList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, req.(*CreateRandomnessPairListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_KeyRecord_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyRecordRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).KeyRecord(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_KeyRecord_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).KeyRecord(ctx, req.(*KeyRecordRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_SignEOTS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignEOTSRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).SignEOTS(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_SignEOTS_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).SignEOTS(ctx, req.(*SignEOTSRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_SignSchnorrSig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignSchnorrSigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).SignSchnorrSig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_SignSchnorrSig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).SignSchnorrSig(ctx, req.(*SignSchnorrSigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// EOTSManager_ServiceDesc is the grpc.ServiceDesc for EOTSManager service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var EOTSManager_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.EOTSManager", + HandlerType: (*EOTSManagerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateKey", + Handler: _EOTSManager_CreateKey_Handler, + }, + { + MethodName: "CreateRandomnessPairList", + Handler: _EOTSManager_CreateRandomnessPairList_Handler, + }, + { + MethodName: "KeyRecord", + Handler: _EOTSManager_KeyRecord_Handler, + }, + { + MethodName: "SignEOTS", + Handler: _EOTSManager_SignEOTS_Handler, + }, + { + MethodName: "SignSchnorrSig", + Handler: _EOTSManager_SignSchnorrSig_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "eotsmanager.proto", +} diff --git a/eotsmanager/proto/scripts/protocgen.sh b/eotsmanager/proto/scripts/protocgen.sh new file mode 100755 index 00000000..6132eed1 --- /dev/null +++ b/eotsmanager/proto/scripts/protocgen.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -eo pipefail + +cd proto +buf mod update +buf generate . +cd .. + +go mod tidy -compat=1.20 diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go new file mode 100644 index 00000000..126ff393 --- /dev/null +++ b/eotsmanager/service/rpcserver.go @@ -0,0 +1,112 @@ +package service + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/proto" +) + +// rpcServer is the main RPC server for the BTC-Validator daemon that handles +// gRPC incoming requests. +type rpcServer struct { + proto.UnimplementedEOTSManagerServer + + em eotsmanager.EOTSManager +} + +// newRPCServer creates a new RPC sever from the set of input dependencies. +func newRPCServer( + em eotsmanager.EOTSManager, +) *rpcServer { + + return &rpcServer{ + em: em, + } +} + +// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC +// server. +func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { + // Register the main RPC server. + proto.RegisterEOTSManagerServer(grpcServer, r) + return nil +} + +// CreateKey generates and saves an EOTS key +func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) ( + *proto.CreateKeyResponse, error) { + + pk, err := r.em.CreateKey(req.Name, req.PassPhrase) + + if err != nil { + return nil, err + } + + 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) + + 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, + }, nil +} + +// KeyRecord returns the key record +func (r *rpcServer) KeyRecord(ctx context.Context, req *proto.KeyRecordRequest) ( + *proto.KeyRecordResponse, error) { + + record, err := r.em.KeyRecord(req.Uid, req.PassPhrase) + if err != nil { + return nil, err + } + + res := &proto.KeyRecordResponse{ + Name: record.Name, + PrivateKey: record.PrivKey.Serialize(), + } + + return res, nil +} + +// SignEOTS signs an EOTS with the EOTS private key and the relevant randomness +func (r *rpcServer) SignEOTS(ctx context.Context, req *proto.SignEOTSRequest) ( + *proto.SignEOTSResponse, error) { + + sig, err := r.em.SignEOTS(req.Uid, req.ChainId, req.Msg, req.Height) + if err != nil { + return nil, err + } + + sigBytes := sig.Bytes() + + return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil +} + +// SignSchnorrSig signs a Schnorr sig with the EOTS private key +func (r *rpcServer) SignSchnorrSig(ctx context.Context, req *proto.SignSchnorrSigRequest) ( + *proto.SignSchnorrSigResponse, error) { + + sig, err := r.em.SignSchnorrSig(req.Uid, req.Msg) + if err != nil { + return nil, err + } + + return &proto.SignSchnorrSigResponse{Sig: sig.Serialize()}, nil +} diff --git a/eotsmanager/service/server.go b/eotsmanager/service/server.go new file mode 100644 index 00000000..1098e9de --- /dev/null +++ b/eotsmanager/service/server.go @@ -0,0 +1,109 @@ +package service + +import ( + "fmt" + "net" + "sync" + "sync/atomic" + + "github.com/lightningnetwork/lnd/signal" + "github.com/sirupsen/logrus" + "google.golang.org/grpc" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" +) + +// Server is the main daemon construct for the EOTS manager server. It handles +// spinning up the RPC sever, the database, and any other components that the +// EOTS manager server needs to function. +type Server struct { + started int32 + + cfg *config.Config + logger *logrus.Logger + + rpcServer *rpcServer + interceptor signal.Interceptor + + quit chan struct{} +} + +// NewEOTSManagerServer creates a new server with the given config. +func NewEOTSManagerServer(cfg *config.Config, l *logrus.Logger, em eotsmanager.EOTSManager, sig signal.Interceptor) *Server { + return &Server{ + cfg: cfg, + logger: l, + rpcServer: newRPCServer(em), + interceptor: sig, + quit: make(chan struct{}, 1), + } +} + +// RunUntilShutdown runs the main EOTS manager server loop until a signal is +// received to shut down the process. +func (s *Server) RunUntilShutdown() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + + defer func() { + s.logger.Info("Shutdown complete") + }() + + listenAddr := s.cfg.RpcListener + // we create listeners from the RPCListeners defined + // in the config. + lis, err := net.Listen("tcp", listenAddr) + if err != nil { + return fmt.Errorf("failed to listen on %s: %w", listenAddr, err) + } + defer lis.Close() + + grpcServer := grpc.NewServer() + defer grpcServer.Stop() + + if err := s.rpcServer.RegisterWithGrpcServer(grpcServer); err != nil { + return fmt.Errorf("failed to register gRPC server: %w", err) + } + + // All the necessary components have been registered, so we can + // actually start listening for requests. + if err := s.startGrpcListen(grpcServer, []net.Listener{lis}); err != nil { + return fmt.Errorf("failed to start gRPC listener: %v", err) + } + + s.logger.Infof("EOTS Manager Daemon is fully active!") + + // Wait for shutdown signal from either a graceful server stop or from + // the interrupt handler. + <-s.interceptor.ShutdownChannel() + + return nil +} + +// startGrpcListen starts the GRPC server on the passed listeners. +func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listener) error { + + // Use a WaitGroup so we can be sure the instructions on how to input the + // password is the last thing to be printed to the console. + var wg sync.WaitGroup + + for _, lis := range listeners { + wg.Add(1) + go func(lis net.Listener) { + s.logger.Infof("RPC server listening on %s", lis.Addr()) + + // Close the ready chan to indicate we are listening. + defer lis.Close() + + wg.Done() + _ = grpcServer.Serve(lis) + }(lis) + } + + // Wait for gRPC servers to be up running. + wg.Wait() + + return nil +} diff --git a/go.mod b/go.mod index 54f09d55..2056bd68 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 github.com/cometbft/cometbft v0.37.2 github.com/cosmos/cosmos-proto v1.0.0-beta.2 github.com/cosmos/cosmos-sdk v0.47.3 @@ -63,6 +62,7 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect github.com/btcsuite/btcd/btcutil/psbt v1.1.8 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13 // indirect github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect diff --git a/itest/test_manager.go b/itest/test_manager.go index 38f64ed3..c04fef4b 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -83,10 +83,10 @@ func StartManager(t *testing.T, isJury bool) *TestManager { bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(cfg) + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(cfg) require.NoError(t, err) - em, err := eotsmanager.NewEOTSManager(eotsCfg) + em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) valApp, err := service.NewValidatorApp(cfg, bc, em, logger) diff --git a/service/app.go b/service/app.go index a5b66c3e..4d052ab5 100644 --- a/service/app.go +++ b/service/app.go @@ -15,6 +15,7 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/client" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/valcfg" @@ -57,13 +58,27 @@ func NewValidatorAppFromConfig( return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) } - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(config) - if err != nil { - return nil, err - } - em, err := eotsmanager.NewEOTSManager(eotsCfg) - if err != nil { - return nil, fmt.Errorf("failed to create EOTS manager: %w", err) + // if the EOTSManagerAddress is empty, run a local EOTS manager; + // otherwise connect a remote one with a gRPC client + var em eotsmanager.EOTSManager + if config.EOTSManagerAddress == "" { + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(config) + if err != nil { + return nil, err + } + em, err = eotsmanager.NewLocalEOTSManager(eotsCfg, logger) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager locally: %w", err) + } + + logger.Info("running EOTS manager locally") + } else { + em, err = client.NewEOTSManagerGRpcClient(config.EOTSManagerAddress) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) + } + // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy + logger.Infof("successfully connected to a remote EOTS manager at %s", config.EOTSManagerAddress) } return NewValidatorApp(config, cc, em, logger) diff --git a/service/app_test.go b/service/app_test.go index b95c2c8f..28a4669a 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -46,11 +46,12 @@ func FuzzRegisterValidator(f *testing.F) { currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) - em, err := eotsmanager.NewEOTSManager(eotsCfg) + logger := logrus.New() + em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) - app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) + app, err := service.NewValidatorApp(&cfg, mockClientController, em, logger) require.NoError(t, err) err = app.Start() @@ -115,9 +116,10 @@ func FuzzAddJurySig(f *testing.F) { finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) - em, err := eotsmanager.NewEOTSManager(eotsCfg) + logger := logrus.New() + em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) require.NoError(t, err) diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go index 7ab54f09..ed19f3a9 100644 --- a/service/validator_instance_test.go +++ b/service/validator_instance_test.go @@ -110,9 +110,9 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli cfg.ValidatorModeConfig.AutoChainScanningMode = false cfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight logger := logrus.New() - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) - em, err := eotsmanager.NewEOTSManager(eotsCfg) + em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) app, err := service.NewValidatorApp(&cfg, cc, em, logger) require.NoError(t, err) diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index c117c994..10b8b97f 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -109,9 +109,9 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c valStore, err := val.NewValidatorStore(cfg.DatabaseConfig) require.NoError(t, err) - eotsCfg, err := valcfg.AppConfigToEOTSManagerConfig(&cfg) + eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) - em, err := eotsmanager.NewEOTSManager(eotsCfg) + em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) vm, err := service.NewValidatorManager(valStore, &cfg, cc, em, logger) diff --git a/testutil/datagen.go b/testutil/datagen.go index 2b50a7ed..2ec5cace 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -112,15 +112,13 @@ func GenEOTSConfig(r *rand.Rand, t *testing.T) *config.Config { bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" dir := t.TempDir() path := filepath.Join(dir, bucketName) - eotsCfg, err := config.NewConfig( - "local", - "bbolt", - path, - bucketName, - dir, - "test", - ) + dbCfg, err := config.NewDatabaseConfig("bbolt", path, bucketName) require.NoError(t, err) + eotsCfg := &config.Config{ + KeyDirectory: dir, + KeyringBackend: "test", + DatabaseConfig: dbCfg, + } return eotsCfg } diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index acd6fe0c..286e0e16 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -7,9 +7,10 @@ import ( "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/eotsmanager/local" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/val" ) @@ -28,11 +29,13 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) cfg := testutil.GenEOTSConfig(r, t) - em, err := local.NewLocalEOTSManager(sdkCtx, cfg) + em, err := eotsmanager.NewLocalEOTSManager(cfg, logrus.New()) defer func() { err := os.RemoveAll(sdkCtx.KeyringDir) require.NoError(t, err) - err = os.RemoveAll(cfg.DBPath) + err = os.RemoveAll(cfg.KeyringBackend) + require.NoError(t, err) + err = os.RemoveAll(cfg.DatabaseConfig.Path) require.NoError(t, err) }() diff --git a/valcfg/config.go b/valcfg/config.go index 723e750a..0ba130e1 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -16,6 +16,8 @@ import ( "github.com/jessevdk/go-flags" "github.com/lightningnetwork/lnd/lncfg" "github.com/sirupsen/logrus" + + eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" ) const ( @@ -48,9 +50,10 @@ var ( DefaultConfigFile = filepath.Join(DefaultValdDir, defaultConfigFileName) - defaultDataDir = filepath.Join(DefaultValdDir, defaultDataDirname) - defaultLogDir = filepath.Join(DefaultValdDir, defaultLogDirname) - defaultActiveNetParams = chaincfg.SimNetParams + defaultDataDir = filepath.Join(DefaultValdDir, defaultDataDirname) + defaultLogDir = filepath.Join(DefaultValdDir, defaultLogDirname) + defaultActiveNetParams = chaincfg.SimNetParams + defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) ) // Config is the main config for the vald cli command @@ -74,6 +77,7 @@ type Config struct { FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"` FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` + EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` @@ -131,6 +135,7 @@ func DefaultConfig() Config { MaxSubmissionRetries: defaultMaxSubmissionRetries, BitcoinNetwork: defaultBitcoinNetwork, ActiveNetParams: defaultActiveNetParams, + EOTSManagerAddress: defaultEOTSManagerAddress, } } @@ -146,6 +151,25 @@ func (u *usageError) Error() string { return u.err.Error() } +func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) { + dbCfg, err := eotscfg.NewDatabaseConfig( + appCfg.EOTSManagerConfig.DBBackend, + appCfg.EOTSManagerConfig.DBPath, + appCfg.EOTSManagerConfig.DBName, + ) + if err != nil { + return nil, err + } + return &eotscfg.Config{ + LogLevel: appCfg.DebugLevel, + EOTSDir: appCfg.ValdDir, + ConfigFile: appCfg.ConfigFile, + KeyDirectory: appCfg.BabylonConfig.KeyDirectory, + KeyringBackend: appCfg.BabylonConfig.KeyringBackend, + DatabaseConfig: dbCfg, + }, nil +} + // LoadConfig initializes and parses the config using a config file and command // line options. // diff --git a/valcfg/eotsmanager.go b/valcfg/eotsmanager.go index 5cc2a527..a73ca77e 100644 --- a/valcfg/eotsmanager.go +++ b/valcfg/eotsmanager.go @@ -1,61 +1,21 @@ package valcfg -import ( - "fmt" - - "github.com/babylonchain/btc-validator/eotsmanager/config" -) - const ( DefaultEOTSManagerDBBackend = "bbolt" DefaultEOTSManagerDBPath = "bbolt-eots.db" DefaultEOTSManagerDBName = "eots-default" - DefaultEOTSManagerMode = "local" ) type EOTSManagerConfig struct { - Mode string `long:"mode" description:"Indicates in which mode the EOTS manager is running" choice:"local" choice:"remote"` DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` DBPath string `long:"dbpath" description:"The path that stores the database file"` DBName string `long:"dbname" description:"The name of the database"` } -func NewEOTSManagerConfig(backend string, path string, name string) (*EOTSManagerConfig, error) { - if backend != DefaultEOTSManagerDBBackend { - return nil, fmt.Errorf("unsupported DB backend") - } - - if path == "" { - return nil, fmt.Errorf("DB path should not be empty") - } - - if name == "" { - return nil, fmt.Errorf("bucket name should not be empty") - } - - return &EOTSManagerConfig{ - DBBackend: backend, - DBPath: path, - DBName: name, - }, nil -} - -func AppConfigToEOTSManagerConfig(appCfg *Config) (*config.Config, error) { - return config.NewConfig( - appCfg.EOTSManagerConfig.Mode, - appCfg.EOTSManagerConfig.DBBackend, - appCfg.EOTSManagerConfig.DBPath, - appCfg.EOTSManagerConfig.DBName, - appCfg.BabylonConfig.KeyDirectory, - appCfg.BabylonConfig.KeyringBackend, - ) -} - func DefaultEOTSManagerConfig() EOTSManagerConfig { return EOTSManagerConfig{ DBBackend: DefaultEOTSManagerDBBackend, DBPath: DefaultEOTSManagerDBPath, DBName: DefaultEOTSManagerDBName, - Mode: DefaultEOTSManagerMode, } } From bdf5a69bfc153b77cb2bf584a21e8ac13987e7b5 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 18 Oct 2023 18:14:04 +0800 Subject: [PATCH 07/66] chore: Add e2e tests for EOTS manager server (#123) --- clientcontroller/babylon.go | 20 ++ eotsmanager/client/rpcclient.go | 19 +- eotsmanager/proto/eotsmanager.pb.go | 333 +++++++++++++++-------- eotsmanager/proto/eotsmanager.proto | 6 + eotsmanager/proto/eotsmanager_grpc.pb.go | 37 +++ eotsmanager/service/rpcserver.go | 4 + itest/babylon_node_handler.go | 19 +- itest/e2e_test.go | 22 +- itest/eotsmanager_handler.go | 53 ++++ itest/test_manager.go | 117 ++++++-- itest/utils.go | 20 ++ 11 files changed, 485 insertions(+), 165 deletions(-) create mode 100644 itest/eotsmanager_handler.go create mode 100644 itest/utils.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index c2688b4b..5b472189 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -716,6 +716,26 @@ func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP ) } +func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { + ctx, cancel := getContextWithCancel(bc.timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := finalitytypes.NewQueryClient(clientCtx) + + // query all the unsigned delegations + queryRequest := &finalitytypes.QueryVotesAtHeightRequest{ + Height: height, + } + res, err := queryClient.VotesAtHeight(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query BTC delegations: %w", err) + } + + return res.BtcPks, nil +} + func (bc *BabylonController) QueryBTCValidatorUnbondingDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) { // TODO Check what is the order of returned delegations. Ideally we would return // delegation here from the first one which received undelegation diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 4dbac51b..13ebb49d 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -33,6 +33,17 @@ func NewEOTSManagerGRpcClient(remoteAddr string) (*EOTSManagerGRpcClient, error) }, nil } +func (c *EOTSManagerGRpcClient) Ping() error { + req := &proto.PingRequest{} + + _, err := c.client.Ping(context.Background(), req) + if err != nil { + return err + } + + return nil +} + func (c *EOTSManagerGRpcClient) CreateKey(name, passPhrase string) ([]byte, error) { req := &proto.CreateKeyRequest{Name: name, PassPhrase: passPhrase} res, err := c.client.CreateKey(context.Background(), req) @@ -57,9 +68,9 @@ func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, st pubRandFieldValList := make([]*btcec.FieldVal, 0, len(res.PubRandList)) for _, r := range res.PubRandList { - var fieldVal *btcec.FieldVal + var fieldVal btcec.FieldVal fieldVal.SetByteSlice(r) - pubRandFieldValList = append(pubRandFieldValList, fieldVal) + pubRandFieldValList = append(pubRandFieldValList, &fieldVal) } return pubRandFieldValList, nil @@ -98,10 +109,10 @@ func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64) return nil, err } - var s *btcec.ModNScalar + var s btcec.ModNScalar s.SetByteSlice(res.Sig) - return s, nil + return &s, nil } func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte) (*schnorr.Signature, error) { diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index f4bba528..5a7fd11a 100644 --- a/eotsmanager/proto/eotsmanager.pb.go +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -20,6 +20,82 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[0] + 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 PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{0} +} + +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingResponse) ProtoMessage() {} + +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[1] + 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 PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{1} +} + type CreateKeyRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -34,7 +110,7 @@ type CreateKeyRequest struct { func (x *CreateKeyRequest) Reset() { *x = CreateKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[0] + mi := &file_eotsmanager_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -47,7 +123,7 @@ func (x *CreateKeyRequest) String() string { func (*CreateKeyRequest) ProtoMessage() {} func (x *CreateKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[0] + mi := &file_eotsmanager_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -60,7 +136,7 @@ func (x *CreateKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateKeyRequest.ProtoReflect.Descriptor instead. func (*CreateKeyRequest) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{0} + return file_eotsmanager_proto_rawDescGZIP(), []int{2} } func (x *CreateKeyRequest) GetName() string { @@ -89,7 +165,7 @@ type CreateKeyResponse struct { func (x *CreateKeyResponse) Reset() { *x = CreateKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[1] + mi := &file_eotsmanager_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -102,7 +178,7 @@ func (x *CreateKeyResponse) String() string { func (*CreateKeyResponse) ProtoMessage() {} func (x *CreateKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[1] + mi := &file_eotsmanager_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -115,7 +191,7 @@ func (x *CreateKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateKeyResponse.ProtoReflect.Descriptor instead. func (*CreateKeyResponse) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{1} + return file_eotsmanager_proto_rawDescGZIP(), []int{3} } func (x *CreateKeyResponse) GetPk() []byte { @@ -143,7 +219,7 @@ type CreateRandomnessPairListRequest struct { func (x *CreateRandomnessPairListRequest) Reset() { *x = CreateRandomnessPairListRequest{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[2] + mi := &file_eotsmanager_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -156,7 +232,7 @@ func (x *CreateRandomnessPairListRequest) String() string { func (*CreateRandomnessPairListRequest) ProtoMessage() {} func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[2] + mi := &file_eotsmanager_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -169,7 +245,7 @@ func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRandomnessPairListRequest.ProtoReflect.Descriptor instead. func (*CreateRandomnessPairListRequest) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{2} + return file_eotsmanager_proto_rawDescGZIP(), []int{4} } func (x *CreateRandomnessPairListRequest) GetUid() []byte { @@ -212,7 +288,7 @@ type CreateRandomnessPairListResponse struct { func (x *CreateRandomnessPairListResponse) Reset() { *x = CreateRandomnessPairListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[3] + mi := &file_eotsmanager_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -225,7 +301,7 @@ func (x *CreateRandomnessPairListResponse) String() string { func (*CreateRandomnessPairListResponse) ProtoMessage() {} func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[3] + mi := &file_eotsmanager_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -238,7 +314,7 @@ func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRandomnessPairListResponse.ProtoReflect.Descriptor instead. func (*CreateRandomnessPairListResponse) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{3} + return file_eotsmanager_proto_rawDescGZIP(), []int{5} } func (x *CreateRandomnessPairListResponse) GetPubRandList() [][]byte { @@ -262,7 +338,7 @@ type KeyRecordRequest struct { func (x *KeyRecordRequest) Reset() { *x = KeyRecordRequest{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[4] + mi := &file_eotsmanager_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -275,7 +351,7 @@ func (x *KeyRecordRequest) String() string { func (*KeyRecordRequest) ProtoMessage() {} func (x *KeyRecordRequest) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[4] + mi := &file_eotsmanager_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -288,7 +364,7 @@ func (x *KeyRecordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use KeyRecordRequest.ProtoReflect.Descriptor instead. func (*KeyRecordRequest) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{4} + return file_eotsmanager_proto_rawDescGZIP(), []int{6} } func (x *KeyRecordRequest) GetUid() []byte { @@ -319,7 +395,7 @@ type KeyRecordResponse struct { func (x *KeyRecordResponse) Reset() { *x = KeyRecordResponse{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[5] + mi := &file_eotsmanager_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -332,7 +408,7 @@ func (x *KeyRecordResponse) String() string { func (*KeyRecordResponse) ProtoMessage() {} func (x *KeyRecordResponse) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[5] + mi := &file_eotsmanager_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -345,7 +421,7 @@ func (x *KeyRecordResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use KeyRecordResponse.ProtoReflect.Descriptor instead. func (*KeyRecordResponse) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{5} + return file_eotsmanager_proto_rawDescGZIP(), []int{7} } func (x *KeyRecordResponse) GetName() string { @@ -380,7 +456,7 @@ type SignEOTSRequest struct { func (x *SignEOTSRequest) Reset() { *x = SignEOTSRequest{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[6] + mi := &file_eotsmanager_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -393,7 +469,7 @@ func (x *SignEOTSRequest) String() string { func (*SignEOTSRequest) ProtoMessage() {} func (x *SignEOTSRequest) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[6] + mi := &file_eotsmanager_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -406,7 +482,7 @@ func (x *SignEOTSRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SignEOTSRequest.ProtoReflect.Descriptor instead. func (*SignEOTSRequest) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{6} + return file_eotsmanager_proto_rawDescGZIP(), []int{8} } func (x *SignEOTSRequest) GetUid() []byte { @@ -449,7 +525,7 @@ type SignEOTSResponse struct { func (x *SignEOTSResponse) Reset() { *x = SignEOTSResponse{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[7] + mi := &file_eotsmanager_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -462,7 +538,7 @@ func (x *SignEOTSResponse) String() string { func (*SignEOTSResponse) ProtoMessage() {} func (x *SignEOTSResponse) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[7] + mi := &file_eotsmanager_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -475,7 +551,7 @@ func (x *SignEOTSResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SignEOTSResponse.ProtoReflect.Descriptor instead. func (*SignEOTSResponse) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{7} + return file_eotsmanager_proto_rawDescGZIP(), []int{9} } func (x *SignEOTSResponse) GetSig() []byte { @@ -499,7 +575,7 @@ type SignSchnorrSigRequest struct { func (x *SignSchnorrSigRequest) Reset() { *x = SignSchnorrSigRequest{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[8] + mi := &file_eotsmanager_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -512,7 +588,7 @@ func (x *SignSchnorrSigRequest) String() string { func (*SignSchnorrSigRequest) ProtoMessage() {} func (x *SignSchnorrSigRequest) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[8] + mi := &file_eotsmanager_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -525,7 +601,7 @@ func (x *SignSchnorrSigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SignSchnorrSigRequest.ProtoReflect.Descriptor instead. func (*SignSchnorrSigRequest) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{8} + return file_eotsmanager_proto_rawDescGZIP(), []int{10} } func (x *SignSchnorrSigRequest) GetUid() []byte { @@ -554,7 +630,7 @@ type SignSchnorrSigResponse struct { func (x *SignSchnorrSigResponse) Reset() { *x = SignSchnorrSigResponse{} if protoimpl.UnsafeEnabled { - mi := &file_eotsmanager_proto_msgTypes[9] + mi := &file_eotsmanager_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -567,7 +643,7 @@ func (x *SignSchnorrSigResponse) String() string { func (*SignSchnorrSigResponse) ProtoMessage() {} func (x *SignSchnorrSigResponse) ProtoReflect() protoreflect.Message { - mi := &file_eotsmanager_proto_msgTypes[9] + mi := &file_eotsmanager_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -580,7 +656,7 @@ func (x *SignSchnorrSigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SignSchnorrSigResponse.ProtoReflect.Descriptor instead. func (*SignSchnorrSigResponse) Descriptor() ([]byte, []int) { - return file_eotsmanager_proto_rawDescGZIP(), []int{9} + return file_eotsmanager_proto_rawDescGZIP(), []int{11} } func (x *SignSchnorrSigResponse) GetSig() []byte { @@ -594,52 +670,57 @@ var File_eotsmanager_proto protoreflect.FileDescriptor var file_eotsmanager_proto_rawDesc = []byte{ 0x0a, 0x11, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x47, 0x0a, 0x10, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 0x68, 0x72, - 0x61, 0x73, 0x65, 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, 0x83, 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, 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, 0x45, 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, 0x1f, 0x0a, 0x0b, - 0x70, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 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, 0x68, 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, 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, 0x3b, 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, 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, 0x86, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0d, 0x0a, 0x0b, 0x50, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 0x68, 0x72, 0x61, + 0x73, 0x65, 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, 0x83, 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, 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, 0x45, 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, 0x1f, 0x0a, 0x0b, 0x70, + 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 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, 0x68, 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, + 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, 0x3b, 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, 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, @@ -682,35 +763,39 @@ func file_eotsmanager_proto_rawDescGZIP() []byte { return file_eotsmanager_proto_rawDescData } -var file_eotsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_eotsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_eotsmanager_proto_goTypes = []interface{}{ - (*CreateKeyRequest)(nil), // 0: proto.CreateKeyRequest - (*CreateKeyResponse)(nil), // 1: proto.CreateKeyResponse - (*CreateRandomnessPairListRequest)(nil), // 2: proto.CreateRandomnessPairListRequest - (*CreateRandomnessPairListResponse)(nil), // 3: proto.CreateRandomnessPairListResponse - (*KeyRecordRequest)(nil), // 4: proto.KeyRecordRequest - (*KeyRecordResponse)(nil), // 5: proto.KeyRecordResponse - (*SignEOTSRequest)(nil), // 6: proto.SignEOTSRequest - (*SignEOTSResponse)(nil), // 7: proto.SignEOTSResponse - (*SignSchnorrSigRequest)(nil), // 8: proto.SignSchnorrSigRequest - (*SignSchnorrSigResponse)(nil), // 9: proto.SignSchnorrSigResponse + (*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 } var file_eotsmanager_proto_depIdxs = []int32{ - 0, // 0: proto.EOTSManager.CreateKey:input_type -> proto.CreateKeyRequest - 2, // 1: proto.EOTSManager.CreateRandomnessPairList:input_type -> proto.CreateRandomnessPairListRequest - 4, // 2: proto.EOTSManager.KeyRecord:input_type -> proto.KeyRecordRequest - 6, // 3: proto.EOTSManager.SignEOTS:input_type -> proto.SignEOTSRequest - 8, // 4: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest - 1, // 5: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse - 3, // 6: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse - 5, // 7: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse - 7, // 8: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse - 9, // 9: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse - 5, // [5:10] is the sub-list for method output_type - 0, // [0:5] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 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 + 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 + 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 + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_eotsmanager_proto_init() } @@ -720,7 +805,7 @@ func file_eotsmanager_proto_init() { } if !protoimpl.UnsafeEnabled { file_eotsmanager_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateKeyRequest); i { + switch v := v.(*PingRequest); i { case 0: return &v.state case 1: @@ -732,7 +817,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateKeyResponse); i { + switch v := v.(*PingResponse); i { case 0: return &v.state case 1: @@ -744,7 +829,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateRandomnessPairListRequest); i { + switch v := v.(*CreateKeyRequest); i { case 0: return &v.state case 1: @@ -756,7 +841,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateRandomnessPairListResponse); i { + switch v := v.(*CreateKeyResponse); i { case 0: return &v.state case 1: @@ -768,7 +853,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyRecordRequest); i { + switch v := v.(*CreateRandomnessPairListRequest); i { case 0: return &v.state case 1: @@ -780,7 +865,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyRecordResponse); i { + switch v := v.(*CreateRandomnessPairListResponse); i { case 0: return &v.state case 1: @@ -792,7 +877,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignEOTSRequest); i { + switch v := v.(*KeyRecordRequest); i { case 0: return &v.state case 1: @@ -804,7 +889,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignEOTSResponse); i { + switch v := v.(*KeyRecordResponse); i { case 0: return &v.state case 1: @@ -816,7 +901,7 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignSchnorrSigRequest); i { + switch v := v.(*SignEOTSRequest); i { case 0: return &v.state case 1: @@ -828,6 +913,30 @@ func file_eotsmanager_proto_init() { } } file_eotsmanager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignEOTSResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignSchnorrSigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SignSchnorrSigResponse); i { case 0: return &v.state @@ -846,7 +955,7 @@ func file_eotsmanager_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_eotsmanager_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto index bf9af3d7..29974bfc 100644 --- a/eotsmanager/proto/eotsmanager.proto +++ b/eotsmanager/proto/eotsmanager.proto @@ -5,6 +5,8 @@ package proto; option go_package = "github.com/babylonchain/btc-validator/eotsmanager/proto"; service EOTSManager { + rpc Ping (PingRequest) returns (PingResponse); + // CreateKey generates and saves an EOTS key rpc CreateKey (CreateKeyRequest) returns (CreateKeyResponse); @@ -26,6 +28,10 @@ service EOTSManager { returns (SignSchnorrSigResponse); } +message PingRequest {} + +message PingResponse {} + message CreateKeyRequest { // name is the identifier key in keyring string name = 1; diff --git a/eotsmanager/proto/eotsmanager_grpc.pb.go b/eotsmanager/proto/eotsmanager_grpc.pb.go index 876dfcb4..0a8814ad 100644 --- a/eotsmanager/proto/eotsmanager_grpc.pb.go +++ b/eotsmanager/proto/eotsmanager_grpc.pb.go @@ -19,6 +19,7 @@ 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" @@ -30,6 +31,7 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 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 @@ -50,6 +52,15 @@ func NewEOTSManagerClient(cc grpc.ClientConnInterface) EOTSManagerClient { return &eOTSManagerClient{cc} } +func (c *eOTSManagerClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, EOTSManager_Ping_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *eOTSManagerClient) CreateKey(ctx context.Context, in *CreateKeyRequest, opts ...grpc.CallOption) (*CreateKeyResponse, error) { out := new(CreateKeyResponse) err := c.cc.Invoke(ctx, EOTSManager_CreateKey_FullMethodName, in, out, opts...) @@ -99,6 +110,7 @@ func (c *eOTSManagerClient) SignSchnorrSig(ctx context.Context, in *SignSchnorrS // All implementations must embed UnimplementedEOTSManagerServer // for forward compatibility 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 @@ -116,6 +128,9 @@ type EOTSManagerServer interface { type UnimplementedEOTSManagerServer struct { } +func (UnimplementedEOTSManagerServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} func (UnimplementedEOTSManagerServer) CreateKey(context.Context, *CreateKeyRequest) (*CreateKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateKey not implemented") } @@ -144,6 +159,24 @@ func RegisterEOTSManagerServer(s grpc.ServiceRegistrar, srv EOTSManagerServer) { s.RegisterService(&EOTSManager_ServiceDesc, srv) } +func _EOTSManager_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _EOTSManager_CreateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateKeyRequest) if err := dec(in); err != nil { @@ -241,6 +274,10 @@ var EOTSManager_ServiceDesc = grpc.ServiceDesc{ ServiceName: "proto.EOTSManager", HandlerType: (*EOTSManagerServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _EOTSManager_Ping_Handler, + }, { MethodName: "CreateKey", Handler: _EOTSManager_CreateKey_Handler, diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go index 126ff393..e7b57e5d 100644 --- a/eotsmanager/service/rpcserver.go +++ b/eotsmanager/service/rpcserver.go @@ -35,6 +35,10 @@ func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { return nil } +func (r *rpcServer) Ping(ctx context.Context, req *proto.PingRequest) (*proto.PingResponse, error) { + return &proto.PingResponse{}, nil +} + // CreateKey generates and saves an EOTS key func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) ( *proto.CreateKeyResponse, error) { diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 573059cf..6c40f58b 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -18,23 +18,6 @@ import ( "github.com/babylonchain/btc-validator/val" ) -func baseDir() (string, error) { - tempPath := os.TempDir() - - tempName, err := os.MkdirTemp(tempPath, "zBabylonTest") - if err != nil { - return "", err - } - - err = os.Chmod(tempName, 0755) - - if err != nil { - return "", err - } - - return tempName, nil -} - type babylonNode struct { cmd *exec.Cmd pidFile string @@ -129,7 +112,7 @@ type BabylonNodeHandler struct { } func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { - testDir, err := baseDir() + testDir, err := baseDir("zBabylonTest") require.NoError(t, err) defer func() { if err != nil { diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 8ff9f81d..d5f590ca 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -103,8 +103,10 @@ func TestValidatorLifeCycle(t *testing.T) { dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // check there's a block finalized - _ = tm.WaitForNFinalizedBlocks(t, 1) + // check the last voted block is finalized + lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) } // TestMultipleValidators tests starting with multiple validators @@ -199,7 +201,11 @@ func TestDoubleSigning(t *testing.T) { dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // check there's a block finalized + // check the last voted block is finalized + lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) // attack: manually submit a finality vote over a conflicting block @@ -242,12 +248,16 @@ func TestFastSync(t *testing.T) { dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // check there's a block finalized + // check the last voted block is finalized + lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) n := 3 // stop the validator for a few blocks then restart to trigger the fast sync - tm.Config.FastSyncGap = uint64(n) + tm.ValConfig.FastSyncGap = uint64(n) tm.StopAndRestartValidatorAfterNBlocks(t, n, valIns) // check there are n+1 blocks finalized @@ -306,7 +316,7 @@ func TestJuryUnbondingSigSubmission(t *testing.T) { require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryBTCDelegations( btcstakingtypes.BTCDelegationStatus_PENDING, - tm.Config.JuryModeConfig.DelegationLimit, + tm.ValConfig.JuryModeConfig.DelegationLimit, ) if err != nil { return false diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go new file mode 100644 index 00000000..f6c9398b --- /dev/null +++ b/itest/eotsmanager_handler.go @@ -0,0 +1,53 @@ +package e2etest + +import ( + "os" + "testing" + + "github.com/lightningnetwork/lnd/signal" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/eotsmanager/service" +) + +type EOTSServerHandler struct { + t *testing.T + interceptor *signal.Interceptor + eotsServer *service.Server + baseDir string +} + +func NewEOTSServerHandler(t *testing.T, cfg *config.Config) *EOTSServerHandler { + shutdownInterceptor, err := signal.Intercept() + require.NoError(t, err) + + logger := logrus.New() + eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, logger) + require.NoError(t, err) + + eotsServer := service.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + + return &EOTSServerHandler{ + t: t, + eotsServer: eotsServer, + interceptor: &shutdownInterceptor, + } +} + +func (eh *EOTSServerHandler) Start() { + go eh.startServer() +} + +func (eh *EOTSServerHandler) startServer() { + err := eh.eotsServer.RunUntilShutdown() + require.NoError(eh.t, err) +} + +func (eh *EOTSServerHandler) Stop() { + eh.interceptor.RequestShutdown() + err := os.RemoveAll(eh.baseDir) + require.NoError(eh.t, err) +} diff --git a/itest/test_manager.go b/itest/test_manager.go index c04fef4b..56c0ca2c 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -27,7 +27,8 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/client" + eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" @@ -41,12 +42,14 @@ var ( var btcNetworkParams = &chaincfg.SimNetParams type TestManager struct { - Wg sync.WaitGroup - BabylonHandler *BabylonNodeHandler - Config *valcfg.Config - Va *service.ValidatorApp - Em eotsmanager.EOTSManager - BabylonClient *clientcontroller.BabylonController + Wg sync.WaitGroup + BabylonHandler *BabylonNodeHandler + EOTSServerHandler *EOTSServerHandler + ValConfig *valcfg.Config + EOTSConfig *eotsconfig.Config + Va *service.ValidatorApp + EOTSClient *client.EOTSManagerGRpcClient + BabylonClient *clientcontroller.BabylonController } type TestDelegationData struct { @@ -83,38 +86,44 @@ func StartManager(t *testing.T, isJury bool) *TestManager { bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(cfg) - require.NoError(t, err) + eotsCfg := defaultEOTSConfig(t) + + eh := NewEOTSServerHandler(t, eotsCfg) + eh.Start() - em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) + eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) - valApp, err := service.NewValidatorApp(cfg, bc, em, logger) + valApp, err := service.NewValidatorApp(cfg, bc, eotsCli, logger) require.NoError(t, err) err = valApp.Start() require.NoError(t, err) tm := &TestManager{ - BabylonHandler: bh, - Config: cfg, - Va: valApp, - Em: em, - BabylonClient: bc, + BabylonHandler: bh, + EOTSServerHandler: eh, + ValConfig: cfg, + EOTSConfig: eotsCfg, + Va: valApp, + EOTSClient: eotsCli, + BabylonClient: bc, } - tm.WaitForNodeStart(t) + tm.WaitForServicesStart(t) return tm } -func (tm *TestManager) WaitForNodeStart(t *testing.T) { - +func (tm *TestManager) WaitForServicesStart(t *testing.T) { + // wait for Babylon node starts require.Eventually(t, func() bool { _, err := tm.BabylonClient.GetStakingParams() return err == nil }, eventuallyWaitTimeOut, eventuallyPollTime) + + t.Logf("Babylon node is started") } func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { @@ -178,9 +187,12 @@ func (tm *TestManager) Stop(t *testing.T) { require.NoError(t, err) err = tm.BabylonHandler.Stop() require.NoError(t, err) - err = os.RemoveAll(tm.Config.DatabaseConfig.Path) + err = os.RemoveAll(tm.ValConfig.DatabaseConfig.Path) + require.NoError(t, err) + err = os.RemoveAll(tm.ValConfig.BabylonConfig.KeyDirectory) require.NoError(t, err) - err = os.RemoveAll(tm.Config.BabylonConfig.KeyDirectory) + tm.EOTSServerHandler.Stop() + err = os.RemoveAll(tm.EOTSServerHandler.baseDir) require.NoError(t, err) } @@ -212,7 +224,7 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryBTCDelegations( bstypes.BTCDelegationStatus_PENDING, - tm.Config.JuryModeConfig.DelegationLimit, + tm.ValConfig.JuryModeConfig.DelegationLimit, ) if err != nil { return false @@ -277,6 +289,42 @@ func CheckDelsStatus(dels []*bstypes.BTCDelegation, btcHeight uint64, w uint64, return allChecked } +func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { + // we need to ensure votes are collected at the given height + require.Eventually(t, func() bool { + votes, err := tm.BabylonClient.QueryVotesAtHeight(height) + if err != nil { + t.Logf("failed to get the votes at height %v: %s", height, err.Error()) + return false + } + return len(votes) == num + }, eventuallyWaitTimeOut, eventuallyPollTime) + + // as the votes have been collected, the block should be finalized + require.Eventually(t, func() bool { + finalized, err := tm.BabylonClient.QueryBlockFinalization(height) + if err != nil { + t.Logf("failed to query block at height %v: %s", height, err.Error()) + return false + } + return finalized + }, eventuallyWaitTimeOut, eventuallyPollTime) +} + +func (tm *TestManager) WaitForValVoteCast(t *testing.T, valIns *service.ValidatorInstance) uint64 { + var lastVotedHeight uint64 + require.Eventually(t, func() bool { + if valIns.GetLastVotedHeight() > 0 { + lastVotedHeight = valIns.GetLastVotedHeight() + return true + } else { + return false + } + }, eventuallyWaitTimeOut, eventuallyPollTime) + + return lastVotedHeight +} + func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.BlockInfo { var ( blocks []*types.BlockInfo @@ -320,7 +368,7 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, t.Log("restarting the validator instance") - tm.Config.ValidatorModeConfig.AutoChainScanningMode = true + tm.ValConfig.ValidatorModeConfig.AutoChainScanningMode = true err = valIns.Start() require.NoError(t, err) } @@ -338,7 +386,7 @@ func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegat stakingMsgTx, stakingTx.Script, juryPrivKey, - &tm.Config.ActiveNetParams, + &tm.ValConfig.ActiveNetParams, ) require.NoError(t, err) @@ -391,7 +439,7 @@ func (tm *TestManager) GetJuryPrivKey(t *testing.T) *btcec.PrivateKey { } func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { - record, err := tm.Em.KeyRecord(valPk, "") + record, err := tm.EOTSClient.KeyRecord(valPk, "") require.NoError(t, err) return record.PrivKey } @@ -553,6 +601,25 @@ func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Con return &cfg } +func defaultEOTSConfig(t *testing.T) *eotsconfig.Config { + cfg := eotsconfig.DefaultConfig() + + eotsDir, err := baseDir("zEOTSTest") + require.NoError(t, err) + + configFile := filepath.Join(eotsDir, "eotsd-test.conf") + dataDir := filepath.Join(eotsDir, "data") + logDir := filepath.Join(eotsDir, "log") + + cfg.EOTSDir = eotsDir + cfg.ConfigFile = configFile + cfg.LogDir = logDir + cfg.KeyDirectory = dataDir + cfg.DatabaseConfig.Path = filepath.Join(eotsDir, "db") + + return &cfg +} + func tempDirWithName(name string) (string, error) { tempPath := os.TempDir() diff --git a/itest/utils.go b/itest/utils.go new file mode 100644 index 00000000..ee51188a --- /dev/null +++ b/itest/utils.go @@ -0,0 +1,20 @@ +package e2etest + +import "os" + +func baseDir(pattern string) (string, error) { + tempPath := os.TempDir() + + tempName, err := os.MkdirTemp(tempPath, pattern) + if err != nil { + return "", err + } + + err = os.Chmod(tempName, 0755) + + if err != nil { + return "", err + } + + return tempName, nil +} From 118ad137c34e04843a59f56ab2d0000bc501911b Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 19 Oct 2023 14:52:15 +0800 Subject: [PATCH 08/66] chore: Remove chain-id in creating chain key (#125) --- cmd/valcli/jury.go | 1 - itest/babylon_node_handler.go | 3 +-- service/app.go | 6 +++--- service/app_test.go | 2 +- service/validator_manager_test.go | 2 +- val/keyringcontroller.go | 24 ++++++------------------ val/keyringcontroller_test.go | 2 +- 7 files changed, 13 insertions(+), 27 deletions(-) diff --git a/cmd/valcli/jury.go b/cmd/valcli/jury.go index 777ec0e5..64a32440 100644 --- a/cmd/valcli/jury.go +++ b/cmd/valcli/jury.go @@ -69,7 +69,6 @@ func createJuryKey(ctx *cli.Context) error { krController, err := val.NewChainKeyringController( sdkCtx, ctx.String(keyNameFlag), - ctx.String(chainIdFlag), ctx.String(keyringBackendFlag), ) if err != nil { diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 6c40f58b..6747e12d 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -134,7 +134,6 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { krController, err := val.NewChainKeyringController( sdkCtx, juryKeyName, - chainID, "test", ) require.NoError(t, err) @@ -208,7 +207,7 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { } func (w *BabylonNodeHandler) GetJuryKeyName() string { - return val.GetKeyName(w.babylonNode.chainID, w.babylonNode.juryKeyName) + return w.babylonNode.juryKeyName } func (w *BabylonNodeHandler) GetSlashingAddress() string { diff --git a/service/app.go b/service/app.go index 4d052ab5..8e5c5a6b 100644 --- a/service/app.go +++ b/service/app.go @@ -103,7 +103,7 @@ func NewValidatorApp( } if config.JuryMode { - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.JuryModeConfig.JuryKeyName, config.BabylonConfig.ChainID) + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.JuryModeConfig.JuryKeyName) if err != nil { return nil, err } @@ -376,7 +376,7 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio } func (app *ValidatorApp) getJuryPrivKey() (*btcec.PrivateKey, error) { - kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.JuryModeConfig.JuryKeyName, app.config.BabylonConfig.ChainID) + kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.JuryModeConfig.JuryKeyName) if err != nil { return nil, err } @@ -510,7 +510,7 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, err } - kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, req.chainID) + kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName) if err != nil { return nil, err } diff --git a/service/app_test.go b/service/app_test.go index 28a4669a..353181eb 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -125,7 +125,7 @@ func FuzzAddJurySig(f *testing.F) { require.NoError(t, err) // create a Jury key pair in the keyring - juryKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName, cfg.BabylonConfig.ChainID) + juryKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName) require.NoError(t, err) sdkJurPk, err := juryKc.CreateChainKey() require.NoError(t, err) diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index 10b8b97f..dc323efc 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -120,7 +120,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c // create registered validator keyName := datagen.GenRandomHexStr(r, 10) chainID := datagen.GenRandomHexStr(r, 10) - kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName, chainID) + kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName) require.NoError(t, err) btcPkBytes, err := em.CreateKey(keyName, "") require.NoError(t, err) diff --git a/val/keyringcontroller.go b/val/keyringcontroller.go index acb6bc4d..5be803ef 100644 --- a/val/keyringcontroller.go +++ b/val/keyringcontroller.go @@ -19,16 +19,13 @@ const ( type ChainKeyringController struct { kr keyring.Keyring valName string - chainID string } -func NewChainKeyringController(ctx client.Context, name, chainID, keyringBackend string) (*ChainKeyringController, error) { +func NewChainKeyringController(ctx client.Context, name, keyringBackend string) (*ChainKeyringController, error) { if name == "" { return nil, fmt.Errorf("the key name should not be empty") } - if chainID == "" { - return nil, fmt.Errorf("the chainID should not be empty") - } + if keyringBackend == "" { return nil, fmt.Errorf("the keyring backend should not be empty") } @@ -47,22 +44,17 @@ func NewChainKeyringController(ctx client.Context, name, chainID, keyringBackend return &ChainKeyringController{ valName: name, kr: kr, - chainID: chainID, }, nil } -func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name, chainID string) (*ChainKeyringController, error) { +func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string) (*ChainKeyringController, error) { if name == "" { return nil, fmt.Errorf("the key name should not be empty") } - if chainID == "" { - return nil, fmt.Errorf("the chainID should not be empty") - } return &ChainKeyringController{ kr: kr, valName: name, - chainID: chainID, }, nil } @@ -89,10 +81,10 @@ func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { } // TODO use a better way to remind the user to keep it - fmt.Printf("Generated mnemonic for the validator %s connected to chain %s is:\n%s\n", kc.valName, kc.chainID, mnemonic) + fmt.Printf("Generated mnemonic for the validator %s is:\n%s\n", kc.valName, mnemonic) // TODO for now we leave bip39Passphrase and hdPath empty - record, err := kc.kr.NewAccount(GetKeyName(kc.chainID, kc.valName), mnemonic, "", "", algo) + record, err := kc.kr.NewAccount(kc.valName, mnemonic, "", "", algo) if err != nil { return nil, err } @@ -110,10 +102,6 @@ func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { } } -func GetKeyName(chainID, valName string) string { - return chainID + "-" + valName -} - // CreatePop creates proof-of-possession of Babylon and BTC public keys // the input is the bytes of BTC public key used to sign // this requires both keys created beforehand @@ -127,7 +115,7 @@ func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey) (*bsty } func (kc *ChainKeyringController) GetChainPrivKey() (*secp256k1.PrivKey, error) { - k, err := kc.kr.Key(GetKeyName(kc.chainID, kc.valName)) + k, err := kc.kr.Key(kc.valName) if err != nil { return nil, fmt.Errorf("failed to get private key: %w", err) } diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index 286e0e16..c52e5fe7 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -25,7 +25,7 @@ func FuzzCreatePoP(f *testing.F) { sdkCtx := testutil.GenSdkContext(r, t) chainID := testutil.GenRandomHexStr(r, 4) - kc, err := val.NewChainKeyringController(sdkCtx, keyName, chainID, "test") + kc, err := val.NewChainKeyringController(sdkCtx, keyName, "test") require.NoError(t, err) cfg := testutil.GenEOTSConfig(r, t) From 5090eb2045bf807c273fb9978fbe6f0b5515b168 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 19 Oct 2023 15:05:45 +0800 Subject: [PATCH 09/66] chore: Add docker file to EOTS manager (#124) --- eotsmanager/Dockerfile | 57 ++++++++++++++++++++++++++++++++++++++++++ eotsmanager/Makefile | 39 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 eotsmanager/Dockerfile diff --git a/eotsmanager/Dockerfile b/eotsmanager/Dockerfile new file mode 100644 index 00000000..d9374b19 --- /dev/null +++ b/eotsmanager/Dockerfile @@ -0,0 +1,57 @@ +FROM golang:1.20.5-alpine as builder + +# Version to build. Default is the Git HEAD. +ARG VERSION="HEAD" + +# Use muslc for static libs +ARG BUILD_TAGS="muslc" + + +RUN apk add --no-cache --update openssh git make build-base linux-headers libc-dev \ + pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \ + libzmq-static libsodium-static gcc + + +RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts +RUN git config --global url."git@github.com:".insteadOf "https://github.com/" +ENV GOPRIVATE=github.com/babylonchain/babylon-private + +# Build +WORKDIR /go/src/github.com/babylonchain/eots-manager +# Cache dependencies +COPY ./../go.mod ./../go.sum /go/src/github.com/babylonchain/eots-manager/ +RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download +# Copy the rest of the files +COPY ./ /go/src/github.com/babylonchain/eots-manager/ + +# Cosmwasm - Download correct libwasmvm version +RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ + -O /lib/libwasmvm_muslc.a && \ + # verify checksum + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ + sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) + +RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ + CGO_ENABLED=1 \ + BUILD_TAGS=$BUILD_TAGS \ + LINK_STATICALLY=true \ + make build + +# FINAL IMAGE +FROM alpine:3.16 AS run + +RUN addgroup --gid 1138 -S eotsmanager && adduser --uid 1138 -S eotsmanager -G eotsmanager + +RUN apk add bash curl jq + +COPY --from=builder /go/src/github.com/babylonchain/eots-manager/build/eotsd /bin/eotsd +COPY --from=builder /go/src/github.com/babylonchain/eots-manager/build/eotscli /bin/eotscli + +WORKDIR /home/eotsmanager +RUN chown -R eotsmanager /home/eotsmanager +USER eotsmanager + +ENTRYPOINT ["/bin/eotsd"] +CMD [] +STOPSIGNAL SIGTERM diff --git a/eotsmanager/Makefile b/eotsmanager/Makefile index abc4da72..c06703af 100644 --- a/eotsmanager/Makefile +++ b/eotsmanager/Makefile @@ -1,3 +1,42 @@ +BUILDDIR ?= $(CURDIR)/build + +DOCKER := $(shell which docker) +CUR_DIR := $(shell pwd) + +ldflags := $(LDFLAGS) +build_tags := $(BUILD_TAGS) +build_args := $(BUILD_ARGS) + +ifeq ($(LINK_STATICALLY),true) + ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v +endif + +ifeq ($(VERBOSE),true) + build_args += -v +endif + +BUILD_TARGETS := build install +BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' + +all: build install + +build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) + +$(BUILD_TARGETS): go.sum $(BUILDDIR)/ + go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... + +$(BUILDDIR)/: + mkdir -p $(BUILDDIR)/ + +build-docker: + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/eots-manager -f Dockerfile \ + $(shell git rev-parse --show-toplevel) + +.PHONY: build build-docker clean + ############################################################################### ### Protobuf ### ############################################################################### From 8ceb6b659af043bf472045da19ad86f8f4a0c4f1 Mon Sep 17 00:00:00 2001 From: Filippos Malandrakis <35352222+filippos47@users.noreply.github.com> Date: Fri, 20 Oct 2023 12:34:23 +0300 Subject: [PATCH 10/66] CI: Build/push images for eotsmanager (#127) --- .circleci/config.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index cffba354..19b24a59 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -55,6 +55,14 @@ jobs: tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "$CIRCLE_PROJECT_REPONAME" extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" + - aws-ecr/build-image: + push-image: false + dockerfile: Dockerfile + path: ./eotsmanager + build-path: ./ + tag: "$CIRCLE_SHA1,$CIRCLE_TAG" + repo: "eotsmanager" + extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - run: name: Save Docker image to export it to workspace command: | @@ -84,6 +92,11 @@ jobs: region: "$AWS_REGION" repo: "$CIRCLE_PROJECT_REPONAME" tag: "$CIRCLE_SHA1,$CIRCLE_TAG" + - aws-ecr/push-image: + registry-id: AWS_ECR_REGISTRY_ID + region: "$AWS_REGION" + repo: "eotsmanager" + tag: "$CIRCLE_SHA1,$CIRCLE_TAG" workflows: CI: From a395c4e3d7b763cbea6cc762cc40dfa61221ef82 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 20 Oct 2023 18:49:49 +0800 Subject: [PATCH 11/66] chore: Bump babylon version to fix flaky issue in e2e tests (#129) --- go.mod | 2 +- go.sum | 4 ++-- tools/go.mod | 2 +- tools/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2056bd68..2616a527 100644 --- a/go.mod +++ b/go.mod @@ -303,7 +303,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index c841c93d..84646c53 100644 --- a/go.sum +++ b/go.sum @@ -269,8 +269,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231012233618-eeacd5f24308 h1:o5a+fpqjWNpZQMWE22vW8Aqj6csIlTGDp0SXH4SDyYc= -github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 h1:NvfNgjTi3FgnEAwXHAObNNZeOcYT2S/CUT+dckXz36c= +github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= diff --git a/tools/go.mod b/tools/go.mod index bb4fd595..8613266a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -179,7 +179,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 diff --git a/tools/go.sum b/tools/go.sum index 7cdc3b7a..36291e17 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -253,8 +253,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231012233618-eeacd5f24308 h1:o5a+fpqjWNpZQMWE22vW8Aqj6csIlTGDp0SXH4SDyYc= -github.com/babylonchain/babylon-private v0.0.0-20231012233618-eeacd5f24308/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 h1:NvfNgjTi3FgnEAwXHAObNNZeOcYT2S/CUT+dckXz36c= +github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= From 9ca03ec64eb64609a515d4fcddaa2ccb24ad054a Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 24 Oct 2023 10:19:52 +0800 Subject: [PATCH 12/66] Improve randomness management in the EOTS manager (#128) --- eotsmanager/client/rpcclient.go | 5 -- eotsmanager/eotsmanager.go | 7 +-- eotsmanager/eotsstore.go | 47 ---------------- eotsmanager/localmanager.go | 65 +++++----------------- eotsmanager/randgenerator/randgenerator.go | 29 ++++++++++ 5 files changed, 45 insertions(+), 108 deletions(-) create mode 100644 eotsmanager/randgenerator/randgenerator.go diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 13ebb49d..8b055128 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -76,11 +76,6 @@ func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, st return pubRandFieldValList, nil } -func (c *EOTSManagerGRpcClient) CreateRandomnessPairListWithExistenceCheck(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { - // TODO consider remove this API when we no longer store randomness - return c.CreateRandomnessPairList(uid, chainID, startHeight, num) -} - func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) { req := &proto.KeyRecordRequest{Uid: uid, PassPhrase: passPhrase} diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index f6c6a3fe..5c6b7a0a 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -13,18 +13,13 @@ type EOTSManager interface { // It fails if there is an existing key Info with the same name or public key. CreateKey(name, passPhrase string) ([]byte, error) - // CreateRandomnessPairList generates and persists a list of Schnorr randomness pairs from + // CreateRandomnessPairList generates a list of Schnorr randomness pairs from // startHeight to startHeight+(num-1)*step where step means the gap between each block height // that the validator wants to finalize and num means the number of public randomness // It fails if the validator does not exist or a randomness pair has been created before // NOTE: it will overwrite the randomness regardless of whether there's one existed CreateRandomnessPairList(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) - // CreateRandomnessPairListWithExistenceCheck checks the existence of randomness by given height - // before calling CreateRandomnessPairList. - // It fails if there's randomness existed at a given height - CreateRandomnessPairListWithExistenceCheck(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) - // KeyRecord returns the validator record // It fails if the validator does not exist or passPhrase is incorrect KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) diff --git a/eotsmanager/eotsstore.go b/eotsmanager/eotsstore.go index 87780b92..8430b247 100644 --- a/eotsmanager/eotsstore.go +++ b/eotsmanager/eotsstore.go @@ -3,17 +3,12 @@ package eotsmanager import ( "fmt" - sdktypes "github.com/cosmos/cosmos-sdk/types" - gproto "google.golang.org/protobuf/proto" - "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/eotsmanager/types" - "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/store" ) const ( - randPairPrefix = "rand-pair" validatorKeyNamePrefix = "val-key" ) @@ -52,48 +47,6 @@ func (es *EOTSStore) saveValidatorKey(pk []byte, keyName string) error { return es.s.Put(k, []byte(keyName)) } -func (es *EOTSStore) saveRandPair(pk []byte, chainID []byte, height uint64, randPair *proto.SchnorrRandPair) error { - k := getRandPairKey(pk, chainID, height) - v, err := gproto.Marshal(randPair) - if err != nil { - return fmt.Errorf("failed to marshal the Schnorr random pair: %w", err) - } - - if err := es.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the Schnorr random pair: %w", err) - } - - return nil -} - -func (es *EOTSStore) getRandPair(pk []byte, chainID []byte, height uint64) (*proto.SchnorrRandPair, error) { - k := getRandPairKey(pk, chainID, height) - v, err := es.s.Get(k) - if err != nil { - return nil, err - } - - pair := new(proto.SchnorrRandPair) - if err := gproto.Unmarshal(v, pair); err != nil { - return nil, err - } - - return pair, nil -} - -func (es *EOTSStore) randPairExists(pk []byte, chainID []byte, height uint64) (bool, error) { - k := getRandPairKey(pk, chainID, height) - return es.s.Exists(k) -} - -func getRandPairKey(pk []byte, chainID []byte, height uint64) []byte { - return append(getRandPairListKey(pk, chainID), sdktypes.Uint64ToBigEndian(height)...) -} - -func getRandPairListKey(pk []byte, chainID []byte) []byte { - return append(append([]byte(randPairPrefix), pk...), chainID...) -} - func (es *EOTSStore) getValidatorKeyName(pk []byte) (string, error) { k := getValidatorKeyNameKey(pk) v, err := es.s.Get(k) diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index 265764aa..ce75711b 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -2,10 +2,8 @@ package eotsmanager import ( "fmt" - "math/rand" "os" "path" - "time" "github.com/babylonchain/babylon/crypto/eots" bbntypes "github.com/babylonchain/babylon/types" @@ -19,8 +17,8 @@ import ( "github.com/babylonchain/btc-validator/codec" "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/eotsmanager/randgenerator" eotstypes "github.com/babylonchain/btc-validator/eotsmanager/types" - "github.com/babylonchain/btc-validator/types" ) const ( @@ -132,55 +130,28 @@ func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { return eotsPk.MustMarshal(), nil } -func (lm *LocalEOTSManager) CreateRandomnessPairListWithExistenceCheck(valPk []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { - // check whether the randomness is created already - for i := uint32(0); i < num; i++ { - height := startHeight + uint64(i) - exists, err := lm.es.randPairExists(valPk, chainID, height) - if err != nil { - return nil, err - } - if exists { - return nil, eotstypes.ErrSchnorrRandomnessAlreadyCreated - } - } - - return lm.CreateRandomnessPairList(valPk, chainID, startHeight, num) -} - +// 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 (valPk, chainID, height) or +// the hash of each generated randomness and return error if the same randomness is requested tweice func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { prList := make([]*btcec.FieldVal, 0, num) - // TODO improve the security of randomness generation if concerned - r := rand.New(rand.NewSource(time.Now().UnixNano())) - for i := uint32(0); i < num; i++ { - // generate randomness pair - eotsSR, eotsPR, err := eots.RandGen(r) - if err != nil { - return nil, fmt.Errorf("failed to generate randomness pair: %w", err) - } - - // persists randomness pair height := startHeight + uint64(i) - privRand := eotsSR.Bytes() - pubRand := eotsPR.Bytes() - randPair, err := types.NewSchnorrRandPair(privRand[:], pubRand[:]) + _, pubRand, err := lm.getRandomnessPair(valPk, chainID, height) if err != nil { - return nil, fmt.Errorf("invalid Schnorr randomness") - } - if err := lm.es.saveRandPair(valPk, chainID, height, randPair); err != nil { - return nil, fmt.Errorf("failed to save randomness pair: %w", err) + return nil, err } - prList = append(prList, eotsPR) + prList = append(prList, pubRand) } return prList, nil } func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, height uint64) (*btcec.ModNScalar, error) { - privRand, err := lm.getPrivRandomness(valPk, chainID, height) + privRand, _, err := lm.getRandomnessPair(valPk, chainID, height) if err != nil { return nil, fmt.Errorf("failed to get private randomness: %w", err) } @@ -206,20 +177,14 @@ func (lm *LocalEOTSManager) Close() error { return lm.es.Close() } -func (lm *LocalEOTSManager) getPrivRandomness(valPk []byte, chainID []byte, height uint64) (*eots.PrivateRand, error) { - randPair, err := lm.es.getRandPair(valPk, chainID, height) +// getRandomnessPair returns a randomness pair generated based on the given validator key, chainID and height +func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, height uint64) (*eots.PrivateRand, *eots.PublicRand, error) { + record, err := lm.KeyRecord(valPk, "") if err != nil { - return nil, err - } - - if len(randPair.SecRand) != types.SchnorrRandomnessLength { - return nil, fmt.Errorf("the private randomness should be 32 bytes") + return nil, nil, err } - - privRand := new(eots.PrivateRand) - privRand.SetByteSlice(randPair.SecRand) - - return privRand, nil + privRand, pubRand := randgenerator.GenerateRandomness(record.PrivKey.Serialize(), chainID, height) + return privRand, pubRand, nil } // TODO: we ignore passPhrase in local implementation for now diff --git a/eotsmanager/randgenerator/randgenerator.go b/eotsmanager/randgenerator/randgenerator.go new file mode 100644 index 00000000..570031f0 --- /dev/null +++ b/eotsmanager/randgenerator/randgenerator.go @@ -0,0 +1,29 @@ +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 +} From ee9dd6523d05dd3afa8fe3445f6d76636113df44 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 1 Nov 2023 17:18:14 +0800 Subject: [PATCH 13/66] chore: Generalize client controller (#130) --- clientcontroller/babylon.go | 735 +++++++++++++++++------------ clientcontroller/interface.go | 147 +++--- go.mod | 8 +- go.sum | 4 +- itest/e2e_test.go | 132 +----- itest/test_manager.go | 94 ++-- service/app.go | 85 +++- service/app_test.go | 46 +- service/chain_poller.go | 104 ++-- service/event_loop.go | 19 +- service/fastsync.go | 5 +- service/fastsync_test.go | 17 +- service/rpcserver.go | 4 +- service/validator_instance.go | 126 ++--- service/validator_instance_test.go | 35 +- service/validator_manager.go | 22 +- service/validator_manager_test.go | 31 +- testutil/datagen.go | 4 +- testutil/mocks/babylon.go | 524 +++++++++++++++----- testutil/utils.go | 28 +- tools/go.mod | 2 +- tools/go.sum | 4 +- types/blockinfo.go | 5 +- types/delegation.go | 59 +++ types/randpair.go | 24 - types/txresponse.go | 10 + 26 files changed, 1349 insertions(+), 925 deletions(-) create mode 100644 types/delegation.go delete mode 100644 types/randpair.go create mode 100644 types/txresponse.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 5b472189..a95699b9 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -3,12 +3,14 @@ package clientcontroller import ( "context" "fmt" + "math/big" "os" "path" "strings" "sync" "time" + "cosmossdk.io/math" "github.com/avast/retry-go/v4" bbnapp "github.com/babylonchain/babylon/app" bbntypes "github.com/babylonchain/babylon/types" @@ -16,12 +18,12 @@ import ( btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" finalitytypes "github.com/babylonchain/babylon/x/finality/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" - ctypes "github.com/cometbft/cometbft/rpc/core/types" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" - sdkTypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" sdkquery "github.com/cosmos/cosmos-sdk/types/query" sttypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -33,7 +35,7 @@ import ( "github.com/sirupsen/logrus" "go.uber.org/zap" "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" + "sigs.k8s.io/yaml" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" @@ -41,6 +43,25 @@ import ( var _ ClientController = &BabylonController{} +type StakingParams struct { + // K-deep + ComfirmationTimeBlocks uint64 + // W-deep + FinalizationTimeoutBlocks uint64 + + // Minimum amount of satoshis required for slashing transaction + MinSlashingTxFeeSat btcutil.Amount + + // Bitcoin public key of the current jury + JuryPk *btcec.PublicKey + + // Address to which slashing transactions are sent + SlashingAddress string + + // Minimum commission required by the consumer chain + MinCommissionRate string +} + type BabylonController struct { provider *cosmos.CosmosProvider logger *logrus.Logger @@ -167,7 +188,7 @@ func (bc *BabylonController) GetStakingParams() (*StakingParams, error) { MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), JuryPk: juryPk, SlashingAddress: stakingParamRes.Params.SlashingAddress, - MinCommissionRate: stakingParamRes.Params.MinCommissionRate, + MinCommissionRate: stakingParamRes.Params.MinCommissionRate.String(), }, nil } @@ -265,20 +286,31 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer // RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon // it returns tx hash and error func (bc *BabylonController) RegisterValidator( - bbnPubKey *secp256k1.PubKey, - btcPubKey *bbntypes.BIP340PubKey, - pop *btcstakingtypes.ProofOfPossession, - commission *sdkTypes.Dec, - description *sttypes.Description, -) (*provider.RelayerTxResponse, error) { + chainPk []byte, + valPk *btcec.PublicKey, + pop []byte, + commission *big.Int, + description string, +) (*types.TxResponse, error) { + var bbnPop btcstakingtypes.ProofOfPossession + if err := bbnPop.Unmarshal(pop); err != nil { + return nil, fmt.Errorf("invalid proof-of-possession: %w", err) + } + + sdkCommission := math.LegacyNewDecFromBigInt(commission) + + var sdkDescription sttypes.Description + if err := yaml.Unmarshal([]byte(description), &sdkDescription); err != nil { + return nil, fmt.Errorf("invalid descirption: %w", err) + } msg := &btcstakingtypes.MsgCreateBTCValidator{ Signer: bc.MustGetTxSigner(), - BabylonPk: bbnPubKey, - BtcPk: btcPubKey, - Pop: pop, - Commission: commission, - Description: description, + BabylonPk: &secp256k1.PubKey{Key: chainPk}, + BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + Pop: &bbnPop, + Commission: &sdkCommission, + Description: &sdkDescription, } res, err := bc.reliablySendMsg(msg) @@ -286,18 +318,31 @@ func (bc *BabylonController) RegisterValidator( return nil, err } - return res, nil + 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(btcPubKey *bbntypes.BIP340PubKey, startHeight uint64, pubRandList []bbntypes.SchnorrPubRand, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) CommitPubRandList( + valPk *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(), - ValBtcPk: btcPubKey, + ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), StartHeight: startHeight, - PubRandList: pubRandList, - Sig: sig, + PubRandList: schnorrPubRandList, + Sig: &bip340Sig, } res, err := bc.reliablySendMsg(msg) @@ -305,18 +350,25 @@ func (bc *BabylonController) CommitPubRandList(btcPubKey *bbntypes.BIP340PubKey, return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode // it returns tx hash and error -func (bc *BabylonController) SubmitJurySig(btcPubKey *bbntypes.BIP340PubKey, delPubKey *bbntypes.BIP340PubKey, stakingTxHash string, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) SubmitJurySig( + valPk *btcec.PublicKey, + delPk *btcec.PublicKey, + stakingTxHash string, + sig *schnorr.Signature, +) (*types.TxResponse, error) { + bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) + msg := &btcstakingtypes.MsgAddJurySig{ Signer: bc.MustGetTxSigner(), - ValPk: btcPubKey, - DelPk: delPubKey, + ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), StakingTxHash: stakingTxHash, - Sig: sig, + Sig: &bip340Sig, } res, err := bc.reliablySendMsg(msg) @@ -324,25 +376,29 @@ func (bc *BabylonController) SubmitJurySig(btcPubKey *bbntypes.BIP340PubKey, del return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode // it returns tx hash and error func (bc *BabylonController) SubmitJuryUnbondingSigs( - btcPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, + valPk *btcec.PublicKey, + delPk *btcec.PublicKey, stakingTxHash string, - unbondingSig *bbntypes.BIP340Signature, - slashUnbondingSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { + unbondingSig *schnorr.Signature, + slashUnbondingSig *schnorr.Signature, +) (*types.TxResponse, error) { + bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) + + bip340SlashUnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(slashUnbondingSig) + msg := &btcstakingtypes.MsgAddJuryUnbondingSigs{ Signer: bc.MustGetTxSigner(), - ValPk: btcPubKey, - DelPk: delPubKey, + ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), StakingTxHash: stakingTxHash, - UnbondingTxSig: unbondingSig, - SlashingUnbondingTxSig: slashUnbondingSig, + UnbondingTxSig: &bip340UnbondingSig, + SlashingUnbondingTxSig: &bip340SlashUnbondingSig, } res, err := bc.reliablySendMsg(msg) @@ -350,17 +406,17 @@ func (bc *BabylonController) SubmitJuryUnbondingSigs( return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon -func (bc *BabylonController) SubmitFinalitySig(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { msg := &finalitytypes.MsgAddFinalitySig{ Signer: bc.MustGetTxSigner(), - ValBtcPk: btcPubKey, + ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), BlockHeight: blockHeight, BlockLastCommitHash: blockHash, - FinalitySig: sig, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), } res, err := bc.reliablySendMsg(msg) @@ -368,11 +424,11 @@ func (bc *BabylonController) SubmitFinalitySig(btcPubKey *bbntypes.BIP340PubKey, return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon -func (bc *BabylonController) SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340PubKey, blocks []*types.BlockInfo, sigs []*bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { if len(blocks) != len(sigs) { return nil, fmt.Errorf("the number of blocks %v should match the number of finality signatures %v", len(blocks), len(sigs)) } @@ -381,10 +437,10 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340P for i, b := range blocks { msg := &finalitytypes.MsgAddFinalitySig{ Signer: bc.MustGetTxSigner(), - ValBtcPk: btcPubKey, + ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), BlockHeight: b.Height, - BlockLastCommitHash: b.LastCommitHash, - FinalitySig: sigs[i], + BlockLastCommitHash: b.Hash, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]), } msgs = append(msgs, msg) } @@ -394,21 +450,25 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340P return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } func (bc *BabylonController) SubmitValidatorUnbondingSig( - valPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, + valPk *btcec.PublicKey, + delPk *btcec.PublicKey, stakingTxHash string, - sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { + sig *schnorr.Signature, +) (*types.TxResponse, error) { + valBtcPk := bbntypes.NewBIP340PubKeyFromBTCPK(valPk) + + bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) msg := &btcstakingtypes.MsgAddValidatorUnbondingSig{ Signer: bc.MustGetTxSigner(), - ValPk: valPubKey, - DelPk: delPubKey, + ValPk: valBtcPk, + DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), StakingTxHash: stakingTxHash, - UnbondingTxSig: sig, + UnbondingTxSig: &bip340Sig, } res, err := bc.reliablySendMsg(msg) @@ -418,125 +478,27 @@ func (bc *BabylonController) SubmitValidatorUnbondingSig( } bc.logger.WithFields(logrus.Fields{ - "validator": valPubKey.MarshalHex(), + "validator": valBtcPk.MarshalHex(), "code": res.Code, "height": res.Height, "tx_hash": res.TxHash, }).Debug("Succesfuly submitted validator signature for unbonding tx") - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -// Currently this is only used for e2e tests, probably does not need to add it into the interface -func (bc *BabylonController) CreateBTCDelegation( - delBabylonPk *secp256k1.PubKey, - pop *btcstakingtypes.ProofOfPossession, - stakingTx *btcstakingtypes.BabylonBTCTaprootTx, - stakingTxInfo *btcctypes.TransactionInfo, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgCreateBTCDelegation{ - Signer: bc.MustGetTxSigner(), - BabylonPk: delBabylonPk, - Pop: pop, - StakingTx: stakingTx, - StakingTxInfo: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delSig, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - bc.logger.Infof("successfully submitted a BTC delegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) - return res, nil +func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { + return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) CreateBTCUndelegation( - unbondingTx *btcstakingtypes.BabylonBTCTaprootTx, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgBTCUndelegate{ - Signer: bc.MustGetTxSigner(), - UnbondingTx: unbondingTx, - SlashingTx: slashingTx, - DelegatorSlashingSig: delSig, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - bc.logger.Infof("successfully submitted a BTC undelegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) - return res, nil +func (bc *BabylonController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { + return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) } -// Insert BTC block header using rpc client -// Currently this is only used for e2e tests, probably does not need to add it into the interface -func (bc *BabylonController) InsertBtcBlockHeaders(headers []*bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { - msgs := make([]sdk.Msg, 0, len(headers)) - for _, h := range headers { - msg := &btclctypes.MsgInsertHeader{ - Signer: bc.MustGetTxSigner(), - Header: h, - } - msgs = append(msgs, msg) - } - - res, err := bc.reliablySendMsgs(msgs) - if err != nil { - return nil, err - } - - return res, nil -} - -// Note: the following queries are only for PoC -// QueryHeightWithLastPubRand queries the height of the last block with public randomness -func (bc *BabylonController) QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP340PubKey) (uint64, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query the last committed public randomness - queryRequest := &finalitytypes.QueryListPublicRandomnessRequest{ - ValBtcPkHex: btcPubKey.MarshalHex(), - Pagination: &sdkquery.PageRequest{ - Limit: 1, - Reverse: true, - }, - } - - res, err := queryClient.ListPublicRandomness(ctx, queryRequest) - if err != nil { - return 0, err - } - - if len(res.PubRandMap) == 0 { - return 0, nil - } - - ks := maps.Keys(res.PubRandMap) - if len(ks) > 1 { - return 0, fmt.Errorf("the query should not return more than one public rand item") - } - - return ks[0], nil -} - -// QueryBTCDelegations queries BTC delegations that need a Jury signature +// queryDelegationsWithStatus queries BTC delegations that need a Jury signature // with the given status (either pending or unbonding) // it is only used when the program is running in Jury mode -func (bc *BabylonController) QueryBTCDelegations(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*types.Delegation, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() pagination := &sdkquery.PageRequest{ @@ -549,7 +511,7 @@ func (bc *BabylonController) QueryBTCDelegations(status btcstakingtypes.BTCDeleg // query all the unsigned delegations queryRequest := &btcstakingtypes.QueryBTCDelegationsRequest{ - Status: status, + Status: btcstakingtypes.BTCDelegationStatus(status), Pagination: pagination, } res, err := queryClient.BTCDelegations(ctx, queryRequest) @@ -557,82 +519,40 @@ func (bc *BabylonController) QueryBTCDelegations(status btcstakingtypes.BTCDeleg return nil, fmt.Errorf("failed to query BTC delegations: %v", err) } - return res.BtcDelegations, nil -} - -func (bc *BabylonController) QueryValidator(btcPk *bbntypes.BIP340PubKey) (*btcstakingtypes.BTCValidator, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryRequest := &btcstakingtypes.QueryBTCValidatorRequest{ValBtcPkHex: btcPk.MarshalHex()} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - res, err := queryClient.BTCValidator(ctx, queryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query the validator %s: %v", btcPk.MarshalHex(), err) + dels := make([]*types.Delegation, 0, len(res.BtcDelegations)) + for _, d := range res.BtcDelegations { + dels = append(dels, ConvertDelegationType(d)) } - return res.BtcValidator, nil + return dels, nil } -// QueryValidators queries BTC validators -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, error) { - var validators []*btcstakingtypes.BTCValidator - pagination := &sdkquery.PageRequest{ - Limit: 100, - } - +func (bc *BabylonController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - queryClient := btcstakingtypes.NewQueryClient(clientCtx) + valPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(valPk) - for { - queryRequest := &btcstakingtypes.QueryBTCValidatorsRequest{ - Pagination: pagination, - } - res, err := queryClient.BTCValidators(ctx, queryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query BTC validators: %v", err) - } - validators = append(validators, res.BtcValidators...) - if res.Pagination == nil || res.Pagination.NextKey == nil { - break - } + queryRequest := &btcstakingtypes.QueryBTCValidatorRequest{ValBtcPkHex: valPubKey.MarshalHex()} - pagination.Key = res.Pagination.NextKey - } - - return validators, nil -} - -func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btclctypes.NewQueryClient(clientCtx) - - queryRequest := &btclctypes.QueryTipRequest{} - res, err := queryClient.Tip(ctx, queryRequest) + queryClient := btcstakingtypes.NewQueryClient(clientCtx) + res, err := queryClient.BTCValidator(ctx, queryRequest) if err != nil { - return nil, fmt.Errorf("failed to query BTC tip: %v", err) + return false, fmt.Errorf("failed to query the validator %s: %v", valPubKey.MarshalHex(), err) } - return res.Header, nil + slashed := res.BtcValidator.SlashedBtcHeight > 0 + + return slashed, nil } func (bc *BabylonController) getNDelegations( valBtcPk *bbntypes.BIP340PubKey, startKey []byte, n uint64, -) ([]*btcstakingtypes.BTCDelegation, []byte, error) { +) ([]*types.Delegation, []byte, error) { pagination := &sdkquery.PageRequest{ Key: startKey, Limit: n, @@ -655,10 +575,12 @@ func (bc *BabylonController) getNDelegations( return nil, nil, fmt.Errorf("failed to query BTC delegations: %v", err) } - var delegations []*btcstakingtypes.BTCDelegation + var delegations []*types.Delegation for _, dels := range res.BtcDelegatorDelegations { - delegations = append(delegations, dels.Dels...) + for _, d := range dels.Dels { + delegations = append(delegations, ConvertDelegationType(d)) + } } var nextKey []byte @@ -673,10 +595,10 @@ func (bc *BabylonController) getNDelegations( func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( valBtcPk *bbntypes.BIP340PubKey, n uint64, - match func(*btcstakingtypes.BTCDelegation) bool, -) ([]*btcstakingtypes.BTCDelegation, error) { + match func(*types.Delegation) bool, +) ([]*types.Delegation, error) { batchSize := 100 - var delegations []*btcstakingtypes.BTCDelegation + var delegations []*types.Delegation var startKey []byte for { @@ -706,50 +628,21 @@ func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( } } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) { - return bc.getNValidatorDelegationsMatchingCriteria( - valBtcPk, - max, - // fitlering function which always returns true as we want all delegations - func(*btcstakingtypes.BTCDelegation) bool { return true }, - ) -} - -func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &finalitytypes.QueryVotesAtHeightRequest{ - Height: height, - } - res, err := queryClient.VotesAtHeight(ctx, queryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %w", err) - } - - return res.BtcPks, nil -} - -func (bc *BabylonController) QueryBTCValidatorUnbondingDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) { +func (bc *BabylonController) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { // TODO Check what is the order of returned delegations. Ideally we would return // delegation here from the first one which received undelegation + return bc.getNValidatorDelegationsMatchingCriteria( - valBtcPk, + bbntypes.NewBIP340PubKeyFromBTCPK(valPk), max, - func(del *btcstakingtypes.BTCDelegation) bool { + func(del *types.Delegation) bool { return del.BtcUndelegation != nil && del.BtcUndelegation.ValidatorUnbondingSig == nil }, ) } // QueryValidatorVotingPower queries the voting power of the validator at a given height -func (bc *BabylonController) QueryValidatorVotingPower(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64) (uint64, error) { +func (bc *BabylonController) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() @@ -759,7 +652,7 @@ func (bc *BabylonController) QueryValidatorVotingPower(btcPubKey *bbntypes.BIP34 // query all the unsigned delegations queryRequest := &btcstakingtypes.QueryBTCValidatorPowerAtHeightRequest{ - ValBtcPkHex: btcPubKey.MarshalHex(), + ValBtcPkHex: bbntypes.NewBIP340PubKeyFromBTCPK(valPk).MarshalHex(), Height: blockHeight, } res, err := queryClient.BTCValidatorPowerAtHeight(ctx, queryRequest) @@ -770,27 +663,6 @@ func (bc *BabylonController) QueryValidatorVotingPower(btcPubKey *bbntypes.BIP34 return res.VotingPower, nil } -// QueryBlockFinalization queries whether the block has been finalized -func (bc *BabylonController) QueryBlockFinalization(blockHeight uint64) (bool, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query the indexed block at the given height - queryRequest := &finalitytypes.QueryBlockRequest{ - Height: blockHeight, - } - res, err := queryClient.Block(ctx, queryRequest) - if err != nil { - return false, fmt.Errorf("failed to query indexed block at height %v: %w", blockHeight, err) - } - - return res.Block.Finalized, nil -} - func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { return bc.queryLatestBlocks(nil, count, finalitytypes.QueriedBlockStatus_FINALIZED, true) } @@ -832,8 +704,8 @@ func (bc *BabylonController) queryLatestBlocks(startKey []byte, count uint64, st for _, b := range res.Blocks { ib := &types.BlockInfo{ - Height: b.Height, - LastCommitHash: b.LastCommitHash, + Height: b.Height, + Hash: b.LastCommitHash, } blocks = append(blocks, ib) } @@ -846,46 +718,64 @@ func getContextWithCancel(timeout time.Duration) (context.Context, context.Cance return ctx, cancel } -func (bc *BabylonController) QueryHeader(height int64) (*ctypes.ResultHeader, error) { +func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) { ctx, cancel := getContextWithCancel(bc.timeout) - headerResp, err := bc.provider.RPCClient.Header(ctx, &height) defer cancel() + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := finalitytypes.NewQueryClient(clientCtx) + + // query the indexed block at the given height + queryRequest := &finalitytypes.QueryBlockRequest{ + Height: height, + } + res, err := queryClient.Block(ctx, queryRequest) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to query indexed block at height %v: %w", height, err) } - // Returning response directly, if header with specified number did not exist - // at request will contain nil header - return headerResp, nil + return &types.BlockInfo{ + Height: height, + Hash: res.Block.LastCommitHash, + Finalized: res.Block.Finalized, + }, nil } -func (bc *BabylonController) QueryBestHeader() (*ctypes.ResultHeader, error) { +func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { ctx, cancel := getContextWithCancel(bc.timeout) - // this will return 20 items at max in the descending order (highest first) - chainInfo, err := bc.provider.RPCClient.BlockchainInfo(ctx, 0, 0) defer cancel() + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := btcstakingtypes.NewQueryClient(clientCtx) + + // query the indexed block at the given height + queryRequest := &btcstakingtypes.QueryActivatedHeightRequest{} + res, err := queryClient.ActivatedHeight(ctx, queryRequest) if err != nil { - return nil, err + return 0, fmt.Errorf("failed to query activated height: %w", err) } - // Returning response directly, if header with specified number did not exist - // at request will contain nil header - return &ctypes.ResultHeader{ - Header: &chainInfo.BlockMetas[0].Header, - }, nil + return res.Height, nil } -func (bc *BabylonController) QueryNodeStatus() (*ctypes.ResultStatus, error) { +func (bc *BabylonController) QueryBestBlock() (*types.BlockInfo, error) { ctx, cancel := getContextWithCancel(bc.timeout) + // this will return 20 items at max in the descending order (highest first) + chainInfo, err := bc.provider.RPCClient.BlockchainInfo(ctx, 0, 0) defer cancel() - status, err := bc.provider.QueryStatus(ctx) if err != nil { return nil, err } - return status, nil + + // Returning response directly, if header with specified number did not exist + // at request will contain nil header + return &types.BlockInfo{ + Height: uint64(chainInfo.BlockMetas[0].Header.Height), + Hash: chainInfo.BlockMetas[0].Header.LastCommitHash, + }, nil } // accessKeyWithLock triggers a function that access key ring while acquiring @@ -947,3 +837,258 @@ func ConvertErrType(err error) error { return err } } + +func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation { + var ( + stakingTxHex string + slashingTxHex string + jurySchnorrSig *schnorr.Signature + undelegation *types.Undelegation + err error + ) + + if del.StakingTx == nil { + panic(fmt.Errorf("staking tx should not be empty in delegation")) + } + + if del.SlashingTx == nil { + panic(fmt.Errorf("slashing tx should not be empty in delegation")) + } + + stakingTxHex, err = del.StakingTx.ToHexStr() + if err != nil { + panic(err) + } + + slashingTxHex = del.SlashingTx.ToHexStr() + + if del.JurySig != nil { + jurySchnorrSig, err = del.JurySig.ToBTCSig() + if err != nil { + panic(err) + } + } + + if del.BtcUndelegation != nil { + undelegation = ConvertUndelegationType(del.BtcUndelegation) + } + + return &types.Delegation{ + BtcPk: del.BtcPk.MustToBTCPK(), + ValBtcPk: del.ValBtcPk.MustToBTCPK(), + StartHeight: del.StartHeight, + EndHeight: del.EndHeight, + StakingTxHex: stakingTxHex, + SlashingTxHex: slashingTxHex, + JurySig: jurySchnorrSig, + BtcUndelegation: undelegation, + } +} + +func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Undelegation { + var ( + unbondingTxHex string + slashingTxHex string + jurySlashingSchnorrSig *schnorr.Signature + juryUnbondingSchnorrSig *schnorr.Signature + valUnbondingSchnorrSig *schnorr.Signature + err error + ) + + if undel.UnbondingTx == nil { + panic(fmt.Errorf("staking tx should not be empty in undelegation")) + } + + if undel.SlashingTx == nil { + panic(fmt.Errorf("slashing tx should not be empty in undelegation")) + } + + unbondingTxHex, err = undel.UnbondingTx.ToHexStr() + if err != nil { + panic(err) + } + + slashingTxHex = undel.SlashingTx.ToHexStr() + + if undel.JurySlashingSig != nil { + jurySlashingSchnorrSig, err = undel.JurySlashingSig.ToBTCSig() + if err != nil { + panic(err) + } + } + + if undel.JuryUnbondingSig != nil { + juryUnbondingSchnorrSig, err = undel.JuryUnbondingSig.ToBTCSig() + if err != nil { + panic(err) + } + } + + if undel.ValidatorUnbondingSig != nil { + valUnbondingSchnorrSig, err = undel.ValidatorUnbondingSig.ToBTCSig() + if err != nil { + panic(err) + } + } + + return &types.Undelegation{ + UnbondingTxHex: unbondingTxHex, + SlashingTxHex: slashingTxHex, + JurySlashingSig: jurySlashingSchnorrSig, + JuryUnbondingSig: juryUnbondingSchnorrSig, + ValidatorUnbondingSig: valUnbondingSchnorrSig, + } +} + +// Currently this is only used for e2e tests, probably does not need to add it into the interface +func (bc *BabylonController) CreateBTCDelegation( + delBabylonPk *secp256k1.PubKey, + pop *btcstakingtypes.ProofOfPossession, + stakingTx *btcstakingtypes.BabylonBTCTaprootTx, + stakingTxInfo *btcctypes.TransactionInfo, + slashingTx *btcstakingtypes.BTCSlashingTx, + delSig *bbntypes.BIP340Signature, +) (*types.TxResponse, error) { + msg := &btcstakingtypes.MsgCreateBTCDelegation{ + Signer: bc.MustGetTxSigner(), + BabylonPk: delBabylonPk, + Pop: pop, + StakingTx: stakingTx, + StakingTxInfo: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSig: delSig, + } + + res, err := bc.reliablySendMsg(msg) + if err != nil { + return nil, err + } + + bc.logger.Infof("successfully submitted a BTC delegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) + return &types.TxResponse{TxHash: res.TxHash}, nil +} + +// Currently this is only used for e2e tests, probably does not need to add this into the interface +func (bc *BabylonController) CreateBTCUndelegation( + unbondingTx *btcstakingtypes.BabylonBTCTaprootTx, + slashingTx *btcstakingtypes.BTCSlashingTx, + delSig *bbntypes.BIP340Signature, +) (*provider.RelayerTxResponse, error) { + msg := &btcstakingtypes.MsgBTCUndelegate{ + Signer: bc.MustGetTxSigner(), + UnbondingTx: unbondingTx, + SlashingTx: slashingTx, + DelegatorSlashingSig: delSig, + } + + res, err := bc.reliablySendMsg(msg) + if err != nil { + return nil, err + } + + bc.logger.Infof("successfully submitted a BTC undelegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) + return res, nil +} + +// Insert BTC block header using rpc client +// Currently this is only used for e2e tests, probably does not need to add it into the interface +func (bc *BabylonController) InsertBtcBlockHeaders(headers []*bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { + msgs := make([]sdk.Msg, 0, len(headers)) + for _, h := range headers { + msg := &btclctypes.MsgInsertHeader{ + Signer: bc.MustGetTxSigner(), + Header: h, + } + msgs = append(msgs, msg) + } + + res, err := bc.reliablySendMsgs(msgs) + if err != nil { + return nil, err + } + + return res, nil +} + +// QueryValidators queries BTC validators +// Currently this is only used for e2e tests, probably does not need to add this into the interface +func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, error) { + var validators []*btcstakingtypes.BTCValidator + pagination := &sdkquery.PageRequest{ + Limit: 100, + } + + ctx, cancel := getContextWithCancel(bc.timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := btcstakingtypes.NewQueryClient(clientCtx) + + for { + queryRequest := &btcstakingtypes.QueryBTCValidatorsRequest{ + Pagination: pagination, + } + res, err := queryClient.BTCValidators(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query BTC validators: %v", err) + } + validators = append(validators, res.BtcValidators...) + if res.Pagination == nil || res.Pagination.NextKey == nil { + break + } + + pagination.Key = res.Pagination.NextKey + } + + return validators, nil +} + +// Currently this is only used for e2e tests, probably does not need to add this into the interface +func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { + ctx, cancel := getContextWithCancel(bc.timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := btclctypes.NewQueryClient(clientCtx) + + queryRequest := &btclctypes.QueryTipRequest{} + res, err := queryClient.Tip(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query BTC tip: %v", err) + } + + return res.Header, nil +} + +// Currently this is only used for e2e tests, probably does not need to add this into the interface +func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*types.Delegation, error) { + return bc.getNValidatorDelegationsMatchingCriteria( + valBtcPk, + max, + // fitlering function which always returns true as we want all delegations + func(*types.Delegation) bool { return true }, + ) +} + +// Currently this is only used for e2e tests, probably does not need to add this into the interface +func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { + ctx, cancel := getContextWithCancel(bc.timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + + queryClient := finalitytypes.NewQueryClient(clientCtx) + + // query all the unsigned delegations + queryRequest := &finalitytypes.QueryVotesAtHeightRequest{ + Height: height, + } + res, err := queryClient.VotesAtHeight(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query BTC delegations: %w", err) + } + + return res.BtcPks, nil +} diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 2e5424bd..94346921 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -2,16 +2,10 @@ package clientcontroller import ( "fmt" + "math/big" - bbntypes "github.com/babylonchain/babylon/types" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcutil" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdkTypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/provider" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/types" @@ -22,102 +16,95 @@ const ( babylonConsumerChainName = "babylon" ) -type StakingParams struct { - // K-deep - ComfirmationTimeBlocks uint64 - // W-deep - FinalizationTimeoutBlocks uint64 - - // Minimum amount of satoshis required for slashing transaction - MinSlashingTxFeeSat btcutil.Amount - - // Bitcoin public key of the current jury - JuryPk *btcec.PublicKey +type ClientController interface { + ValidatorAPIs - // Address to which slashing transactions are sent - SlashingAddress string + JuryAPIs - // Minimum commission required by babylon - MinCommissionRate sdkTypes.Dec + Close() error } -// TODO replace babylon types with general ones -type ClientController interface { - GetStakingParams() (*StakingParams, error) - // RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon +// ValidatorAPIs contains interfaces needed when the program is running in the validator mode +type ValidatorAPIs interface { + // RegisterValidator registers a BTC validator to the consumer chain // it returns tx hash and error RegisterValidator( - bbnPubKey *secp256k1.PubKey, - btcPubKey *bbntypes.BIP340PubKey, - pop *btcstakingtypes.ProofOfPossession, - commission *sdkTypes.Dec, - description *stakingtypes.Description, - ) (*provider.RelayerTxResponse, error) - // CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon - // it returns tx hash and error - CommitPubRandList(btcPubKey *bbntypes.BIP340PubKey, startHeight uint64, pubRandList []bbntypes.SchnorrPubRand, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) - // SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode + chainPk []byte, + valPk *btcec.PublicKey, + pop []byte, + commission *big.Int, + description string, + ) (*types.TxResponse, error) + + // CommitPubRandList commits a list of EOTS public randomness the consumer chain // it returns tx hash and error - SubmitJurySig(btcPubKey *bbntypes.BIP340PubKey, delPubKey *bbntypes.BIP340PubKey, stakingTxHash string, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) + CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) - // SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode - // it returns tx hash and error - SubmitJuryUnbondingSigs( - btcPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, - stakingTxHash string, - unbondingSig *bbntypes.BIP340Signature, - slashUnbondingSig *bbntypes.BIP340Signature, - ) (*provider.RelayerTxResponse, error) + // SubmitFinalitySig submits the finality signature to the consumer chain + SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) - // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon - SubmitFinalitySig(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) - // SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon - SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340PubKey, blocks []*types.BlockInfo, sigs []*bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) + // SubmitBatchFinalitySigs submits a batch of finality signatures to the consumer chain + SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) - // SubmitValidatorUnbondingSig submits the validator signature for unbonding transaction + // SubmitValidatorUnbondingSig submits the validator signature for unbonding transaction to the consumer chain SubmitValidatorUnbondingSig( - valPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, + valPk *btcec.PublicKey, + delPk *btcec.PublicKey, stakingTxHash string, - sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) + sig *schnorr.Signature, + ) (*types.TxResponse, error) // Note: the following queries are only for PoC - // QueryHeightWithLastPubRand queries the height of the last block with public randomness - QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP340PubKey) (uint64, error) + // QueryValidatorVotingPower queries the voting power of the validator at a given height + QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) - // QueryBTCDelegations queries BTC delegations that need a Jury signature - // with the given status (either pending or unbonding) - // it is only used when the program is running in Jury mode - QueryBTCDelegations(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) + // QueryValidatorSlashed queries if the validator is slashed + QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) - // QueryValidatorVotingPower queries the voting power of the validator at a given height - QueryValidatorVotingPower(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64) (uint64, error) // QueryLatestFinalizedBlocks returns the latest finalized blocks QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) + + // QueryBlock queries the block at the given height + QueryBlock(height uint64) (*types.BlockInfo, error) + // QueryBlocks returns a list of blocks from startHeight to endHeight QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) - // QueryValidator returns a BTC validator object - QueryValidator(btcPk *bbntypes.BIP340PubKey) (*btcstakingtypes.BTCValidator, error) - // QueryBlockFinalization queries whether the block has been finalized - QueryBlockFinalization(height uint64) (bool, error) - - // QueryBestHeader queries the tip header of the Babylon chain, if header is not found - // it returns result with nil header - QueryBestHeader() (*ctypes.ResultHeader, error) - // QueryNodeStatus returns current node status, with info about latest block - QueryNodeStatus() (*ctypes.ResultStatus, error) - // QueryHeader queries the header at the given height, if header is not found - // it returns result with nil header - QueryHeader(height int64) (*ctypes.ResultHeader, error) - - // QueryBTCValidatorUnbondingDelegations queries the unbonding delegations.UnbondingDelegations: + + // QueryBestBlock queries the tip block of the consumer chain + QueryBestBlock() (*types.BlockInfo, error) + + // QueryActivatedHeight returns the activated height of the consumer chain + // error will be returned if the consumer chain has not been activated + QueryActivatedHeight() (uint64, error) + + // QueryBTCValidatorUnbondingDelegations queries the unbonding delegations. UnbondingDelegations: // - already received unbodning transaction on babylon chain // - not received validator signature yet - QueryBTCValidatorUnbondingDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) + QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) +} - Close() error +// JuryAPIs contains interfaces needed when the program is running in the jury mode +type JuryAPIs interface { + // SubmitJurySig submits the Jury signature to the consumer chain + // it returns tx hash and error + SubmitJurySig(valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) + + // SubmitJuryUnbondingSigs submits the Jury signatures to the consumer chain + // it returns tx hash and error + SubmitJuryUnbondingSigs( + valPk *btcec.PublicKey, + delPk *btcec.PublicKey, + stakingTxHash string, + unbondingSig *schnorr.Signature, + slashUnbondingSig *schnorr.Signature, + ) (*types.TxResponse, error) + + // QueryPendingDelegations queries BTC delegations that are in status of pending + QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) + + // QueryUnbondingDelegations queries BTC delegations that are in status of unbonding + QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) } func NewClientController(cfg *valcfg.Config, logger *logrus.Logger) (ClientController, error) { diff --git a/go.mod b/go.mod index 2616a527..48dade24 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 - github.com/cometbft/cometbft v0.37.2 github.com/cosmos/cosmos-proto v1.0.0-beta.2 github.com/cosmos/cosmos-sdk v0.47.3 github.com/cosmos/go-bip39 v1.0.0 @@ -28,10 +27,10 @@ require ( go.etcd.io/bbolt v1.3.7 go.uber.org/atomic v1.10.0 go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/sync v0.1.0 google.golang.org/grpc v1.56.1 google.golang.org/protobuf v1.31.0 + sigs.k8s.io/yaml v1.3.0 ) require ( @@ -79,6 +78,7 @@ require ( github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect + github.com/cometbft/cometbft v0.37.2 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -266,6 +266,7 @@ require ( go.opentelemetry.io/proto/otlp v0.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/crypto v0.9.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect @@ -299,11 +300,10 @@ require ( modernc.org/token v1.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v0.5.5 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 84646c53..cb87c5bb 100644 --- a/go.sum +++ b/go.sum @@ -269,8 +269,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231019041015-8f9d04986515 h1:NvfNgjTi3FgnEAwXHAObNNZeOcYT2S/CUT+dckXz36c= -github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= +github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index d5f590ca..bdb92fb5 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -5,19 +5,14 @@ package e2etest import ( "math/rand" - "os" "testing" "time" "github.com/babylonchain/babylon/testutil/datagen" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" ) var ( @@ -25,56 +20,6 @@ var ( stakingAmount = int64(20000) ) -func TestPoller(t *testing.T) { - handler := NewBabylonNodeHandler(t) - - err := handler.Start() - require.NoError(t, err) - defer handler.Stop() - - defaultConfig := valcfg.DefaultBBNConfig() - logger := logrus.New() - logger.SetLevel(logrus.DebugLevel) - logger.Out = os.Stdout - defaultPollerConfig := valcfg.DefaultChainPollerConfig() - - bc, err := clientcontroller.NewBabylonController(handler.GetNodeDataDir(), &defaultConfig, logger) - require.NoError(t, err) - - poller := service.NewChainPoller(logger, &defaultPollerConfig, bc) - require.NoError(t, err) - - // Set auto calculated start height to 1, as we have disabled automatic start height calculation - err = poller.Start(1) - require.NoError(t, err) - defer poller.Stop() - - // Get 3 blocks which should be received in order - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(1), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } - - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(2), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } - - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(3), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } -} - // TestValidatorLifeCycle tests the whole life cycle of a validator // creation -> registration -> randomness commitment -> // activation with BTC delegation and Jury sig -> @@ -90,18 +35,16 @@ func TestValidatorLifeCycle(t *testing.T) { tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // submit Jury sig _ = tm.AddJurySignature(t, dels[0]) // check the BTC delegation is active dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -138,7 +81,7 @@ func TestMultipleValidators(t *testing.T) { // submit Jury sigs for each delegation for _, del := range dels { tm.Wg.Add(1) - go func(btcDel *btcstakingtypes.BTCDelegation) { + go func(btcDel *types.Delegation) { defer tm.Wg.Done() _ = tm.AddJurySignature(t, btcDel) }(del) @@ -158,22 +101,6 @@ func TestMultipleValidators(t *testing.T) { _ = tm.WaitForNFinalizedBlocks(t, 1) } -func TestJurySigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, true) - // changing the mode because we need to ensure the validator is also stopped when the test is finished - defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] - - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) - - dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - err := valIns.Stop() - require.NoError(t, err) -} - // TestDoubleSigning tests the attack scenario where the validator // sends a finality vote over a conflicting block // in this case, the BTC private key should be extracted by Babylon @@ -188,18 +115,16 @@ func TestDoubleSigning(t *testing.T) { tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // submit Jury sig _ = tm.AddJurySignature(t, dels[0]) // check the BTC delegation is active dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -212,8 +137,8 @@ func TestDoubleSigning(t *testing.T) { // to trigger the extraction of validator's private key r := rand.New(rand.NewSource(time.Now().UnixNano())) b := &types.BlockInfo{ - Height: finalizedBlocks[0].Height, - LastCommitHash: datagen.GenRandomLastCommitHash(r), + Height: finalizedBlocks[0].Height, + Hash: datagen.GenRandomLastCommitHash(r), } _, extractedKey, err := valIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) @@ -236,23 +161,21 @@ func TestFastSync(t *testing.T) { tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // submit Jury sig _ = tm.AddJurySignature(t, dels[0]) dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) tm.CheckBlockFinalization(t, lastVotedHeight, 1) t.Logf("the block at height %v is finalized", lastVotedHeight) - + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) n := 3 @@ -266,11 +189,11 @@ func TestFastSync(t *testing.T) { t.Logf("the latest finalized block is at %v", finalizedHeight) // check if the fast sync works by checking if the gap is not more than 1 - currentHeaderRes, err := tm.BabylonClient.QueryBestHeader() - currentHeight := currentHeaderRes.Header.Height + currentHeaderRes, err := tm.BabylonClient.QueryBestBlock() + currentHeight := currentHeaderRes.Height t.Logf("the current block is at %v", currentHeight) require.NoError(t, err) - require.True(t, currentHeight < int64(finalizedHeight)+int64(n)) + require.True(t, currentHeight < finalizedHeight+uint64(n)) } func TestValidatorUnbondingSigSubmission(t *testing.T) { @@ -293,14 +216,13 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { _ = tm.AddJurySignature(t, dels[0]) dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) _ = tm.WaitForValNUnbondingDels(t, valIns.GetBtcPkBIP340(), 1) } -func TestJuryUnbondingSigSubmission(t *testing.T) { +func TestJuryLifeCycle(t *testing.T) { tm := StartManagerWithValidator(t, 1, true) defer tm.Stop(t) app := tm.Va @@ -309,35 +231,9 @@ func TestJuryUnbondingSigSubmission(t *testing.T) { // send BTC delegation and make sure it's deep enough in btclightclient module delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) - var ( - dels []*btcstakingtypes.BTCDelegation - err error - ) - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCDelegations( - btcstakingtypes.BTCDelegationStatus_PENDING, - tm.ValConfig.JuryModeConfig.DelegationLimit, - ) - if err != nil { - return false - } - return len(dels) == 1 - }, eventuallyWaitTimeOut, eventuallyPollTime) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - - currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() - require.NoError(t, err) - params, err := tm.BabylonClient.GetStakingParams() + dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + err := valIns.Stop() require.NoError(t, err) - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) - if err != nil { - return false - } - status := dels[0].GetStatus(currentBtcTip.Height, params.FinalizationTimeoutBlocks) - return len(dels) == 1 && status == btcstakingtypes.BTCDelegationStatus_ACTIVE - }, eventuallyWaitTimeOut, eventuallyPollTime) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) @@ -379,6 +275,6 @@ func TestJuryUnbondingSigSubmission(t *testing.T) { return false } - return del.BtcUndelegation.HasJurySigs() + return del.BtcUndelegation.JurySlashingSig != nil && del.BtcUndelegation.JuryUnbondingSig != nil }, 1*time.Minute, eventuallyPollTime) } diff --git a/itest/test_manager.go b/itest/test_manager.go index 56c0ca2c..16050e18 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -22,7 +22,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -138,7 +137,7 @@ func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { for i := 0; i < n; i++ { valName := valNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) - commission := sdktypes.OneDec() + commission := sdktypes.ZeroDec() res, err := app.CreateValidator(valName, chainID, "", newDescription(moniker), &commission) require.NoError(t, err) _, err = app.RegisterValidator(res.ValPk.MarshalHex()) @@ -166,7 +165,7 @@ func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { if !strings.Contains(v.Description.Moniker, monikerPrefix) { return false } - if !v.Commission.Equal(sdktypes.OneDec()) { + if !v.Commission.Equal(sdktypes.ZeroDec()) { return false } } @@ -216,14 +215,13 @@ func (tm *TestManager) WaitForValPubRandCommitted(t *testing.T, valIns *service. 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) []*types.Delegation { var ( - dels []*bstypes.BTCDelegation + dels []*types.Delegation err error ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCDelegations( - bstypes.BTCDelegationStatus_PENDING, + dels, err = tm.BabylonClient.QueryPendingDelegations( tm.ValConfig.JuryModeConfig.DelegationLimit, ) if err != nil { @@ -237,8 +235,8 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe return dels } -func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*bstypes.BTCDelegation { - var dels []*bstypes.BTCDelegation +func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { + var dels []*types.Delegation currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() require.NoError(t, err) params, err := tm.BabylonClient.GetStakingParams() @@ -256,9 +254,9 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 return dels } -func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*bstypes.BTCDelegation { +func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { var ( - dels []*bstypes.BTCDelegation + dels []*types.Delegation err error ) // wait for our validator to: @@ -277,10 +275,10 @@ func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BI return dels } -func CheckDelsStatus(dels []*bstypes.BTCDelegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { +func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { allChecked := true for _, d := range dels { - s := d.GetStatus(btcHeight, w) + s := getDelStatus(d, btcHeight, w) if s != status { allChecked = false } @@ -289,6 +287,33 @@ func CheckDelsStatus(dels []*bstypes.BTCDelegation, btcHeight uint64, w uint64, return allChecked } +func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTCDelegationStatus { + if del.BtcUndelegation != nil { + if del.BtcUndelegation.JurySlashingSig != nil && + del.BtcUndelegation.JuryUnbondingSig != nil && + del.BtcUndelegation.ValidatorUnbondingSig != nil { + return bstypes.BTCDelegationStatus_UNBONDED + } + // If we received an undelegation but is still does not have all required signature, + // delegation receives UNBONING status. + // Voting power from this delegation is removed from the total voting power and now we + // are waiting for signatures from validator and jury for delegation to become expired. + // For now we do not have any unbonding time on the consumer chain, only time lock on BTC chain + // we may consider adding unbonding time on the consumer chain later to avoid situation where + // we can lose to much voting power in to short time. + return bstypes.BTCDelegationStatus_UNBONDING + } + + if del.StartHeight <= btcHeight && btcHeight+w <= del.EndHeight { + if del.JurySig != nil { + return bstypes.BTCDelegationStatus_ACTIVE + } else { + return bstypes.BTCDelegationStatus_PENDING + } + } + return bstypes.BTCDelegationStatus_UNBONDED +} + func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { // we need to ensure votes are collected at the given height require.Eventually(t, func() bool { @@ -302,12 +327,12 @@ func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num i // as the votes have been collected, the block should be finalized require.Eventually(t, func() bool { - finalized, err := tm.BabylonClient.QueryBlockFinalization(height) + b, err := tm.BabylonClient.QueryBlock(height) if err != nil { t.Logf("failed to query block at height %v: %s", height, err.Error()) return false } - return finalized + return b.Finalized }, eventuallyWaitTimeOut, eventuallyPollTime) } @@ -352,18 +377,18 @@ func (tm *TestManager) WaitForValStopped(t *testing.T, valPk *bbntypes.BIP340Pub } func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, valIns *service.ValidatorInstance) { - headerBeforeStop, err := tm.BabylonClient.QueryBestHeader() + blockBeforeStop, err := tm.BabylonClient.QueryBestBlock() require.NoError(t, err) err = valIns.Stop() require.NoError(t, err) require.Eventually(t, func() bool { - headerAfterStop, err := tm.BabylonClient.QueryBestHeader() + headerAfterStop, err := tm.BabylonClient.QueryBestBlock() if err != nil { return false } - return headerAfterStop.Header.Height >= int64(n)+headerBeforeStop.Header.Height + return headerAfterStop.Height >= uint64(n)+blockBeforeStop.Height }, eventuallyWaitTimeOut, eventuallyPollTime) t.Log("restarting the validator instance") @@ -373,9 +398,11 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, require.NoError(t, err) } -func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegation) *provider.RelayerTxResponse { - slashingTx := btcDel.SlashingTx - stakingTx := btcDel.StakingTx +func (tm *TestManager) AddJurySignature(t *testing.T, del *types.Delegation) *types.TxResponse { + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(del.SlashingTxHex) + require.NoError(t, err) + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + require.NoError(t, err) stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) @@ -390,7 +417,14 @@ func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegat ) require.NoError(t, err) - res, err := tm.BabylonClient.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingMsgTx.TxHash().String(), jurySig) + jurySchnorrSig, err := jurySig.ToBTCSig() + require.NoError(t, err) + res, err := tm.BabylonClient.SubmitJurySig( + del.ValBtcPk, + del.BtcPk, + stakingMsgTx.TxHash().String(), + jurySchnorrSig, + ) require.NoError(t, err) return res @@ -399,14 +433,16 @@ func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegat // delegation must containt undelgation object func (tm *TestManager) AddValidatorUnbondingSignature( t *testing.T, - btcDel *bstypes.BTCDelegation, + del *types.Delegation, validatorSk *btcec.PrivateKey, ) { - stakingTx := btcDel.StakingTx + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + require.NoError(t, err) stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) - unbondingTx := btcDel.BtcUndelegation.UnbondingTx + unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) + require.NoError(t, err) valSig, err := unbondingTx.Sign( stakingMsgTx, @@ -418,11 +454,13 @@ func (tm *TestManager) AddValidatorUnbondingSignature( stakingTxHash := stakingMsgTx.TxHash().String() + valSchnorrSig, err := valSig.ToBTCSig() + require.NoError(t, err) _, err = tm.BabylonClient.SubmitValidatorUnbondingSig( - btcDel.ValBtcPk, - btcDel.BtcPk, + del.ValBtcPk, + del.BtcPk, stakingTxHash, - valSig, + valSchnorrSig, ) require.NoError(t, err) } diff --git a/service/app.go b/service/app.go index 8e5c5a6b..cfb7ecca 100644 --- a/service/app.go +++ b/service/app.go @@ -17,6 +17,7 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/client" "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" "github.com/babylonchain/btc-validator/val" @@ -221,13 +222,19 @@ func (app *ValidatorApp) StartHandlingValidators() error { // AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon // Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJurySignature(btcDel *bstypes.BTCDelegation) (*AddJurySigResponse, error) { +func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySigResponse, error) { if btcDel.JurySig != nil { return nil, fmt.Errorf("the Jury sig already existed in the Bitcoin delection") } - slashingTx := btcDel.SlashingTx - stakingTx := btcDel.StakingTx + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) + if err != nil { + return nil, err + } + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) + if err != nil { + return nil, err + } stakingMsgTx, err := stakingTx.ToMsgTx() if err != nil { return nil, err @@ -251,13 +258,19 @@ func (app *ValidatorApp) AddJurySignature(btcDel *bstypes.BTCDelegation) (*AddJu stakingTxHash := stakingMsgTx.TxHash().String() - res, err := app.cc.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, jurySig) + jurySchnorrSig, err := jurySig.ToBTCSig() + if err != nil { + return nil, err + } + res, err := app.cc.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, jurySchnorrSig) + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, }).Error("failed to submit Jury signature") return nil, err } @@ -265,8 +278,8 @@ func (app *ValidatorApp) AddJurySignature(btcDel *bstypes.BTCDelegation) (*AddJu if res == nil { app.logger.WithFields(logrus.Fields{ "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, }).Error("failed to submit Jury signature") return nil, fmt.Errorf("failed to submit Jury signature due to known error") } @@ -278,23 +291,23 @@ func (app *ValidatorApp) AddJurySignature(btcDel *bstypes.BTCDelegation) (*AddJu // AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon // Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegation) (*AddJurySigResponse, error) { - if btcDel == nil { +func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*AddJurySigResponse, error) { + if del == nil { return nil, fmt.Errorf("btc delegation is nil") } - if btcDel.BtcUndelegation == nil { + if del.BtcUndelegation == nil { return nil, fmt.Errorf("delegation does not have an unbonding transaction") } - if btcDel.BtcUndelegation.ValidatorUnbondingSig == nil { + if del.BtcUndelegation.ValidatorUnbondingSig == nil { return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") } // In normal operation it is not possible to have one of this signatures and not have the other // as only way to update this fields in delegation is by processing the MsgAddJuryUnbondingSigs msg // which should update both fields at atomically in case of successfull transaction. - if btcDel.BtcUndelegation.JurySlashingSig != nil || btcDel.BtcUndelegation.JuryUnbondingSig != nil { + if del.BtcUndelegation.JurySlashingSig != nil || del.BtcUndelegation.JuryUnbondingSig != nil { return nil, fmt.Errorf("delegation already has required jury signatures") } @@ -305,14 +318,21 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio } // 1. Sign unbonding transaction - stakingTx := btcDel.StakingTx + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + if err != nil { + return nil, err + } stakingMsgTx, err := stakingTx.ToMsgTx() if err != nil { return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) } - juryUnbondingSig, err := btcDel.BtcUndelegation.UnbondingTx.Sign( + unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) + if err != nil { + return nil, err + } + juryUnbondingSig, err := unbondingTx.Sign( stakingMsgTx, stakingTx.Script, juryPrivKey, @@ -324,15 +344,17 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio } // 2. Sign slash unbonding transaction - slashUnbondigTx := btcDel.BtcUndelegation.SlashingTx - unbondingTx := btcDel.BtcUndelegation.UnbondingTx + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + if err != nil { + return nil, err + } unbondingMsgTx, err := unbondingTx.ToMsgTx() if err != nil { return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) } - jurySlashingUnbondingSig, err := slashUnbondigTx.Sign( + jurySlashingUnbondingSig, err := slashUnbondingTx.Sign( unbondingMsgTx, unbondingTx.Script, juryPrivKey, @@ -344,19 +366,30 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio stakingTxHash := stakingMsgTx.TxHash().String() + juryUnbondingSchnorrSig, err := juryUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } + jurySlashingUnbondingShcnorrSig, err := jurySlashingUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } res, err := app.cc.SubmitJuryUnbondingSigs( - btcDel.ValBtcPk, - btcDel.BtcPk, + del.ValBtcPk, + del.BtcPk, stakingTxHash, - juryUnbondingSig, - jurySlashingUnbondingSig, + juryUnbondingSchnorrSig, + jurySlashingUnbondingShcnorrSig, ) + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() + if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, }).Error("failed to submit Jury signature") return nil, err } @@ -364,8 +397,8 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegatio if res == nil { app.logger.WithFields(logrus.Fields{ "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, }).Error("failed to submit Jury signature") return nil, fmt.Errorf("failed to submit Jury signature due to known error") } diff --git a/service/app_test.go b/service/app_test.go index 353181eb..caf018c8 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -9,8 +9,6 @@ import ( bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/chaincfg" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/relayer/v2/relayer/provider" secp256k12 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" @@ -20,6 +18,7 @@ import ( "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" + "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -71,16 +70,18 @@ func FuzzRegisterValidator(f *testing.F) { BtcSig: btcSig.MustMarshal(), BtcSigType: bstypes.BTCSigType_BIP340, } + popBytes, err := pop.Marshal() + require.NoError(t, err) txHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). RegisterValidator( - validator.GetBabylonPK(), - validator.MustGetBIP340BTCPK(), - pop, - testutil.ZeroCommissionRate(), - testutil.EmptyDescription(), - ).Return(&provider.RelayerTxResponse{TxHash: txHash}, nil).AnyTimes() + validator.GetBabylonPK().Key, + validator.MustGetBIP340BTCPK().MustToBTCPK(), + popBytes, + testutil.ZeroCommissionRate().BigInt(), + testutil.EmptyDescription().String(), + ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() res, err := app.RegisterValidator(validator.MustGetBIP340BTCPK().MarshalHex()) require.NoError(t, err) @@ -155,27 +156,28 @@ func FuzzAddJurySig(f *testing.F) { stakingValue := int64(2 * 10e8) stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, juryPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) require.NoError(t, err) - delBabylonSK, delBabylonPK, err := datagen.GenRandomSecp256k1KeyPair(r) - require.NoError(t, err) - pop, err := bstypes.NewPoP(delBabylonSK, delSK) require.NoError(t, err) + stakingTxHex, err := stakingTx.ToHexStr() require.NoError(t, err) - delegation := &bstypes.BTCDelegation{ - ValBtcPk: btcPkBIP340, - BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPK), - BabylonPk: delBabylonPK.(*secp256k1.PubKey), - Pop: pop, - StakingTx: stakingTx, - SlashingTx: slashingTx, + delegation := &types.Delegation{ + ValBtcPk: btcPkBIP340.MustToBTCPK(), + BtcPk: delPK, + StakingTxHex: stakingTxHex, + SlashingTxHex: slashingTx.ToHexStr(), } stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryBTCDelegations(bstypes.BTCDelegationStatus_PENDING, gomock.Any()). - Return([]*bstypes.BTCDelegation{delegation}, nil).AnyTimes() - mockClientController.EXPECT().SubmitJurySig(delegation.ValBtcPk, delegation.BtcPk, stakingMsgTx.TxHash().String(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + mockClientController.EXPECT().QueryPendingDelegations(gomock.Any()). + Return([]*types.Delegation{delegation}, nil).AnyTimes() + mockClientController.EXPECT().SubmitJurySig( + delegation.ValBtcPk, + delegation.BtcPk, + stakingMsgTx.TxHash().String(), + gomock.Any(), + ). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() res, err := app.AddJurySignature(delegation) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) diff --git a/service/chain_poller.go b/service/chain_poller.go index a80ff612..046e73dd 100644 --- a/service/chain_poller.go +++ b/service/chain_poller.go @@ -6,7 +6,6 @@ import ( "time" "github.com/avast/retry-go/v4" - ctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" @@ -98,36 +97,40 @@ func (cp *ChainPoller) GetBlockInfoChan() <-chan *types.BlockInfo { return cp.blockInfoChan } -func (cp *ChainPoller) nodeStatusWithRetry() (*ctypes.ResultStatus, error) { - var response *ctypes.ResultStatus +func (cp *ChainPoller) latestBlockWithRetry() (*types.BlockInfo, error) { + var ( + latestBlock *types.BlockInfo + err error + ) if err := retry.Do(func() error { - status, err := cp.cc.QueryNodeStatus() + latestBlock, err = cp.cc.QueryBestBlock() if err != nil { return err } - response = status return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { cp.logger.WithFields(logrus.Fields{ "attempt": n + 1, "max_attempts": RtyAttNum, "error": err, - }).Debug("Failed to query babylon For the latest height") + }).Debug("failed to query the consumer chain for the latest block") })); err != nil { return nil, err } - return response, nil + return latestBlock, nil } -func (cp *ChainPoller) headerWithRetry(height uint64) (*ctypes.ResultHeader, error) { - var response *ctypes.ResultHeader +func (cp *ChainPoller) blockWithRetry(height uint64) (*types.BlockInfo, error) { + var ( + block *types.BlockInfo + err error + ) if err := retry.Do(func() error { - headerResult, err := cp.cc.QueryHeader(int64(height)) + block, err = cp.cc.QueryBlock(height) if err != nil { return err } - response = headerResult return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { cp.logger.WithFields(logrus.Fields{ @@ -135,12 +138,12 @@ func (cp *ChainPoller) headerWithRetry(height uint64) (*ctypes.ResultHeader, err "max_attempts": RtyAttNum, "height": height, "error": err, - }).Debug("failed to query the consumer chain for the header") + }).Debug("failed to query the consumer chain for the block") })); err != nil { return nil, err } - return response, nil + return block, nil } func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { @@ -153,7 +156,7 @@ func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { var currentBestChainHeight uint64 for { - status, err := cp.nodeStatusWithRetry() + lastestBlock, err := cp.latestBlockWithRetry() if err != nil { cp.logger.WithFields(logrus.Fields{ "error": err, @@ -161,7 +164,7 @@ func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { continue } - currentBestChainHeight = uint64(status.SyncInfo.LatestBlockHeight) + currentBestChainHeight = lastestBlock.Height break } @@ -173,52 +176,65 @@ func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { return nil } +// waitForActivation waits until BTC staking is activated +func (cp *ChainPoller) waitForActivation() { + // ensure that the startHeight is no lower than the activated height + for { + activatedHeight, err := cp.cc.QueryActivatedHeight() + if err != nil { + cp.logger.WithFields(logrus.Fields{ + "error": err, + }).Debug("failed to query the consumer chain for the activated height") + } else { + if cp.GetNextHeight() < activatedHeight { + cp.SetNextHeight(activatedHeight) + } + return + } + + select { + case <-time.After(cp.cfg.PollInterval): + + case <-cp.quit: + return + } + } + +} + func (cp *ChainPoller) pollChain() { defer cp.wg.Done() + cp.waitForActivation() + var failedCycles uint64 for { // TODO: Handlig of request cancellation, as otherwise shutdown will be blocked // until request is finished - headerToRetrieve := cp.GetNextHeight() - result, err := cp.headerWithRetry(headerToRetrieve) - if err == nil && result.Header != nil { + blockToRetrieve := cp.GetNextHeight() + block, err := cp.blockWithRetry(blockToRetrieve) + if err != nil { + failedCycles++ + cp.logger.WithFields(logrus.Fields{ + "error": err, + "currFailures": failedCycles, + "blockToGet": blockToRetrieve, + }).Error("failed to query the consumer chain for the block") + } else { // no error and we got the header we wanted to get, bump the state and push // notification about data - cp.SetNextHeight(headerToRetrieve + 1) + cp.SetNextHeight(blockToRetrieve + 1) failedCycles = 0 cp.logger.WithFields(logrus.Fields{ - "height": result.Header.Height, - }).Info("the poller retrieved the header from the consumer chain") + "height": block.Height, + }).Info("the poller retrieved the block from the consumer chain") // Push the data to the channel. // If the cosumers are to slow i.e the buffer is full, this will block and we will // stop retrieving data from the node. - cp.blockInfoChan <- &types.BlockInfo{ - Height: uint64(result.Header.Height), - LastCommitHash: result.Header.LastCommitHash, - } - - } else if err == nil && result.Header == nil { - // no error but header is nil, means the header is not found on node - failedCycles++ - - cp.logger.WithFields(logrus.Fields{ - "error": err, - "currFailures": failedCycles, - "headerToGet": headerToRetrieve, - }).Error("failed to retrieve header from the consumer chain. Header did not produced yet") - - } else { - failedCycles++ - - cp.logger.WithFields(logrus.Fields{ - "error": err, - "currFailures": failedCycles, - "headerToGet": headerToRetrieve, - }).Error("failed to query the consumer chain for the header") + cp.blockInfoChan <- block } if failedCycles > maxFailedCycles { diff --git a/service/event_loop.go b/service/event_loop.go index 8171343b..dd39d0c3 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "time" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" @@ -22,7 +21,7 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { select { case <-jurySigTicker.C: // 1. Get all pending delegations first, this are more important than the unbonding ones - dels, err := app.cc.QueryBTCDelegations(btcstakingtypes.BTCDelegationStatus_PENDING, limit) + dels, err := app.cc.QueryPendingDelegations(limit) if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, @@ -43,7 +42,7 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { } } // 2. Get all unbonding delegations - unbondingDels, err := app.cc.QueryBTCDelegations(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) + unbondingDels, err := app.cc.QueryUnbondingDelegations(limit) if err != nil { app.logger.WithFields(logrus.Fields{ @@ -131,7 +130,19 @@ func (app *ValidatorApp) registrationLoop() { // we won't do any retries here to not block the loop for more important messages. // Most probably it fails due so some user error so we just return the error to the user. // TODO: need to start passing context here to be able to cancel the request in case of app quiting - res, err := app.cc.RegisterValidator(req.bbnPubKey, req.btcPubKey, req.pop, req.commission, req.description) + popBytes, err := req.pop.Marshal() + if err != nil { + req.errResponse <- err + continue + } + + res, err := app.cc.RegisterValidator( + req.bbnPubKey.Key, + req.btcPubKey.MustToBTCPK(), + popBytes, + req.commission.BigInt(), + req.description.String(), + ) if err != nil { app.logger.WithFields(logrus.Fields{ diff --git a/service/fastsync.go b/service/fastsync.go index d17b958b..bb6b679c 100644 --- a/service/fastsync.go +++ b/service/fastsync.go @@ -3,14 +3,13 @@ package service import ( "fmt" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/types" ) type FastSyncResult struct { - Responses []*provider.RelayerTxResponse + Responses []*types.TxResponse SyncedHeight uint64 LastProcessedHeight uint64 } @@ -30,7 +29,7 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe } var syncedHeight uint64 - responses := make([]*provider.RelayerTxResponse, 0) + responses := make([]*types.TxResponse, 0) // we may need several rounds to catch-up as we need to limit // the catch-up distance for each round to avoid memory overflow for startHeight <= endHeight { diff --git a/service/fastsync_test.go b/service/fastsync_test.go index 72bdf54f..6fad58ce 100644 --- a/service/fastsync_test.go +++ b/service/fastsync_test.go @@ -4,7 +4,6 @@ import ( "math/rand" "testing" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -20,7 +19,7 @@ func FuzzFastSync(f *testing.F) { randomStartingHeight := uint64(r.Int63n(100) + 1) finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} + startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() @@ -30,25 +29,23 @@ func FuzzFastSync(f *testing.F) { // commit public randomness expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() + CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() res, err := valIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). Return(uint64(1), nil).AnyTimes() // fast sync catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) expectedTxHash = testutil.GenRandomHexStr(r, 32) - finalizedBlock := &types.BlockInfo{Height: finalizedHeight, LastCommitHash: testutil.GenRandomByteArray(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(valIns.GetBtcPkBIP340(), catchUpBlocks, gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + mockClientController.EXPECT().SubmitBatchFinalitySigs(valIns.MustGetBtcPk(), catchUpBlocks, gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() result, err := valIns.FastSync(finalizedHeight+1, currentHeight) require.NoError(t, err) require.NotNil(t, result) diff --git a/service/rpcserver.go b/service/rpcserver.go index ed93ed73..eeae0a95 100644 --- a/service/rpcserver.go +++ b/service/rpcserver.go @@ -152,8 +152,8 @@ func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFina } b := &types.BlockInfo{ - Height: req.Height, - LastCommitHash: req.LastCommitHash, + Height: req.Height, + Hash: req.LastCommitHash, } txRes, privKey, err := v.TestSubmitFinalitySignatureAndExtractPrivKey(b) diff --git a/service/validator_instance.go b/service/validator_instance.go index c5ff074a..a734a02b 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -9,11 +9,10 @@ import ( "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + types2 "github.com/babylonchain/babylon/x/btcstaking/types" ftypes "github.com/babylonchain/babylon/x/finality/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/gogo/protobuf/jsonpb" "github.com/sirupsen/logrus" "go.uber.org/atomic" @@ -111,7 +110,7 @@ func (v *ValidatorInstance) Start() error { v.poller = poller - v.laggingTargetChan = make(chan *types.BlockInfo) + v.laggingTargetChan = make(chan *types.BlockInfo, 1) v.quit = make(chan struct{}) @@ -173,11 +172,15 @@ func (v *ValidatorInstance) IsRunning() bool { func (v *ValidatorInstance) signUnbondingTransactions( privKey *btcec.PrivateKey, - toSign []*bstypes.BTCDelegation) ([]unbondingTxSigData, error) { + toSign []*types.Delegation) ([]unbondingTxSigData, error) { var dataWithSignatures []unbondingTxSigData for _, delegation := range toSign { - fundingTx, err := delegation.StakingTx.ToMsgTx() + stakingTx, err := types2.NewBabylonTaprootTxFromHex(delegation.StakingTxHex) + if err != nil { + return nil, err + } + fundingTx, err := stakingTx.ToMsgTx() if err != nil { return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) @@ -185,11 +188,14 @@ func (v *ValidatorInstance) signUnbondingTransactions( fundingTxHash := fundingTx.TxHash().String() - txToSign := delegation.BtcUndelegation.UnbondingTx + txToSign, err := types2.NewBabylonTaprootTxFromHex(delegation.BtcUndelegation.UnbondingTxHex) + if err != nil { + return nil, err + } sig, err := txToSign.Sign( fundingTx, - delegation.StakingTx.Script, + stakingTx.Script, privKey, &v.cfg.ActiveNetParams, ) @@ -199,7 +205,7 @@ func (v *ValidatorInstance) signUnbondingTransactions( } utd := unbondingTxSigData{ - stakerPk: delegation.BtcPk, + stakerPk: bbntypes.NewBIP340PubKeyFromBTCPK(delegation.BtcPk), stakingTxHash: fundingTxHash, signature: sig, } @@ -218,11 +224,18 @@ func (v *ValidatorInstance) sendSignaturesForUnbondingTransactions(sigsToSend [] for _, sigData := range sigsToSend { sd := sigData eg.Go(func() error { - _, err := v.cc.SubmitValidatorUnbondingSig( - v.GetBtcPkBIP340(), - sd.stakerPk, + schnorrSig, err := sd.signature.ToBTCSig() + if err != nil { + res = append(res, unbondingTxSigSendResult{ + err: err, + stakingTxHash: sd.stakingTxHash, + }) + } + _, err = v.cc.SubmitValidatorUnbondingSig( + v.MustGetBtcPk(), + sd.stakerPk.MustToBTCPK(), sd.stakingTxHash, - sd.signature, + schnorrSig, ) mu.Lock() @@ -262,7 +275,7 @@ func (v *ValidatorInstance) unbondindSigSubmissionLoop() { select { case <-sendUnbondingSigTicker.C: delegationsNeedingSignatures, err := v.cc.QueryBTCValidatorUnbondingDelegations( - v.GetBtcPkBIP340(), + v.MustGetBtcPk(), // TODO: parameterize the max number of delegations to be queried // it should not be to high to not take too long time to sign them 10, @@ -476,7 +489,6 @@ func (v *ValidatorInstance) checkLaggingLoop() { v.isLagging.Store(true) v.laggingTargetChan <- latestBlock } - case <-v.quit: v.logger.Debug("the fast sync loop is closing") return @@ -529,6 +541,8 @@ func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSync return nil, fmt.Errorf("the start height %v should not be higher than the current block %v", startHeight, targetBlock.Height) } + v.logger.Debug("the validator is entering fast sync") + return v.FastSync(startHeight, targetBlock.Height) } @@ -589,7 +603,7 @@ func (v *ValidatorInstance) checkLagging(currentBlock *types.BlockInfo) bool { // 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 (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { +func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { var failedCycles uint64 // we break the for loop if the block is finalized or the signature is successfully submitted @@ -618,7 +632,7 @@ func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targ select { case <-time.After(v.cfg.SubmissionRetryInterval): // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.cc.QueryBlockFinalization(targetBlock.Height) + finalized, err := v.checkBlockFinalization(targetBlock.Height) if err != nil { return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) } @@ -637,9 +651,18 @@ func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targ } } +func (v *ValidatorInstance) checkBlockFinalization(height uint64) (bool, error) { + b, err := v.cc.QueryBlock(height) + if err != nil { + return false, err + } + + 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 (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { +func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { var failedCycles uint64 // we break the for loop if the block is finalized or the public rand is successfully committed @@ -669,7 +692,7 @@ func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *t select { case <-time.After(v.cfg.SubmissionRetryInterval): // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.cc.QueryBlockFinalization(targetBlock.Height) + finalized, err := v.checkBlockFinalization(targetBlock.Height) if err != nil { return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) } @@ -691,21 +714,8 @@ func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *t // CommitPubRand generates a list of Schnorr rand pairs, // commits the public randomness for the managed validators, // and save the randomness pair to DB -func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { - lastCommittedHeight, err := v.cc.QueryHeightWithLastPubRand(v.btcPk) - if err != nil { - return nil, fmt.Errorf("failed to query the consumer chain for the last committed height: %w", err) - } - - // NOTE: this check will cause failure to the case when the program dies - // after committing randomness to babylon but before we update the last_committed_height - // TODO: consider remove this check - if v.GetLastCommittedHeight() != lastCommittedHeight { - // for some reason number of random numbers locally does not match the chain node - // log it and try to recover somehow - return nil, fmt.Errorf("the local last committed height %v does not match the remote last committed height %v", - v.GetLastCommittedHeight(), lastCommittedHeight) - } +func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxResponse, error) { + lastCommittedHeight := v.GetLastCommittedHeight() var startHeight uint64 if lastCommittedHeight == uint64(0) { @@ -751,9 +761,12 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider. if err != nil { return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) } - sig := bbntypes.NewBIP340SignatureFromBTCSig(schnorrSig) - res, err := v.cc.CommitPubRandList(v.btcPk, startHeight, pubRandList, &sig) + pubRandByteList := make([]*btcec.FieldVal, 0, len(pubRandList)) + for _, r := range pubRandList { + pubRandByteList = append(pubRandByteList, r.ToFieldVal()) + } + res, err := v.cc.CommitPubRandList(v.MustGetBtcPk(), startHeight, pubRandByteList, schnorrSig) if err != nil { // TODO Add retry. check issue: https://github.com/babylonchain/btc-validator/issues/34 return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) @@ -786,14 +799,14 @@ func (v *ValidatorInstance) createPubRandList(startHeight uint64) ([]bbntypes.Sc } // SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain -func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*provider.RelayerTxResponse, error) { +func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*types.TxResponse, error) { eotsSig, err := v.signEotsSig(b) if err != nil { return nil, err } // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.GetBtcPkBIP340(), b.Height, b.LastCommitHash, eotsSig) + res, err := v.cc.SubmitFinalitySig(v.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) if err != nil { return nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) } @@ -806,22 +819,22 @@ func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*provid // SubmitBatchFinalitySignatures builds and sends a finality signature over the given block to the consumer chain // NOTE: the input blocks should be in the ascending order of height -func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*provider.RelayerTxResponse, error) { +func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*types.TxResponse, error) { if len(blocks) == 0 { return nil, fmt.Errorf("should not submit batch finality signature with zero block") } - sigs := make([]*bbntypes.SchnorrEOTSSig, 0, len(blocks)) + sigs := make([]*btcec.ModNScalar, 0, len(blocks)) for _, b := range blocks { eotsSig, err := v.signEotsSig(b) if err != nil { return nil, err } - sigs = append(sigs, eotsSig) + sigs = append(sigs, eotsSig.ToModNScalar()) } // send finality signature to the consumer chain - res, err := v.cc.SubmitBatchFinalitySigs(v.GetBtcPkBIP340(), blocks, sigs) + res, err := v.cc.SubmitBatchFinalitySigs(v.MustGetBtcPk(), blocks, sigs) if err != nil { return nil, fmt.Errorf("failed to send a batch of finality signatures to the consumer chain: %w", err) } @@ -838,7 +851,7 @@ func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEO msg := &ftypes.MsgAddFinalitySig{ ValBtcPk: v.btcPk, BlockHeight: b.Height, - BlockLastCommitHash: b.LastCommitHash, + BlockLastCommitHash: b.Hash, } msgToSign := msg.MsgToSign() sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height) @@ -852,7 +865,7 @@ func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEO // TestSubmitFinalitySignatureAndExtractPrivKey is exposed for presentation/testing purpose to allow manual sending finality signature // 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 (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*provider.RelayerTxResponse, *btcec.PrivateKey, error) { +func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { // check last committed height if v.GetLastCommittedHeight() < b.Height { return nil, nil, fmt.Errorf("the validator's last committed height %v is lower than the current block height %v", @@ -865,7 +878,7 @@ func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *type } // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.GetBtcPkBIP340(), b.Height, b.LastCommitHash, eotsSig) + res, err := v.cc.SubmitFinalitySig(v.MustGetBtcPk(), 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) } @@ -945,17 +958,16 @@ func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*typ } func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { - var latestBlock *types.BlockInfo + var ( + latestBlock *types.BlockInfo + err error + ) if err := retry.Do(func() error { - headerResult, err := v.cc.QueryBestHeader() + latestBlock, err = v.cc.QueryBestBlock() if err != nil { return err } - latestBlock = &types.BlockInfo{ - Height: uint64(headerResult.Header.Height), - LastCommitHash: headerResult.Header.LastCommitHash, - } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { v.logger.WithFields(logrus.Fields{ @@ -977,7 +989,7 @@ func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, erro ) if err := retry.Do(func() error { - power, err = v.cc.QueryValidatorVotingPower(v.GetBtcPkBIP340(), height) + power, err = v.cc.QueryValidatorVotingPower(v.MustGetBtcPk(), height) if err != nil { return err } @@ -995,17 +1007,17 @@ func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, erro return power, nil } -func (v *ValidatorInstance) GetSlashedHeightWithRetry() (uint64, error) { +func (v *ValidatorInstance) GetValidatorSlashedWithRetry() (bool, error) { var ( - slashedHeight uint64 + slashed bool + err error ) if err := retry.Do(func() error { - res, err := v.cc.QueryValidator(v.GetBtcPkBIP340()) + slashed, err = v.cc.QueryValidatorSlashed(v.MustGetBtcPk()) if err != nil { return err } - slashedHeight = res.SlashedBtcHeight return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { v.logger.WithFields(logrus.Fields{ @@ -1014,8 +1026,8 @@ func (v *ValidatorInstance) GetSlashedHeightWithRetry() (uint64, error) { "error": err, }).Debug("failed to query the voting power") })); err != nil { - return 0, err + return false, err } - return slashedHeight, nil + return slashed, nil } diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go index ed19f3a9..39c448a8 100644 --- a/service/validator_instance_test.go +++ b/service/validator_instance_test.go @@ -5,7 +5,6 @@ import ( "os" "testing" - "github.com/cosmos/relayer/v2/relayer/provider" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -26,22 +25,20 @@ func FuzzCommitPubRandList(f *testing.F) { randomStartingHeight := uint64(r.Int63n(100) + 1) currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} + 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() app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) require.NoError(t, err) expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() + CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() res, err := valIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) @@ -59,12 +56,12 @@ func FuzzSubmitFinalitySig(f *testing.F) { randomStartingHeight := uint64(r.Int63n(100) + 1) currentHeight := randomStartingHeight + uint64(r.Int63n(10)+1) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} + 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() app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) require.NoError(t, err) @@ -72,28 +69,26 @@ func FuzzSubmitFinalitySig(f *testing.F) { // commit public randomness expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() + CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() res, err := valIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). Return(uint64(1), nil).AnyTimes() // submit finality sig nextBlock := &types.BlockInfo{ - Height: startingBlock.Height + 1, - LastCommitHash: testutil.GenRandomByteArray(r, 32), + Height: startingBlock.Height + 1, + Hash: testutil.GenRandomByteArray(r, 32), } expectedTxHash = testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - SubmitFinalitySig(valIns.GetBtcPkBIP340(), nextBlock.Height, nextBlock.LastCommitHash, gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err = valIns.SubmitFinalitySignature(nextBlock) + SubmitFinalitySig(valIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + providerRes, err := valIns.SubmitFinalitySignature(nextBlock) require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) + require.Equal(t, expectedTxHash, providerRes.TxHash) // check the last_voted_height require.Equal(t, nextBlock.Height, valIns.GetLastVotedHeight()) diff --git a/service/validator_manager.go b/service/validator_manager.go index a1da37ea..e1e4d844 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -153,7 +153,7 @@ func (vm *ValidatorManager) monitorStatusUpdate() { } continue } - slashedHeight, err := v.GetSlashedHeightWithRetry() + slashed, err := v.GetValidatorSlashedWithRetry() if err != nil { vm.logger.WithFields(logrus.Fields{ "err": err, @@ -161,13 +161,12 @@ func (vm *ValidatorManager) monitorStatusUpdate() { }).Debug("failed to get the slashed height") continue } - // power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the validator instance - if slashedHeight > 0 { + // power == 0 and slashed == true, set status to SLASHED and stop and remove the validator instance + if slashed { vm.setValidatorSlashed(v) vm.logger.WithFields(logrus.Fields{ - "val_btc_pk": v.GetBtcPkHex(), - "old_status": oldStatus, - "slashed_height": slashedHeight, + "val_btc_pk": v.GetBtcPkHex(), + "old_status": oldStatus, }).Debug("the validator status has been slashed") continue } @@ -312,17 +311,16 @@ func (vm *ValidatorManager) addValidatorInstance( } func (vm *ValidatorManager) getLatestBlockWithRetry() (*types.BlockInfo, error) { - var latestBlock *types.BlockInfo + var ( + latestBlock *types.BlockInfo + err error + ) if err := retry.Do(func() error { - headerResult, err := vm.cc.QueryBestHeader() + latestBlock, err = vm.cc.QueryBestBlock() if err != nil { return err } - latestBlock = &types.BlockInfo{ - Height: uint64(headerResult.Header.Height), - LastCommitHash: headerResult.Header.LastCommitHash, - } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { vm.logger.WithFields(logrus.Fields{ diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index dc323efc..50984056 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -7,10 +7,7 @@ import ( "time" "github.com/babylonchain/babylon/testutil/datagen" - "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - coretypes "github.com/cometbft/cometbft/rpc/core/types" - cometbfttypes "github.com/cometbft/cometbft/types" + bbntypes "github.com/babylonchain/babylon/types" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -21,6 +18,7 @@ import ( "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/testutil/mocks" + "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -42,29 +40,22 @@ func FuzzStatusUpdate(f *testing.F) { // setup mocks currentHeight := uint64(r.Int63n(100) + 1) - currentHeaderRes := &coretypes.ResultHeader{ - Header: &cometbfttypes.Header{ - Height: int64(currentHeight), - LastCommitHash: datagen.GenRandomByteArray(r, 32), - }, + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + Hash: datagen.GenRandomByteArray(r, 32), } - mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() - status := &coretypes.ResultStatus{ - SyncInfo: coretypes.SyncInfo{LatestBlockHeight: int64(currentHeight)}, - } - mockClientController.EXPECT().QueryNodeStatus().Return(status, nil).AnyTimes() + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().Close().Return(nil).AnyTimes() mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() - mockClientController.EXPECT().QueryHeader(gomock.Any()).Return(currentHeaderRes, nil).AnyTimes() + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + mockClientController.EXPECT().QueryBlock(gomock.Any()).Return(currentBlockRes, nil).AnyTimes() votingPower := uint64(r.Intn(2)) mockClientController.EXPECT().QueryValidatorVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() var slashedHeight uint64 if votingPower == 0 { - slashedHeight = uint64(r.Intn(2)) - btcVal := &bstypes.BTCValidator{SlashedBtcHeight: slashedHeight} - mockClientController.EXPECT().QueryValidator(gomock.Any()).Return(btcVal, nil).AnyTimes() + mockClientController.EXPECT().QueryValidatorSlashed(gomock.Any()).Return(true, nil).AnyTimes() } err := vm.Start() @@ -124,7 +115,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) btcPkBytes, err := em.CreateKey(keyName, "") require.NoError(t, err) - btcPk, err := types.NewBIP340PubKey(btcPkBytes) + btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) bbnPk, err := kc.CreateChainKey() require.NoError(t, err) diff --git a/testutil/datagen.go b/testutil/datagen.go index 2ec5cace..d5f160bd 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -73,8 +73,8 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { blocks := make([]*types.BlockInfo, 0) for i := startHeight; i <= endHeight; i++ { b := &types.BlockInfo{ - Height: i, - LastCommitHash: datagen.GenRandomLastCommitHash(r), + Height: i, + Hash: datagen.GenRandomLastCommitHash(r), } blocks = append(blocks, b) } diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index d489fa55..fafb244a 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -5,17 +5,12 @@ package mocks import ( + big "math/big" reflect "reflect" - types "github.com/babylonchain/babylon/types" - types0 "github.com/babylonchain/babylon/x/btcstaking/types" - clientcontroller "github.com/babylonchain/btc-validator/clientcontroller" - types1 "github.com/babylonchain/btc-validator/types" - coretypes "github.com/cometbft/cometbft/rpc/core/types" - secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - types2 "github.com/cosmos/cosmos-sdk/types" - types3 "github.com/cosmos/cosmos-sdk/x/staking/types" - provider "github.com/cosmos/relayer/v2/relayer/provider" + types "github.com/babylonchain/btc-validator/types" + btcec "github.com/btcsuite/btcd/btcec/v2" + schnorr "github.com/btcsuite/btcd/btcec/v2/schnorr" gomock "github.com/golang/mock/gomock" ) @@ -57,286 +52,557 @@ func (mr *MockClientControllerMockRecorder) Close() *gomock.Call { } // CommitPubRandList mocks base method. -func (m *MockClientController) CommitPubRandList(btcPubKey *types.BIP340PubKey, startHeight uint64, pubRandList []types.SchnorrPubRand, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { +func (m *MockClientController) CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitPubRandList", btcPubKey, startHeight, pubRandList, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "CommitPubRandList", valPk, 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(btcPubKey, startHeight, pubRandList, sig interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) CommitPubRandList(valPk, startHeight, pubRandList, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), btcPubKey, startHeight, pubRandList, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), valPk, startHeight, pubRandList, sig) } -// GetStakingParams mocks base method. -func (m *MockClientController) GetStakingParams() (*clientcontroller.StakingParams, error) { +// QueryActivatedHeight mocks base method. +func (m *MockClientController) QueryActivatedHeight() (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStakingParams") - ret0, _ := ret[0].(*clientcontroller.StakingParams) + ret := m.ctrl.Call(m, "QueryActivatedHeight") + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetStakingParams indicates an expected call of GetStakingParams. -func (mr *MockClientControllerMockRecorder) GetStakingParams() *gomock.Call { +// QueryActivatedHeight indicates an expected call of QueryActivatedHeight. +func (mr *MockClientControllerMockRecorder) QueryActivatedHeight() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakingParams", reflect.TypeOf((*MockClientController)(nil).GetStakingParams)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockClientController)(nil).QueryActivatedHeight)) } -// QueryBTCDelegations mocks base method. -func (m *MockClientController) QueryBTCDelegations(status types0.BTCDelegationStatus, limit uint64) ([]*types0.BTCDelegation, error) { +// QueryBTCValidatorUnbondingDelegations mocks base method. +func (m *MockClientController) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBTCDelegations", status, limit) - ret0, _ := ret[0].([]*types0.BTCDelegation) + ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valPk, max) + ret0, _ := ret[0].([]*types.Delegation) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBTCDelegations indicates an expected call of QueryBTCDelegations. -func (mr *MockClientControllerMockRecorder) QueryBTCDelegations(status, limit interface{}) *gomock.Call { +// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. +func (mr *MockClientControllerMockRecorder) QueryBTCValidatorUnbondingDelegations(valPk, max interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCDelegations), status, limit) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCValidatorUnbondingDelegations), valPk, max) } -// QueryBTCValidatorUnbondingDelegations mocks base method. -func (m *MockClientController) QueryBTCValidatorUnbondingDelegations(valBtcPk *types.BIP340PubKey, max uint64) ([]*types0.BTCDelegation, error) { +// QueryBestBlock mocks base method. +func (m *MockClientController) QueryBestBlock() (*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valBtcPk, max) - ret0, _ := ret[0].([]*types0.BTCDelegation) + ret := m.ctrl.Call(m, "QueryBestBlock") + ret0, _ := ret[0].(*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. -func (mr *MockClientControllerMockRecorder) QueryBTCValidatorUnbondingDelegations(valBtcPk, max interface{}) *gomock.Call { +// QueryBestBlock indicates an expected call of QueryBestBlock. +func (mr *MockClientControllerMockRecorder) QueryBestBlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockClientController)(nil).QueryBestBlock)) +} + +// QueryBlock mocks base method. +func (m *MockClientController) QueryBlock(height uint64) (*types.BlockInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryBlock", height) + ret0, _ := ret[0].(*types.BlockInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryBlock indicates an expected call of QueryBlock. +func (mr *MockClientControllerMockRecorder) QueryBlock(height interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockClientController)(nil).QueryBlock), height) +} + +// QueryBlocks mocks base method. +func (m *MockClientController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) + ret0, _ := ret[0].([]*types.BlockInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryBlocks indicates an expected call of QueryBlocks. +func (mr *MockClientControllerMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockClientController)(nil).QueryBlocks), startHeight, endHeight, limit) +} + +// QueryLatestFinalizedBlocks mocks base method. +func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) + ret0, _ := ret[0].([]*types.BlockInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. +func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockClientController)(nil).QueryLatestFinalizedBlocks), count) +} + +// QueryPendingDelegations mocks base method. +func (m *MockClientController) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryPendingDelegations", limit) + ret0, _ := ret[0].([]*types.Delegation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryPendingDelegations indicates an expected call of QueryPendingDelegations. +func (mr *MockClientControllerMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCValidatorUnbondingDelegations), valBtcPk, max) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryPendingDelegations), limit) } -// QueryBestHeader mocks base method. -func (m *MockClientController) QueryBestHeader() (*coretypes.ResultHeader, error) { +// QueryUnbondingDelegations mocks base method. +func (m *MockClientController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBestHeader") - ret0, _ := ret[0].(*coretypes.ResultHeader) + ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) + ret0, _ := ret[0].([]*types.Delegation) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBestHeader indicates an expected call of QueryBestHeader. -func (mr *MockClientControllerMockRecorder) QueryBestHeader() *gomock.Call { +// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. +func (mr *MockClientControllerMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestHeader", reflect.TypeOf((*MockClientController)(nil).QueryBestHeader)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondingDelegations), limit) } -// QueryBlockFinalization mocks base method. -func (m *MockClientController) QueryBlockFinalization(height uint64) (bool, error) { +// QueryValidatorSlashed mocks base method. +func (m *MockClientController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBlockFinalization", height) + ret := m.ctrl.Call(m, "QueryValidatorSlashed", valPk) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBlockFinalization indicates an expected call of QueryBlockFinalization. -func (mr *MockClientControllerMockRecorder) QueryBlockFinalization(height interface{}) *gomock.Call { +// QueryValidatorSlashed indicates an expected call of QueryValidatorSlashed. +func (mr *MockClientControllerMockRecorder) QueryValidatorSlashed(valPk interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlockFinalization", reflect.TypeOf((*MockClientController)(nil).QueryBlockFinalization), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorSlashed", reflect.TypeOf((*MockClientController)(nil).QueryValidatorSlashed), valPk) } -// QueryBlocks mocks base method. -func (m *MockClientController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types1.BlockInfo, error) { +// QueryValidatorVotingPower mocks base method. +func (m *MockClientController) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) - ret0, _ := ret[0].([]*types1.BlockInfo) + ret := m.ctrl.Call(m, "QueryValidatorVotingPower", valPk, blockHeight) + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBlocks indicates an expected call of QueryBlocks. -func (mr *MockClientControllerMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { +// QueryValidatorVotingPower indicates an expected call of QueryValidatorVotingPower. +func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(valPk, blockHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockClientController)(nil).QueryBlocks), startHeight, endHeight, limit) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryValidatorVotingPower), valPk, blockHeight) +} + +// RegisterValidator mocks base method. +func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description string) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RegisterValidator indicates an expected call of RegisterValidator. +func (mr *MockClientControllerMockRecorder) RegisterValidator(chainPk, valPk, pop, commission, description interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockClientController)(nil).RegisterValidator), chainPk, valPk, pop, commission, description) +} + +// SubmitBatchFinalitySigs mocks base method. +func (m *MockClientController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", valPk, blocks, sigs) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. +func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, blocks, sigs interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) +} + +// SubmitFinalitySig mocks base method. +func (m *MockClientController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubmitFinalitySig indicates an expected call of SubmitFinalitySig. +func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) +} + +// SubmitJurySig mocks base method. +func (m *MockClientController) SubmitJurySig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitJurySig", valPk, delPk, stakingTxHash, sig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// QueryHeader mocks base method. -func (m *MockClientController) QueryHeader(height int64) (*coretypes.ResultHeader, error) { +// SubmitJurySig indicates an expected call of SubmitJurySig. +func (mr *MockClientControllerMockRecorder) SubmitJurySig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockClientController)(nil).SubmitJurySig), valPk, delPk, stakingTxHash, sig) +} + +// SubmitJuryUnbondingSigs mocks base method. +func (m *MockClientController) SubmitJuryUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryHeader", height) - ret0, _ := ret[0].(*coretypes.ResultHeader) + ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryHeader indicates an expected call of QueryHeader. -func (mr *MockClientControllerMockRecorder) QueryHeader(height interface{}) *gomock.Call { +// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. +func (mr *MockClientControllerMockRecorder) SubmitJuryUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryHeader", reflect.TypeOf((*MockClientController)(nil).QueryHeader), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitJuryUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) } -// QueryHeightWithLastPubRand mocks base method. -func (m *MockClientController) QueryHeightWithLastPubRand(btcPubKey *types.BIP340PubKey) (uint64, error) { +// SubmitValidatorUnbondingSig mocks base method. +func (m *MockClientController) SubmitValidatorUnbondingSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryHeightWithLastPubRand", btcPubKey) + ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPk, delPk, stakingTxHash, sig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. +func (mr *MockClientControllerMockRecorder) SubmitValidatorUnbondingSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockClientController)(nil).SubmitValidatorUnbondingSig), valPk, delPk, stakingTxHash, sig) +} + +// MockValidatorAPIs is a mock of ValidatorAPIs interface. +type MockValidatorAPIs struct { + ctrl *gomock.Controller + recorder *MockValidatorAPIsMockRecorder +} + +// MockValidatorAPIsMockRecorder is the mock recorder for MockValidatorAPIs. +type MockValidatorAPIsMockRecorder struct { + mock *MockValidatorAPIs +} + +// NewMockValidatorAPIs creates a new mock instance. +func NewMockValidatorAPIs(ctrl *gomock.Controller) *MockValidatorAPIs { + mock := &MockValidatorAPIs{ctrl: ctrl} + mock.recorder = &MockValidatorAPIsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockValidatorAPIs) EXPECT() *MockValidatorAPIsMockRecorder { + return m.recorder +} + +// CommitPubRandList mocks base method. +func (m *MockValidatorAPIs) CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CommitPubRandList", valPk, startHeight, pubRandList, sig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CommitPubRandList indicates an expected call of CommitPubRandList. +func (mr *MockValidatorAPIsMockRecorder) CommitPubRandList(valPk, startHeight, pubRandList, sig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockValidatorAPIs)(nil).CommitPubRandList), valPk, startHeight, pubRandList, sig) +} + +// QueryActivatedHeight mocks base method. +func (m *MockValidatorAPIs) QueryActivatedHeight() (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryActivatedHeight") ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryHeightWithLastPubRand indicates an expected call of QueryHeightWithLastPubRand. -func (mr *MockClientControllerMockRecorder) QueryHeightWithLastPubRand(btcPubKey interface{}) *gomock.Call { +// QueryActivatedHeight indicates an expected call of QueryActivatedHeight. +func (mr *MockValidatorAPIsMockRecorder) QueryActivatedHeight() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryHeightWithLastPubRand", reflect.TypeOf((*MockClientController)(nil).QueryHeightWithLastPubRand), btcPubKey) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryActivatedHeight)) } -// QueryLatestFinalizedBlocks mocks base method. -func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types1.BlockInfo, error) { +// QueryBTCValidatorUnbondingDelegations mocks base method. +func (m *MockValidatorAPIs) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) - ret0, _ := ret[0].([]*types1.BlockInfo) + ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valPk, max) + ret0, _ := ret[0].([]*types.Delegation) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. -func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { +// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. +func (mr *MockValidatorAPIsMockRecorder) QueryBTCValidatorUnbondingDelegations(valPk, max interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockClientController)(nil).QueryLatestFinalizedBlocks), count) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBTCValidatorUnbondingDelegations), valPk, max) +} + +// QueryBestBlock mocks base method. +func (m *MockValidatorAPIs) QueryBestBlock() (*types.BlockInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryBestBlock") + ret0, _ := ret[0].(*types.BlockInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryBestBlock indicates an expected call of QueryBestBlock. +func (mr *MockValidatorAPIsMockRecorder) QueryBestBlock() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBestBlock)) } -// QueryNodeStatus mocks base method. -func (m *MockClientController) QueryNodeStatus() (*coretypes.ResultStatus, error) { +// QueryBlock mocks base method. +func (m *MockValidatorAPIs) QueryBlock(height uint64) (*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryNodeStatus") - ret0, _ := ret[0].(*coretypes.ResultStatus) + ret := m.ctrl.Call(m, "QueryBlock", height) + ret0, _ := ret[0].(*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryNodeStatus indicates an expected call of QueryNodeStatus. -func (mr *MockClientControllerMockRecorder) QueryNodeStatus() *gomock.Call { +// QueryBlock indicates an expected call of QueryBlock. +func (mr *MockValidatorAPIsMockRecorder) QueryBlock(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryNodeStatus", reflect.TypeOf((*MockClientController)(nil).QueryNodeStatus)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBlock), height) } -// QueryValidator mocks base method. -func (m *MockClientController) QueryValidator(btcPk *types.BIP340PubKey) (*types0.BTCValidator, error) { +// QueryBlocks mocks base method. +func (m *MockValidatorAPIs) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidator", btcPk) - ret0, _ := ret[0].(*types0.BTCValidator) + ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) + ret0, _ := ret[0].([]*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryValidator indicates an expected call of QueryValidator. -func (mr *MockClientControllerMockRecorder) QueryValidator(btcPk interface{}) *gomock.Call { +// QueryBlocks indicates an expected call of QueryBlocks. +func (mr *MockValidatorAPIsMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidator", reflect.TypeOf((*MockClientController)(nil).QueryValidator), btcPk) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBlocks), startHeight, endHeight, limit) +} + +// QueryLatestFinalizedBlocks mocks base method. +func (m *MockValidatorAPIs) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) + ret0, _ := ret[0].([]*types.BlockInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. +func (mr *MockValidatorAPIsMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryLatestFinalizedBlocks), count) +} + +// QueryValidatorSlashed mocks base method. +func (m *MockValidatorAPIs) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryValidatorSlashed", valPk) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryValidatorSlashed indicates an expected call of QueryValidatorSlashed. +func (mr *MockValidatorAPIsMockRecorder) QueryValidatorSlashed(valPk interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorSlashed", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryValidatorSlashed), valPk) } // QueryValidatorVotingPower mocks base method. -func (m *MockClientController) QueryValidatorVotingPower(btcPubKey *types.BIP340PubKey, blockHeight uint64) (uint64, error) { +func (m *MockValidatorAPIs) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorVotingPower", btcPubKey, blockHeight) + ret := m.ctrl.Call(m, "QueryValidatorVotingPower", valPk, blockHeight) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // QueryValidatorVotingPower indicates an expected call of QueryValidatorVotingPower. -func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(btcPubKey, blockHeight interface{}) *gomock.Call { +func (mr *MockValidatorAPIsMockRecorder) QueryValidatorVotingPower(valPk, blockHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryValidatorVotingPower), btcPubKey, blockHeight) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryValidatorVotingPower), valPk, blockHeight) } // RegisterValidator mocks base method. -func (m *MockClientController) RegisterValidator(bbnPubKey *secp256k1.PubKey, btcPubKey *types.BIP340PubKey, pop *types0.ProofOfPossession, commission *types2.Dec, description *types3.Description) (*provider.RelayerTxResponse, error) { +func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description string) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterValidator", bbnPubKey, btcPubKey, pop, commission, description) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // RegisterValidator indicates an expected call of RegisterValidator. -func (mr *MockClientControllerMockRecorder) RegisterValidator(bbnPubKey, btcPubKey, pop, commission, description interface{}) *gomock.Call { +func (mr *MockValidatorAPIsMockRecorder) RegisterValidator(chainPk, valPk, pop, commission, description interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockClientController)(nil).RegisterValidator), bbnPubKey, btcPubKey, pop, commission, description) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockValidatorAPIs)(nil).RegisterValidator), chainPk, valPk, pop, commission, description) } // SubmitBatchFinalitySigs mocks base method. -func (m *MockClientController) SubmitBatchFinalitySigs(btcPubKey *types.BIP340PubKey, blocks []*types1.BlockInfo, sigs []*types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (m *MockValidatorAPIs) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", btcPubKey, blocks, sigs) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", valPk, blocks, sigs) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. -func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(btcPubKey, blocks, sigs interface{}) *gomock.Call { +func (mr *MockValidatorAPIsMockRecorder) SubmitBatchFinalitySigs(valPk, blocks, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), btcPubKey, blocks, sigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) } // SubmitFinalitySig mocks base method. -func (m *MockClientController) SubmitFinalitySig(btcPubKey *types.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (m *MockValidatorAPIs) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", btcPubKey, blockHeight, blockHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(btcPubKey, blockHeight, blockHash, sig interface{}) *gomock.Call { +func (mr *MockValidatorAPIsMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), btcPubKey, blockHeight, blockHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) } -// SubmitJurySig mocks base method. -func (m *MockClientController) SubmitJurySig(btcPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { +// SubmitValidatorUnbondingSig mocks base method. +func (m *MockValidatorAPIs) SubmitValidatorUnbondingSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJurySig", btcPubKey, delPubKey, stakingTxHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPk, delPk, stakingTxHash, sig) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJurySig indicates an expected call of SubmitJurySig. -func (mr *MockClientControllerMockRecorder) SubmitJurySig(btcPubKey, delPubKey, stakingTxHash, sig interface{}) *gomock.Call { +// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. +func (mr *MockValidatorAPIsMockRecorder) SubmitValidatorUnbondingSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockClientController)(nil).SubmitJurySig), btcPubKey, delPubKey, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitValidatorUnbondingSig), valPk, delPk, stakingTxHash, sig) } -// SubmitJuryUnbondingSigs mocks base method. -func (m *MockClientController) SubmitJuryUnbondingSigs(btcPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, unbondingSig, slashUnbondingSig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { +// MockJuryAPIs is a mock of JuryAPIs interface. +type MockJuryAPIs struct { + ctrl *gomock.Controller + recorder *MockJuryAPIsMockRecorder +} + +// MockJuryAPIsMockRecorder is the mock recorder for MockJuryAPIs. +type MockJuryAPIsMockRecorder struct { + mock *MockJuryAPIs +} + +// NewMockJuryAPIs creates a new mock instance. +func NewMockJuryAPIs(ctrl *gomock.Controller) *MockJuryAPIs { + mock := &MockJuryAPIs{ctrl: ctrl} + mock.recorder = &MockJuryAPIsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockJuryAPIs) EXPECT() *MockJuryAPIsMockRecorder { + return m.recorder +} + +// QueryPendingDelegations mocks base method. +func (m *MockJuryAPIs) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "QueryPendingDelegations", limit) + ret0, _ := ret[0].([]*types.Delegation) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitJuryUnbondingSigs(btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { +// QueryPendingDelegations indicates an expected call of QueryPendingDelegations. +func (mr *MockJuryAPIsMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitJuryUnbondingSigs), btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockJuryAPIs)(nil).QueryPendingDelegations), limit) } -// SubmitValidatorUnbondingSig mocks base method. -func (m *MockClientController) SubmitValidatorUnbondingSig(valPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { +// QueryUnbondingDelegations mocks base method. +func (m *MockJuryAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPubKey, delPubKey, stakingTxHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) + ret0, _ := ret[0].([]*types.Delegation) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. -func (mr *MockClientControllerMockRecorder) SubmitValidatorUnbondingSig(valPubKey, delPubKey, stakingTxHash, sig interface{}) *gomock.Call { +// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. +func (mr *MockJuryAPIsMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockJuryAPIs)(nil).QueryUnbondingDelegations), limit) +} + +// SubmitJurySig mocks base method. +func (m *MockJuryAPIs) SubmitJurySig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitJurySig", valPk, delPk, stakingTxHash, sig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubmitJurySig indicates an expected call of SubmitJurySig. +func (mr *MockJuryAPIsMockRecorder) SubmitJurySig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockJuryAPIs)(nil).SubmitJurySig), valPk, delPk, stakingTxHash, sig) +} + +// SubmitJuryUnbondingSigs mocks base method. +func (m *MockJuryAPIs) SubmitJuryUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret0, _ := ret[0].(*types.TxResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. +func (mr *MockJuryAPIsMockRecorder) SubmitJuryUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockClientController)(nil).SubmitValidatorUnbondingSig), valPubKey, delPubKey, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockJuryAPIs)(nil).SubmitJuryUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) } diff --git a/testutil/utils.go b/testutil/utils.go index 05200486..bbca2c49 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -4,13 +4,12 @@ import ( "math/rand" "testing" - coretypes "github.com/cometbft/cometbft/rpc/core/types" - cometbfttypes "github.com/cometbft/cometbft/types" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/golang/mock/gomock" "github.com/babylonchain/btc-validator/testutil/mocks" + "github.com/babylonchain/btc-validator/types" ) func EmptyDescription() *stakingtypes.Description { @@ -25,30 +24,23 @@ func ZeroCommissionRate() *sdktypes.Dec { func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64) *mocks.MockClientController { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) - status := &coretypes.ResultStatus{ - SyncInfo: coretypes.SyncInfo{LatestBlockHeight: int64(currentHeight)}, - } for i := startHeight + 1; i <= currentHeight; i++ { - resHeader := &coretypes.ResultHeader{ - Header: &cometbfttypes.Header{ - Height: int64(currentHeight), - LastCommitHash: GenRandomByteArray(r, 32), - }, + resBlock := &types.BlockInfo{ + Height: currentHeight, + Hash: GenRandomByteArray(r, 32), } - mockClientController.EXPECT().QueryHeader(int64(i)).Return(resHeader, nil).AnyTimes() + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() } - currentHeaderRes := &coretypes.ResultHeader{ - Header: &cometbfttypes.Header{ - Height: int64(currentHeight), - LastCommitHash: GenRandomByteArray(r, 32), - }, + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + Hash: GenRandomByteArray(r, 32), } - mockClientController.EXPECT().QueryNodeStatus().Return(status, nil).AnyTimes() mockClientController.EXPECT().Close().Return(nil).AnyTimes() - mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() return mockClientController } diff --git a/tools/go.mod b/tools/go.mod index 8613266a..bae724d8 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -179,7 +179,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 diff --git a/tools/go.sum b/tools/go.sum index 36291e17..d5a6783c 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -253,8 +253,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231019041015-8f9d04986515 h1:NvfNgjTi3FgnEAwXHAObNNZeOcYT2S/CUT+dckXz36c= -github.com/babylonchain/babylon-private v0.0.0-20231019041015-8f9d04986515/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= +github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= diff --git a/types/blockinfo.go b/types/blockinfo.go index 99b750df..4fbc3708 100644 --- a/types/blockinfo.go +++ b/types/blockinfo.go @@ -1,6 +1,7 @@ package types type BlockInfo struct { - Height uint64 - LastCommitHash []byte + Height uint64 + Hash []byte + Finalized bool } diff --git a/types/delegation.go b/types/delegation.go new file mode 100644 index 00000000..6c7ef908 --- /dev/null +++ b/types/delegation.go @@ -0,0 +1,59 @@ +package types + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" +) + +type Delegation struct { + // btc_pk is the Bitcoin secp256k1 PK of this BTC delegation + BtcPk *btcec.PublicKey + // val_btc_pk is the Bitcoin secp256k1 PK of the BTC validator that + // this BTC delegation delegates to + ValBtcPk *btcec.PublicKey + // start_height is the start BTC height of the BTC delegation + // it is the start BTC height of the timelock + StartHeight uint64 + // end_height is the end height of the BTC delegation + // it is the end BTC height of the timelock - w + EndHeight uint64 + // staking_tx_hex is the hex string of the staking tx + StakingTxHex string + // slashing_tx_hex is the hex string of the slashing tx + // It is partially signed by SK corresponding to btc_pk, but not signed by + // validator or jury yet. + SlashingTxHex string + // jury_sig is the signature on the slashing tx + // by the jury (i.e., SK corresponding to jury_pk in params) + // It will be a part of the witness for the staking tx output. + JurySig *schnorr.Signature + // if this object is present it menans that staker requested undelegation, and whole + // delegation is being undelegated. + // directly in delegation object + BtcUndelegation *Undelegation +} + +// Undelegation signalizes that the delegation is being undelegated +type Undelegation struct { + // unbonding_tx_hex is the hex string of the transaction which will transfer the funds from staking + // output to unbonding output. Unbonding output will usually have lower timelock + // than staking output. + UnbondingTxHex string + // slashing_tx is the hex string of the slashing tx for unbodning transactions + // It is partially signed by SK corresponding to btc_pk, but not signed by + // validator or jury yet. + SlashingTxHex string + // jury_slashing_sig is the signature on the slashing tx + // by the jury (i.e., SK corresponding to jury_pk in params) + // It must be provided after processing undelagate message by the consumer chain + JurySlashingSig *schnorr.Signature + // jury_unbonding_sig is the signature on the unbonding tx + // by the jury (i.e., SK corresponding to jury_pk in params) + // It must be provided after processing undelagate message by the consumer chain and after + // validator sig will be provided by validator + JuryUnbondingSig *schnorr.Signature + // validator_unbonding_sig is the signature on the unbonding tx + // by the validator (i.e., SK corresponding to jury_pk in params) + // It must be provided after processing undelagate message by the consumer chain + ValidatorUnbondingSig *schnorr.Signature +} diff --git a/types/randpair.go b/types/randpair.go deleted file mode 100644 index b883afd8..00000000 --- a/types/randpair.go +++ /dev/null @@ -1,24 +0,0 @@ -package types - -import ( - "fmt" - - "github.com/babylonchain/btc-validator/proto" -) - -const SchnorrRandomnessLength = 32 - -func NewSchnorrRandPair(privRand []byte, pubRand []byte) (*proto.SchnorrRandPair, error) { - if len(privRand) != SchnorrRandomnessLength { - return nil, fmt.Errorf("a private randomness should be %v bytes", SchnorrRandomnessLength) - } - - if len(pubRand) != SchnorrRandomnessLength { - return nil, fmt.Errorf("a public randomness should be %v bytes", SchnorrRandomnessLength) - } - - return &proto.SchnorrRandPair{ - PubRand: pubRand, - SecRand: privRand, - }, nil -} diff --git a/types/txresponse.go b/types/txresponse.go new file mode 100644 index 00000000..bd8cdfb6 --- /dev/null +++ b/types/txresponse.go @@ -0,0 +1,10 @@ +package types + +import ( + "github.com/cosmos/relayer/v2/relayer/provider" +) + +type TxResponse struct { + TxHash string + Events []provider.RelayerEvent +} From 0a9511eaa8e5fd1a39ba700739c481dc0548bdf2 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 9 Nov 2023 17:22:37 +0800 Subject: [PATCH 14/66] chore: Add slashing address validation and rename Jury to Covenant (#137) --- clientcontroller/babylon.go | 97 ++++++++++--------------- clientcontroller/interface.go | 16 ++-- cmd/valcli/{jury.go => covenant.go} | 40 +++++----- cmd/valcli/main.go | 2 +- go.mod | 4 +- go.sum | 8 +- itest/babylon_node_handler.go | 44 +++++------ itest/e2e_test.go | 28 +++---- itest/test_manager.go | 72 +++++++++--------- service/app.go | 108 ++++++++++++++------------- service/app_test.go | 21 +++--- service/event_loop.go | 41 ++++++++--- service/types.go | 2 +- testutil/mocks/babylon.go | 109 ++++++++++++++++------------ tools/go.mod | 4 +- tools/go.sum | 2 + types/delegation.go | 24 +++--- types/params.go | 25 +++++++ valcfg/config.go | 8 +- valcfg/covenant.go | 26 +++++++ valcfg/jury.go | 25 ------- 21 files changed, 379 insertions(+), 327 deletions(-) rename cmd/valcli/{jury.go => covenant.go} (61%) create mode 100644 types/params.go create mode 100644 valcfg/covenant.go delete mode 100644 valcfg/jury.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index a95699b9..3d48cdc8 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -43,25 +43,6 @@ import ( var _ ClientController = &BabylonController{} -type StakingParams struct { - // K-deep - ComfirmationTimeBlocks uint64 - // W-deep - FinalizationTimeoutBlocks uint64 - - // Minimum amount of satoshis required for slashing transaction - MinSlashingTxFeeSat btcutil.Amount - - // Bitcoin public key of the current jury - JuryPk *btcec.PublicKey - - // Address to which slashing transactions are sent - SlashingAddress string - - // Minimum commission required by the consumer chain - MinCommissionRate string -} - type BabylonController struct { provider *cosmos.CosmosProvider logger *logrus.Logger @@ -159,7 +140,7 @@ func (bc *BabylonController) MustGetTxSigner() string { return address } -func (bc *BabylonController) GetStakingParams() (*StakingParams, error) { +func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() @@ -177,16 +158,16 @@ func (bc *BabylonController) GetStakingParams() (*StakingParams, error) { if err != nil { return nil, fmt.Errorf("failed to query staking params: %v", err) } - juryPk, err := stakingParamRes.Params.JuryPk.ToBTCPK() + covenantPk, err := stakingParamRes.Params.CovenantPk.ToBTCPK() if err != nil { return nil, err } - return &StakingParams{ + return &types.StakingParams{ ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), - JuryPk: juryPk, + CovenantPk: covenantPk, SlashingAddress: stakingParamRes.Params.SlashingAddress, MinCommissionRate: stakingParamRes.Params.MinCommissionRate.String(), }, nil @@ -353,9 +334,9 @@ func (bc *BabylonController) CommitPubRandList( return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -// SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode +// SubmitCovenantSig submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode // it returns tx hash and error -func (bc *BabylonController) SubmitJurySig( +func (bc *BabylonController) SubmitCovenantSig( valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, @@ -363,7 +344,7 @@ func (bc *BabylonController) SubmitJurySig( ) (*types.TxResponse, error) { bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) - msg := &btcstakingtypes.MsgAddJurySig{ + msg := &btcstakingtypes.MsgAddCovenantSig{ Signer: bc.MustGetTxSigner(), ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), @@ -379,9 +360,9 @@ func (bc *BabylonController) SubmitJurySig( return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -// SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode +// SubmitCovenantUnbondingSigs submits the Covenant signatures via a MsgAddCovenantUnbondingSigs to Babylon if the daemon runs in Covenant mode // it returns tx hash and error -func (bc *BabylonController) SubmitJuryUnbondingSigs( +func (bc *BabylonController) SubmitCovenantUnbondingSigs( valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, @@ -392,7 +373,7 @@ func (bc *BabylonController) SubmitJuryUnbondingSigs( bip340SlashUnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(slashUnbondingSig) - msg := &btcstakingtypes.MsgAddJuryUnbondingSigs{ + msg := &btcstakingtypes.MsgAddCovenantUnbondingSigs{ Signer: bc.MustGetTxSigner(), ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), @@ -495,9 +476,9 @@ func (bc *BabylonController) QueryUnbondingDelegations(limit uint64) ([]*types.D return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) } -// queryDelegationsWithStatus queries BTC delegations that need a Jury signature +// queryDelegationsWithStatus queries BTC delegations that need a Covenant signature // with the given status (either pending or unbonding) -// it is only used when the program is running in Jury mode +// it is only used when the program is running in Covenant mode func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*types.Delegation, error) { ctx, cancel := getContextWithCancel(bc.timeout) defer cancel() @@ -840,11 +821,11 @@ func ConvertErrType(err error) error { func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation { var ( - stakingTxHex string - slashingTxHex string - jurySchnorrSig *schnorr.Signature - undelegation *types.Undelegation - err error + stakingTxHex string + slashingTxHex string + covenantSchnorrSig *schnorr.Signature + undelegation *types.Undelegation + err error ) if del.StakingTx == nil { @@ -862,8 +843,8 @@ func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation slashingTxHex = del.SlashingTx.ToHexStr() - if del.JurySig != nil { - jurySchnorrSig, err = del.JurySig.ToBTCSig() + if del.CovenantSig != nil { + covenantSchnorrSig, err = del.CovenantSig.ToBTCSig() if err != nil { panic(err) } @@ -880,19 +861,19 @@ func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation EndHeight: del.EndHeight, StakingTxHex: stakingTxHex, SlashingTxHex: slashingTxHex, - JurySig: jurySchnorrSig, + CovenantSig: covenantSchnorrSig, BtcUndelegation: undelegation, } } func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Undelegation { var ( - unbondingTxHex string - slashingTxHex string - jurySlashingSchnorrSig *schnorr.Signature - juryUnbondingSchnorrSig *schnorr.Signature - valUnbondingSchnorrSig *schnorr.Signature - err error + unbondingTxHex string + slashingTxHex string + covenantSlashingSchnorrSig *schnorr.Signature + covenantUnbondingSchnorrSig *schnorr.Signature + valUnbondingSchnorrSig *schnorr.Signature + err error ) if undel.UnbondingTx == nil { @@ -910,15 +891,15 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde slashingTxHex = undel.SlashingTx.ToHexStr() - if undel.JurySlashingSig != nil { - jurySlashingSchnorrSig, err = undel.JurySlashingSig.ToBTCSig() + if undel.CovenantSlashingSig != nil { + covenantSlashingSchnorrSig, err = undel.CovenantSlashingSig.ToBTCSig() if err != nil { panic(err) } } - if undel.JuryUnbondingSig != nil { - juryUnbondingSchnorrSig, err = undel.JuryUnbondingSig.ToBTCSig() + if undel.CovenantUnbondingSig != nil { + covenantUnbondingSchnorrSig, err = undel.CovenantUnbondingSig.ToBTCSig() if err != nil { panic(err) } @@ -934,8 +915,8 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde return &types.Undelegation{ UnbondingTxHex: unbondingTxHex, SlashingTxHex: slashingTxHex, - JurySlashingSig: jurySlashingSchnorrSig, - JuryUnbondingSig: juryUnbondingSchnorrSig, + CovenantSlashingSig: covenantSlashingSchnorrSig, + CovenantUnbondingSig: covenantUnbondingSchnorrSig, ValidatorUnbondingSig: valUnbondingSchnorrSig, } } @@ -992,17 +973,13 @@ func (bc *BabylonController) CreateBTCUndelegation( // Insert BTC block header using rpc client // Currently this is only used for e2e tests, probably does not need to add it into the interface -func (bc *BabylonController) InsertBtcBlockHeaders(headers []*bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { - msgs := make([]sdk.Msg, 0, len(headers)) - for _, h := range headers { - msg := &btclctypes.MsgInsertHeader{ - Signer: bc.MustGetTxSigner(), - Header: h, - } - msgs = append(msgs, msg) +func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { + msg := &btclctypes.MsgInsertHeaders{ + Signer: bc.MustGetTxSigner(), + Headers: headers, } - res, err := bc.reliablySendMsgs(msgs) + res, err := bc.reliablySendMsg(msg) if err != nil { return nil, err } diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 94346921..568286df 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -19,7 +19,9 @@ const ( type ClientController interface { ValidatorAPIs - JuryAPIs + CovenantAPIs + + QueryStakingParams() (*types.StakingParams, error) Close() error } @@ -84,15 +86,15 @@ type ValidatorAPIs interface { QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) } -// JuryAPIs contains interfaces needed when the program is running in the jury mode -type JuryAPIs interface { - // SubmitJurySig submits the Jury signature to the consumer chain +// CovenantAPIs contains interfaces needed when the program is running in the covenant mode +type CovenantAPIs interface { + // SubmitCovenantSig submits the Covenant signature to the consumer chain // it returns tx hash and error - SubmitJurySig(valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) + SubmitCovenantSig(valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) - // SubmitJuryUnbondingSigs submits the Jury signatures to the consumer chain + // SubmitCovenantUnbondingSigs submits the Covenant signatures to the consumer chain // it returns tx hash and error - SubmitJuryUnbondingSigs( + SubmitCovenantUnbondingSigs( valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, diff --git a/cmd/valcli/jury.go b/cmd/valcli/covenant.go similarity index 61% rename from cmd/valcli/jury.go rename to cmd/valcli/covenant.go index 64a32440..790e0931 100644 --- a/cmd/valcli/jury.go +++ b/cmd/valcli/covenant.go @@ -12,36 +12,36 @@ import ( "github.com/babylonchain/btc-validator/val" ) -type juryKey struct { +type covenantKey struct { Name string `json:"name"` PublicKey string `json:"public-key"` } -var juryCommands = []cli.Command{ +var covenantCommands = []cli.Command{ { - Name: "jury", - ShortName: "j", - Usage: "Control Babylon Jury.", - Category: "Jury", + Name: "covenant", + ShortName: "c", + Usage: "Control Babylon Covenant.", + Category: "Covenant", Subcommands: []cli.Command{ - createJury, + createCovenant, }, }, } -var createJury = cli.Command{ - Name: "create-jury", - ShortName: "cj", - Usage: "Create a Jury account in the keyring.", +var createCovenant = cli.Command{ + Name: "create-covenant", + ShortName: "cc", + Usage: "Create a Covenant account in the keyring.", Flags: []cli.Flag{ cli.StringFlag{ Name: chainIdFlag, - Usage: "The chainID of the Babylonchain", + Usage: "The chainID of the consumer chain", Value: defaultChainID, }, cli.StringFlag{ Name: keyNameFlag, - Usage: "The unique name of the Jury key", + Usage: "The unique name of the Covenant key", Required: true, }, cli.StringFlag{ @@ -54,10 +54,10 @@ var createJury = cli.Command{ Usage: "The directory where the keyring is stored", }, }, - Action: createJuryKey, + Action: createCovenantKey, } -func createJuryKey(ctx *cli.Context) error { +func createCovenantKey(ctx *cli.Context) error { sdkCtx, err := service.CreateClientCtx( ctx.String(keyringDirFlag), ctx.String(chainIdFlag), @@ -75,17 +75,17 @@ func createJuryKey(ctx *cli.Context) error { return err } - sdkJuryPk, err := krController.CreateChainKey() + sdkCovenantPk, err := krController.CreateChainKey() if err != nil { - return fmt.Errorf("failed to create Jury key: %w", err) + return fmt.Errorf("failed to create Covenant key: %w", err) } - juryPk, err := secp256k1.ParsePubKey(sdkJuryPk.Key) + covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) if err != nil { return err } - bip340Key := types.NewBIP340PubKeyFromBTCPK(juryPk) - printRespJSON(&juryKey{ + bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) + printRespJSON(&covenantKey{ Name: ctx.String(keyNameFlag), PublicKey: bip340Key.MarshalHex(), }) diff --git a/cmd/valcli/main.go b/cmd/valcli/main.go index ec06f622..08627427 100644 --- a/cmd/valcli/main.go +++ b/cmd/valcli/main.go @@ -55,7 +55,7 @@ func main() { app.Commands = append(app.Commands, daemonCommands...) app.Commands = append(app.Commands, adminCommands...) - app.Commands = append(app.Commands, juryCommands...) + app.Commands = append(app.Commands, covenantCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/go.mod b/go.mod index 48dade24..c3727d04 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( cosmossdk.io/math v1.0.1 github.com/avast/retry-go/v4 v4.3.3 github.com/babylonchain/babylon v0.7.1 - github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd + github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cosmos/cosmos-proto v1.0.0-beta.2 @@ -303,7 +303,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index cb87c5bb..07d9955a 100644 --- a/go.sum +++ b/go.sum @@ -269,8 +269,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= -github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f h1:J8wNXIRlc7+vFpWj2LiUNhHng8o37+a1RpbbrkvXr8Q= +github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f/go.mod h1:Omv/7j7d/KioUlGhffrA1uajzYwx959cLElstveJwKc= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= @@ -292,8 +292,8 @@ github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7a github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd h1:v2Bs8yLhwv+8XYU96OOnhZ5BEj8ZlNGownexUO0e80I= -github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 h1:FZR6mILlSI/GDx8ydNVBZAlXlRXsoRBWX2Un64mpfsI= +github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 6747e12d..c7442ac7 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -19,21 +19,21 @@ import ( ) type babylonNode struct { - cmd *exec.Cmd - pidFile string - dataDir string - juryKeyName string - chainID string - slashingAddr string + cmd *exec.Cmd + pidFile string + dataDir string + covenantKeyName string + chainID string + slashingAddr string } -func newBabylonNode(dataDir string, cmd *exec.Cmd, juryKeyName, chainID string, slashingAddr string) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd, covenantKeyName, chainID string, slashingAddr string) *babylonNode { return &babylonNode{ - dataDir: dataDir, - cmd: cmd, - juryKeyName: juryKeyName, - chainID: chainID, - slashingAddr: slashingAddr, + dataDir: dataDir, + cmd: cmd, + covenantKeyName: covenantKeyName, + chainID: chainID, + slashingAddr: slashingAddr, } } @@ -123,25 +123,25 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { nodeDataDir := filepath.Join(testDir, "node0", "babylond") - // the Jury key needs to be created before babylond is started + // the Covenant key needs to be created before babylond is started chainID := "chain-test" sdkCtx, err := service.CreateClientCtx( nodeDataDir, chainID, ) require.NoError(t, err) - juryKeyName := "jury-key" + covenantKeyName := "covenant-key" krController, err := val.NewChainKeyringController( sdkCtx, - juryKeyName, + covenantKeyName, "test", ) require.NoError(t, err) - sdkJuryPk, err := krController.CreateChainKey() + sdkCovenantPk, err := krController.CreateChainKey() require.NoError(t, err) - juryPk, err := secp256k1.ParsePubKey(sdkJuryPk.Key) + covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) require.NoError(t, err) - juryPkBip340 := types.NewBIP340PubKeyFromBTCPK(juryPk) + covenantPkBip340 := types.NewBIP340PubKeyFromBTCPK(covenantPk) slashingAddr := "SZtRT4BySL3o4efdGLh3k7Kny8GAnsBrSW" @@ -155,7 +155,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--jury-pk=%s", juryPkBip340.MarshalHex()), + fmt.Sprintf("--covenant-pk=%s", covenantPkBip340.MarshalHex()), ) var stderr bytes.Buffer @@ -180,7 +180,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, juryKeyName, chainID, slashingAddr), + babylonNode: newBabylonNode(testDir, startCmd, covenantKeyName, chainID, slashingAddr), } } @@ -206,8 +206,8 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { return dir } -func (w *BabylonNodeHandler) GetJuryKeyName() string { - return w.babylonNode.juryKeyName +func (w *BabylonNodeHandler) GetCovenantKeyName() string { + return w.babylonNode.covenantKeyName } func (w *BabylonNodeHandler) GetSlashingAddress() string { diff --git a/itest/e2e_test.go b/itest/e2e_test.go index bdb92fb5..ca357940 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -22,7 +22,7 @@ var ( // TestValidatorLifeCycle tests the whole life cycle of a validator // creation -> registration -> randomness commitment -> -// activation with BTC delegation and Jury sig -> +// activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestValidatorLifeCycle(t *testing.T) { tm := StartManagerWithValidator(t, 1, false) @@ -40,8 +40,8 @@ func TestValidatorLifeCycle(t *testing.T) { // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // submit Covenant sig + _ = tm.AddCovenantSignature(t, dels[0]) // check the BTC delegation is active dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) @@ -78,12 +78,12 @@ func TestMultipleValidators(t *testing.T) { // check the 3 BTC delegations are pending dels := tm.WaitForNPendingDels(t, 3) - // submit Jury sigs for each delegation + // submit Covenant sigs for each delegation for _, del := range dels { tm.Wg.Add(1) go func(btcDel *types.Delegation) { defer tm.Wg.Done() - _ = tm.AddJurySignature(t, btcDel) + _ = tm.AddCovenantSignature(t, btcDel) }(del) } tm.Wg.Wait() @@ -120,8 +120,8 @@ func TestDoubleSigning(t *testing.T) { // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // submit Covenant sig + _ = tm.AddCovenantSignature(t, dels[0]) // check the BTC delegation is active dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) @@ -166,8 +166,8 @@ func TestFastSync(t *testing.T) { // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // submit Covenant sig + _ = tm.AddCovenantSignature(t, dels[0]) dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) @@ -212,8 +212,8 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // submit Covenant sig + _ = tm.AddCovenantSignature(t, dels[0]) dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) @@ -222,7 +222,7 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { _ = tm.WaitForValNUnbondingDels(t, valIns.GetBtcPkBIP340(), 1) } -func TestJuryLifeCycle(t *testing.T) { +func TestCovenantLifeCycle(t *testing.T) { tm := StartManagerWithValidator(t, 1, true) defer tm.Stop(t) app := tm.Va @@ -258,7 +258,7 @@ func TestJuryLifeCycle(t *testing.T) { validatorPrivKey, ) - // after providing validator unbodning signature, we should wait for jury to provide both valid signatures + // after providing validator unbodning signature, we should wait for covenant to provide both valid signatures require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) if err != nil { @@ -275,6 +275,6 @@ func TestJuryLifeCycle(t *testing.T) { return false } - return del.BtcUndelegation.JurySlashingSig != nil && del.BtcUndelegation.JuryUnbondingSig != nil + return del.BtcUndelegation.CovenantSlashingSig != nil && del.BtcUndelegation.CovenantUnbondingSig != nil }, 1*time.Minute, eventuallyPollTime) } diff --git a/itest/test_manager.go b/itest/test_manager.go index 16050e18..f5149f90 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -66,7 +66,7 @@ type TestDelegationData struct { StakingAmount int64 } -func StartManager(t *testing.T, isJury bool) *TestManager { +func StartManager(t *testing.T, isCovenant bool) *TestManager { bh := NewBabylonNodeHandler(t) err := bh.Start() @@ -80,7 +80,7 @@ func StartManager(t *testing.T, isJury bool) *TestManager { testDir, err := tempDirWithName("vale2etest") require.NoError(t, err) - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isJury) + cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isCovenant) bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) @@ -117,7 +117,7 @@ func StartManager(t *testing.T, isJury bool) *TestManager { func (tm *TestManager) WaitForServicesStart(t *testing.T) { // wait for Babylon node starts require.Eventually(t, func() bool { - _, err := tm.BabylonClient.GetStakingParams() + _, err := tm.BabylonClient.QueryStakingParams() return err == nil }, eventuallyWaitTimeOut, eventuallyPollTime) @@ -125,8 +125,8 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { - tm := StartManager(t, isJury) +func StartManagerWithValidator(t *testing.T, n int, isCovenant bool) *TestManager { + tm := StartManager(t, isCovenant) app := tm.Va var ( @@ -222,7 +222,7 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegat ) require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryPendingDelegations( - tm.ValConfig.JuryModeConfig.DelegationLimit, + tm.ValConfig.CovenantModeConfig.DelegationLimit, ) if err != nil { return false @@ -239,7 +239,7 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 var dels []*types.Delegation currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() require.NoError(t, err) - params, err := tm.BabylonClient.GetStakingParams() + params, err := tm.BabylonClient.QueryStakingParams() require.NoError(t, err) require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(btcPk, 1000) @@ -289,15 +289,15 @@ func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, statu func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTCDelegationStatus { if del.BtcUndelegation != nil { - if del.BtcUndelegation.JurySlashingSig != nil && - del.BtcUndelegation.JuryUnbondingSig != nil && + if del.BtcUndelegation.CovenantSlashingSig != nil && + del.BtcUndelegation.CovenantUnbondingSig != nil && del.BtcUndelegation.ValidatorUnbondingSig != nil { return bstypes.BTCDelegationStatus_UNBONDED } // If we received an undelegation but is still does not have all required signature, // delegation receives UNBONING status. // Voting power from this delegation is removed from the total voting power and now we - // are waiting for signatures from validator and jury for delegation to become expired. + // are waiting for signatures from validator and covenant for delegation to become expired. // For now we do not have any unbonding time on the consumer chain, only time lock on BTC chain // we may consider adding unbonding time on the consumer chain later to avoid situation where // we can lose to much voting power in to short time. @@ -305,7 +305,7 @@ func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTC } if del.StartHeight <= btcHeight && btcHeight+w <= del.EndHeight { - if del.JurySig != nil { + if del.CovenantSig != nil { return bstypes.BTCDelegationStatus_ACTIVE } else { return bstypes.BTCDelegationStatus_PENDING @@ -398,7 +398,7 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, require.NoError(t, err) } -func (tm *TestManager) AddJurySignature(t *testing.T, del *types.Delegation) *types.TxResponse { +func (tm *TestManager) AddCovenantSignature(t *testing.T, del *types.Delegation) *types.TxResponse { slashingTx, err := bstypes.NewBTCSlashingTxFromHex(del.SlashingTxHex) require.NoError(t, err) stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) @@ -406,24 +406,24 @@ func (tm *TestManager) AddJurySignature(t *testing.T, del *types.Delegation) *ty stakingMsgTx, err := stakingTx.ToMsgTx() require.NoError(t, err) - // get Jury private key from the keyring - juryPrivKey := tm.GetJuryPrivKey(t) + // get Covenant private key from the keyring + covenantPrivKey := tm.GetCovenantPrivKey(t) - jurySig, err := slashingTx.Sign( + covenantSig, err := slashingTx.Sign( stakingMsgTx, stakingTx.Script, - juryPrivKey, + covenantPrivKey, &tm.ValConfig.ActiveNetParams, ) require.NoError(t, err) - jurySchnorrSig, err := jurySig.ToBTCSig() + covenantSchnorrSig, err := covenantSig.ToBTCSig() require.NoError(t, err) - res, err := tm.BabylonClient.SubmitJurySig( + res, err := tm.BabylonClient.SubmitCovenantSig( del.ValBtcPk, del.BtcPk, stakingMsgTx.TxHash().String(), - jurySchnorrSig, + covenantSchnorrSig, ) require.NoError(t, err) @@ -465,15 +465,15 @@ func (tm *TestManager) AddValidatorUnbondingSignature( require.NoError(t, err) } -func (tm *TestManager) GetJuryPrivKey(t *testing.T) *btcec.PrivateKey { +func (tm *TestManager) GetCovenantPrivKey(t *testing.T) *btcec.PrivateKey { kr := tm.Va.GetKeyring() - juryKeyName := tm.BabylonHandler.GetJuryKeyName() - k, err := kr.Key(juryKeyName) + covenantKeyName := tm.BabylonHandler.GetCovenantKeyName() + k, err := kr.Key(covenantKeyName) require.NoError(t, err) localKey := k.GetLocal().PrivKey.GetCachedValue() require.IsType(t, &secp256k1.PrivKey{}, localKey) - juryPrivKey, _ := btcec.PrivKeyFromBytes(localKey.(*secp256k1.PrivKey).Key) - return juryPrivKey + covenantPrivKey, _ := btcec.PrivKeyFromBytes(localKey.(*secp256k1.PrivKey).Key) + return covenantPrivKey } func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { @@ -486,20 +486,20 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK r := rand.New(rand.NewSource(time.Now().UnixNano())) // examine staking params - params, err := tm.BabylonClient.GetStakingParams() + params, err := tm.BabylonClient.QueryStakingParams() slashingAddr := params.SlashingAddress require.NoError(t, err) require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - juryPk := tm.GetJuryPrivKey(t).PubKey() + covenantPk := tm.GetCovenantPrivKey(t).PubKey() require.NoError(t, err) - require.Equal(t, params.JuryPk.SerializeCompressed()[1:], juryPk.SerializeCompressed()[1:]) + require.Equal(t, params.CovenantPk.SerializeCompressed()[1:], covenantPk.SerializeCompressed()[1:]) // delegator BTC key pairs, staking tx and slashing tx delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx( - r, btcNetworkParams, delBtcPrivKey, valBtcPk, juryPk, stakingTime, stakingAmount, tm.BabylonHandler.GetSlashingAddress()) + r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, tm.BabylonHandler.GetSlashingAddress()) require.NoError(t, err) // get msgTx @@ -526,11 +526,11 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK Height: currentBtcTip.Height + 1, Work: &accumulatedWork, } - headers := make([]*bbntypes.BTCHeaderBytes, 0) - headers = append(headers, &blockWithStakingTx.HeaderBytes) + headers := make([]bbntypes.BTCHeaderBytes, 0) + headers = append(headers, blockWithStakingTx.HeaderBytes) for i := 0; i < int(params.ComfirmationTimeBlocks); i++ { headerInfo := datagen.GenRandomValidBTCHeaderInfoWithParent(r, *parentBlockHeaderInfo) - headers = append(headers, headerInfo.Header) + headers = append(headers, *headerInfo.Header) parentBlockHeaderInfo = headerInfo } _, err = tm.BabylonClient.InsertBtcBlockHeaders(headers) @@ -574,7 +574,7 @@ func (tm *TestManager) InsertBTCUnbonding( validatorPk *btcec.PublicKey, ) { r := rand.New(rand.NewSource(time.Now().UnixNano())) - params, err := tm.BabylonClient.GetStakingParams() + params, err := tm.BabylonClient.QueryStakingParams() require.NoError(t, err) slashingAddr := params.SlashingAddress stakingMsgTx, err := stakingTx.ToMsgTx() @@ -595,7 +595,7 @@ func (tm *TestManager) InsertBTCUnbonding( btcNetworkParams, stakerPrivKey, validatorPk, - params.JuryPk, + params.CovenantPk, wire.NewOutPoint(&stakingTxChainHash, uint32(stakingOutputIdx)), uint16(params.FinalizationTimeoutBlocks)+1, stakingValue-fee, @@ -620,7 +620,7 @@ func (tm *TestManager) InsertBTCUnbonding( require.NoError(t, err) } -func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Config { +func defaultValidatorConfig(keyringDir, testDir string, isCovenant bool) *valcfg.Config { cfg := valcfg.DefaultConfig() cfg.ValidatorModeConfig.AutoChainScanningMode = false @@ -632,8 +632,8 @@ func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Con // Big adjustment to make sure we have enough gas in our transactions cfg.BabylonConfig.GasAdjustment = 20 cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") - cfg.JuryMode = isJury - cfg.JuryModeConfig.QueryInterval = 7 * time.Second + cfg.CovenantMode = isCovenant + cfg.CovenantModeConfig.QueryInterval = 7 * time.Second cfg.UnbondingSigSubmissionInterval = 3 * time.Second return &cfg diff --git a/service/app.go b/service/app.go index cfb7ecca..50757f69 100644 --- a/service/app.go +++ b/service/app.go @@ -103,14 +103,14 @@ func NewValidatorApp( return nil, fmt.Errorf("failed to open the store for validators: %w", err) } - if config.JuryMode { - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.JuryModeConfig.JuryKeyName) + if config.CovenantMode { + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.CovenantModeConfig.CovenantKeyName) if err != nil { return nil, err } if _, err := kc.GetChainPrivKey(); err != nil { - return nil, fmt.Errorf("the program is running in Jury mode but the Jury key %s is not found: %w", - config.JuryModeConfig.JuryKeyName, err) + return nil, fmt.Errorf("the program is running in Covenant mode but the Covenant key %s is not found: %w", + config.CovenantModeConfig.CovenantKeyName, err) } } @@ -220,17 +220,22 @@ func (app *ValidatorApp) StartHandlingValidators() error { return app.validatorManager.Start() } -// AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySigResponse, error) { - if btcDel.JurySig != nil { - return nil, fmt.Errorf("the Jury sig already existed in the Bitcoin delection") +// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// Note: this should be only called when the program is running in Covenant mode +func (app *ValidatorApp) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { + if btcDel.CovenantSig != nil { + return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") } slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) if err != nil { return nil, err } + err = slashingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) + if err != nil { + return nil, fmt.Errorf("invalid delegation: %w", err) + } + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) if err != nil { return nil, err @@ -240,16 +245,16 @@ func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySig return nil, err } - // get Jury private key from the keyring - juryPrivKey, err := app.getJuryPrivKey() + // get Covenant private key from the keyring + covenantPrivKey, err := app.getCovenantPrivKey() if err != nil { - return nil, fmt.Errorf("failed to get Jury private key: %w", err) + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) } - jurySig, err := slashingTx.Sign( + covenantSig, err := slashingTx.Sign( stakingMsgTx, stakingTx.Script, - juryPrivKey, + covenantPrivKey, &app.config.ActiveNetParams, ) if err != nil { @@ -258,11 +263,11 @@ func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySig stakingTxHash := stakingMsgTx.TxHash().String() - jurySchnorrSig, err := jurySig.ToBTCSig() + covenantSchnorrSig, err := covenantSig.ToBTCSig() if err != nil { return nil, err } - res, err := app.cc.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, jurySchnorrSig) + res, err := app.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() @@ -271,7 +276,7 @@ func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySig "err": err, "valBtcPubKey": valPkHex, "delBtcPubKey": delPkHex, - }).Error("failed to submit Jury signature") + }).Error("failed to submit Covenant signature") return nil, err } @@ -280,18 +285,18 @@ func (app *ValidatorApp) AddJurySignature(btcDel *types.Delegation) (*AddJurySig "err": err, "valBtcPubKey": valPkHex, "delBtcPubKey": delPkHex, - }).Error("failed to submit Jury signature") - return nil, fmt.Errorf("failed to submit Jury signature due to known error") + }).Error("failed to submit Covenant signature") + return nil, fmt.Errorf("failed to submit Covenant signature due to known error") } - return &AddJurySigResponse{ + return &AddCovenantSigResponse{ TxHash: res.TxHash, }, nil } -// AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*AddJurySigResponse, error) { +// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// Note: this should be only called when the program is running in Covenant mode +func (app *ValidatorApp) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { if del == nil { return nil, fmt.Errorf("btc delegation is nil") } @@ -305,16 +310,16 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add } // In normal operation it is not possible to have one of this signatures and not have the other - // as only way to update this fields in delegation is by processing the MsgAddJuryUnbondingSigs msg + // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg // which should update both fields at atomically in case of successfull transaction. - if del.BtcUndelegation.JurySlashingSig != nil || del.BtcUndelegation.JuryUnbondingSig != nil { - return nil, fmt.Errorf("delegation already has required jury signatures") + if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { + return nil, fmt.Errorf("delegation already has required covenant signatures") } - // get Jury private key from the keyring - juryPrivKey, err := app.getJuryPrivKey() + // get Covenant private key from the keyring + covenantPrivKey, err := app.getCovenantPrivKey() if err != nil { - return nil, fmt.Errorf("failed to get Jury private key: %w", err) + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) } // 1. Sign unbonding transaction @@ -332,10 +337,10 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add if err != nil { return nil, err } - juryUnbondingSig, err := unbondingTx.Sign( + covenantUnbondingSig, err := unbondingTx.Sign( stakingMsgTx, stakingTx.Script, - juryPrivKey, + covenantPrivKey, &app.config.ActiveNetParams, ) @@ -348,16 +353,21 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add if err != nil { return nil, err } + err = slashUnbondingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) + if err != nil { + return nil, err + } + unbondingMsgTx, err := unbondingTx.ToMsgTx() if err != nil { return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) } - jurySlashingUnbondingSig, err := slashUnbondingTx.Sign( + covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( unbondingMsgTx, unbondingTx.Script, - juryPrivKey, + covenantPrivKey, &app.config.ActiveNetParams, ) if err != nil { @@ -366,20 +376,20 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add stakingTxHash := stakingMsgTx.TxHash().String() - juryUnbondingSchnorrSig, err := juryUnbondingSig.ToBTCSig() + covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() if err != nil { return nil, err } - jurySlashingUnbondingShcnorrSig, err := jurySlashingUnbondingSig.ToBTCSig() + covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() if err != nil { return nil, err } - res, err := app.cc.SubmitJuryUnbondingSigs( + res, err := app.cc.SubmitCovenantUnbondingSigs( del.ValBtcPk, del.BtcPk, stakingTxHash, - juryUnbondingSchnorrSig, - jurySlashingUnbondingShcnorrSig, + covenantUnbondingSchnorrSig, + covenantSlashingUnbondingShcnorrSig, ) valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() @@ -390,7 +400,7 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add "err": err, "valBtcPubKey": valPkHex, "delBtcPubKey": delPkHex, - }).Error("failed to submit Jury signature") + }).Error("failed to submit Covenant signature") return nil, err } @@ -399,17 +409,17 @@ func (app *ValidatorApp) AddJuryUnbondingSignatures(del *types.Delegation) (*Add "err": err, "valBtcPubKey": valPkHex, "delBtcPubKey": delPkHex, - }).Error("failed to submit Jury signature") - return nil, fmt.Errorf("failed to submit Jury signature due to known error") + }).Error("failed to submit Covenant signature") + return nil, fmt.Errorf("failed to submit Covenant signature due to known error") } - return &AddJurySigResponse{ + return &AddCovenantSigResponse{ TxHash: res.TxHash, }, nil } -func (app *ValidatorApp) getJuryPrivKey() (*btcec.PrivateKey, error) { - kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.JuryModeConfig.JuryKeyName) +func (app *ValidatorApp) getCovenantPrivKey() (*btcec.PrivateKey, error) { + kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.CovenantModeConfig.CovenantKeyName) if err != nil { return nil, err } @@ -444,9 +454,9 @@ func (app *ValidatorApp) Start() error { app.sentWg.Add(1) go app.registrationLoop() - if app.IsJury() { + if app.IsCovenant() { app.wg.Add(1) - go app.jurySigSubmissionLoop() + go app.covenantSigSubmissionLoop() } else { if err := app.StartHandlingValidators(); err != nil { startErr = err @@ -468,7 +478,7 @@ func (app *ValidatorApp) Stop() error { close(app.quit) app.wg.Wait() - if !app.IsJury() { + if !app.IsCovenant() { app.logger.Debug("Stopping validators") if err := app.validatorManager.Stop(); err != nil { stopErr = err @@ -528,8 +538,8 @@ func (app *ValidatorApp) CreateValidator(keyName, chainID, passPhrase string, de } } -func (app *ValidatorApp) IsJury() bool { - return app.config.JuryMode +func (app *ValidatorApp) IsCovenant() bool { + return app.config.CovenantMode } func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { diff --git a/service/app_test.go b/service/app_test.go index caf018c8..526641ee 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -96,7 +96,7 @@ func FuzzRegisterValidator(f *testing.F) { }) } -func FuzzAddJurySig(f *testing.F) { +func FuzzAddCovenantSig(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) @@ -125,15 +125,15 @@ func FuzzAddJurySig(f *testing.F) { app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) require.NoError(t, err) - // create a Jury key pair in the keyring - juryKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName) + // create a Covenant key pair in the keyring + covenantKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.CovenantModeConfig.CovenantKeyName) require.NoError(t, err) - sdkJurPk, err := juryKc.CreateChainKey() + sdkJurPk, err := covenantKc.CreateChainKey() require.NoError(t, err) - juryPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) + covenantPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) require.NoError(t, err) - require.NotNil(t, juryPk) - cfg.JuryMode = true + require.NotNil(t, covenantPk) + cfg.CovenantMode = true err = app.Start() require.NoError(t, err) @@ -154,7 +154,7 @@ func FuzzAddJurySig(f *testing.F) { require.NoError(t, err) stakingTimeBlocks := uint16(5) stakingValue := int64(2 * 10e8) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, juryPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) + stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, covenantPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) require.NoError(t, err) require.NoError(t, err) stakingTxHex, err := stakingTx.ToHexStr() @@ -171,14 +171,15 @@ func FuzzAddJurySig(f *testing.F) { expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT().QueryPendingDelegations(gomock.Any()). Return([]*types.Delegation{delegation}, nil).AnyTimes() - mockClientController.EXPECT().SubmitJurySig( + mockClientController.EXPECT().SubmitCovenantSig( delegation.ValBtcPk, delegation.BtcPk, stakingMsgTx.TxHash().String(), gomock.Any(), ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := app.AddJurySignature(delegation) + cfg.CovenantModeConfig.SlashingAddress = slashingAddr.String() + res, err := app.AddCovenantSignature(delegation) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) }) diff --git a/service/event_loop.go b/service/event_loop.go index dd39d0c3..c8ad7ca3 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -4,22 +4,41 @@ import ( "encoding/hex" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" ) -// jurySigSubmissionLoop is the reactor to submit Jury signature for pending BTC delegations -func (app *ValidatorApp) jurySigSubmissionLoop() { +// covenantSigSubmissionLoop is the reactor to submit Covenant signature for pending BTC delegations +func (app *ValidatorApp) covenantSigSubmissionLoop() { defer app.wg.Done() - interval := app.config.JuryModeConfig.QueryInterval - limit := app.config.JuryModeConfig.DelegationLimit - jurySigTicker := time.NewTicker(interval) + interval := app.config.CovenantModeConfig.QueryInterval + limit := app.config.CovenantModeConfig.DelegationLimit + covenantSigTicker := time.NewTicker(interval) for { select { - case <-jurySigTicker.C: + case <-covenantSigTicker.C: + // 0. Update slashing address in case it is changed upon governance proposal + params, err := app.cc.QueryStakingParams() + if err != nil { + app.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get slashing address") + continue + } + slashingAddress := params.SlashingAddress + _, err = btcutil.DecodeAddress(slashingAddress, &app.config.ActiveNetParams) + if err != nil { + app.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("invalid slashing address") + continue + } + app.config.CovenantModeConfig.SlashingAddress = slashingAddress + // 1. Get all pending delegations first, this are more important than the unbonding ones dels, err := app.cc.QueryPendingDelegations(limit) if err != nil { @@ -33,12 +52,12 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { } for _, d := range dels { - _, err := app.AddJurySignature(d) + _, err := app.AddCovenantSignature(d) if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, "del_btc_pk": d.BtcPk, - }).Error("failed to submit Jury sig to the Bitcoin delegation") + }).Error("failed to submit Covenant sig to the Bitcoin delegation") } } // 2. Get all unbonding delegations @@ -56,17 +75,17 @@ func (app *ValidatorApp) jurySigSubmissionLoop() { } for _, d := range unbondingDels { - _, err := app.AddJuryUnbondingSignatures(d) + _, err := app.AddCovenantUnbondingSignatures(d) if err != nil { app.logger.WithFields(logrus.Fields{ "err": err, "del_btc_pk": d.BtcPk, - }).Error("failed to submit Jury sig to the Bitcoin delegation") + }).Error("failed to submit Covenant sig to the Bitcoin delegation") } } case <-app.quit: - app.logger.Debug("exiting jurySigSubmissionLoop") + app.logger.Debug("exiting covenantSigSubmissionLoop") return } } diff --git a/service/types.go b/service/types.go index a912ce8f..534bbeca 100644 --- a/service/types.go +++ b/service/types.go @@ -52,7 +52,7 @@ type RegisterValidatorResponse struct { TxHash string } -type AddJurySigResponse struct { +type AddCovenantSigResponse struct { TxHash string } diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index fafb244a..665e6acb 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -171,6 +171,21 @@ func (mr *MockClientControllerMockRecorder) QueryPendingDelegations(limit interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryPendingDelegations), limit) } +// QueryStakingParams mocks base method. +func (m *MockClientController) QueryStakingParams() (*types.StakingParams, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryStakingParams") + ret0, _ := ret[0].(*types.StakingParams) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryStakingParams indicates an expected call of QueryStakingParams. +func (mr *MockClientControllerMockRecorder) QueryStakingParams() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryStakingParams", reflect.TypeOf((*MockClientController)(nil).QueryStakingParams)) +} + // QueryUnbondingDelegations mocks base method. func (m *MockClientController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() @@ -246,49 +261,49 @@ func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, block return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) } -// SubmitFinalitySig mocks base method. -func (m *MockClientController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { +// SubmitCovenantSig mocks base method. +func (m *MockClientController) SubmitCovenantSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) + ret := m.ctrl.Call(m, "SubmitCovenantSig", valPk, delPk, stakingTxHash, sig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { +// SubmitCovenantSig indicates an expected call of SubmitCovenantSig. +func (mr *MockClientControllerMockRecorder) SubmitCovenantSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSig", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSig), valPk, delPk, stakingTxHash, sig) } -// SubmitJurySig mocks base method. -func (m *MockClientController) SubmitJurySig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitCovenantUnbondingSigs mocks base method. +func (m *MockClientController) SubmitCovenantUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJurySig", valPk, delPk, stakingTxHash, sig) + ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJurySig indicates an expected call of SubmitJurySig. -func (mr *MockClientControllerMockRecorder) SubmitJurySig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { +// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. +func (mr *MockClientControllerMockRecorder) SubmitCovenantUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockClientController)(nil).SubmitJurySig), valPk, delPk, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) } -// SubmitJuryUnbondingSigs mocks base method. -func (m *MockClientController) SubmitJuryUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitFinalitySig mocks base method. +func (m *MockClientController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitJuryUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { +// SubmitFinalitySig indicates an expected call of SubmitFinalitySig. +func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitJuryUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) } // SubmitValidatorUnbondingSig mocks base method. @@ -524,31 +539,31 @@ func (mr *MockValidatorAPIsMockRecorder) SubmitValidatorUnbondingSig(valPk, delP return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitValidatorUnbondingSig), valPk, delPk, stakingTxHash, sig) } -// MockJuryAPIs is a mock of JuryAPIs interface. -type MockJuryAPIs struct { +// MockCovenantAPIs is a mock of CovenantAPIs interface. +type MockCovenantAPIs struct { ctrl *gomock.Controller - recorder *MockJuryAPIsMockRecorder + recorder *MockCovenantAPIsMockRecorder } -// MockJuryAPIsMockRecorder is the mock recorder for MockJuryAPIs. -type MockJuryAPIsMockRecorder struct { - mock *MockJuryAPIs +// MockCovenantAPIsMockRecorder is the mock recorder for MockCovenantAPIs. +type MockCovenantAPIsMockRecorder struct { + mock *MockCovenantAPIs } -// NewMockJuryAPIs creates a new mock instance. -func NewMockJuryAPIs(ctrl *gomock.Controller) *MockJuryAPIs { - mock := &MockJuryAPIs{ctrl: ctrl} - mock.recorder = &MockJuryAPIsMockRecorder{mock} +// NewMockCovenantAPIs creates a new mock instance. +func NewMockCovenantAPIs(ctrl *gomock.Controller) *MockCovenantAPIs { + mock := &MockCovenantAPIs{ctrl: ctrl} + mock.recorder = &MockCovenantAPIsMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockJuryAPIs) EXPECT() *MockJuryAPIsMockRecorder { +func (m *MockCovenantAPIs) EXPECT() *MockCovenantAPIsMockRecorder { return m.recorder } // QueryPendingDelegations mocks base method. -func (m *MockJuryAPIs) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { +func (m *MockCovenantAPIs) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryPendingDelegations", limit) ret0, _ := ret[0].([]*types.Delegation) @@ -557,13 +572,13 @@ func (m *MockJuryAPIs) QueryPendingDelegations(limit uint64) ([]*types.Delegatio } // QueryPendingDelegations indicates an expected call of QueryPendingDelegations. -func (mr *MockJuryAPIsMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { +func (mr *MockCovenantAPIsMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockJuryAPIs)(nil).QueryPendingDelegations), limit) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryPendingDelegations), limit) } // QueryUnbondingDelegations mocks base method. -func (m *MockJuryAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { +func (m *MockCovenantAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) ret0, _ := ret[0].([]*types.Delegation) @@ -572,37 +587,37 @@ func (m *MockJuryAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegat } // QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. -func (mr *MockJuryAPIsMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { +func (mr *MockCovenantAPIsMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockJuryAPIs)(nil).QueryUnbondingDelegations), limit) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryUnbondingDelegations), limit) } -// SubmitJurySig mocks base method. -func (m *MockJuryAPIs) SubmitJurySig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitCovenantSig mocks base method. +func (m *MockCovenantAPIs) SubmitCovenantSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJurySig", valPk, delPk, stakingTxHash, sig) + ret := m.ctrl.Call(m, "SubmitCovenantSig", valPk, delPk, stakingTxHash, sig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJurySig indicates an expected call of SubmitJurySig. -func (mr *MockJuryAPIsMockRecorder) SubmitJurySig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { +// SubmitCovenantSig indicates an expected call of SubmitCovenantSig. +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockJuryAPIs)(nil).SubmitJurySig), valPk, delPk, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSig", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSig), valPk, delPk, stakingTxHash, sig) } -// SubmitJuryUnbondingSigs mocks base method. -func (m *MockJuryAPIs) SubmitJuryUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitCovenantUnbondingSigs mocks base method. +func (m *MockCovenantAPIs) SubmitCovenantUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. -func (mr *MockJuryAPIsMockRecorder) SubmitJuryUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { +// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockJuryAPIs)(nil).SubmitJuryUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) } diff --git a/tools/go.mod b/tools/go.mod index bae724d8..17b0b356 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -29,7 +29,7 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd v0.23.4 // indirect + github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect @@ -179,7 +179,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 diff --git a/tools/go.sum b/tools/go.sum index d5a6783c..fcd4dafa 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -255,6 +255,7 @@ github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8 github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= +github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f/go.mod h1:Omv/7j7d/KioUlGhffrA1uajzYwx959cLElstveJwKc= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -273,6 +274,7 @@ github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tj github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= diff --git a/types/delegation.go b/types/delegation.go index 6c7ef908..4e66838b 100644 --- a/types/delegation.go +++ b/types/delegation.go @@ -21,12 +21,12 @@ type Delegation struct { StakingTxHex string // slashing_tx_hex is the hex string of the slashing tx // It is partially signed by SK corresponding to btc_pk, but not signed by - // validator or jury yet. + // validator or covenant yet. SlashingTxHex string - // jury_sig is the signature on the slashing tx - // by the jury (i.e., SK corresponding to jury_pk in params) + // covenant_sig is the signature on the slashing tx + // by the covenant (i.e., SK corresponding to covenant_pk in params) // It will be a part of the witness for the staking tx output. - JurySig *schnorr.Signature + CovenantSig *schnorr.Signature // if this object is present it menans that staker requested undelegation, and whole // delegation is being undelegated. // directly in delegation object @@ -41,19 +41,19 @@ type Undelegation struct { UnbondingTxHex string // slashing_tx is the hex string of the slashing tx for unbodning transactions // It is partially signed by SK corresponding to btc_pk, but not signed by - // validator or jury yet. + // validator or covenant yet. SlashingTxHex string - // jury_slashing_sig is the signature on the slashing tx - // by the jury (i.e., SK corresponding to jury_pk in params) + // covenant_slashing_sig is the signature on the slashing tx + // by the covenant (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain - JurySlashingSig *schnorr.Signature - // jury_unbonding_sig is the signature on the unbonding tx - // by the jury (i.e., SK corresponding to jury_pk in params) + CovenantSlashingSig *schnorr.Signature + // covenant_unbonding_sig is the signature on the unbonding tx + // by the covenant (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain and after // validator sig will be provided by validator - JuryUnbondingSig *schnorr.Signature + CovenantUnbondingSig *schnorr.Signature // validator_unbonding_sig is the signature on the unbonding tx - // by the validator (i.e., SK corresponding to jury_pk in params) + // by the validator (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain ValidatorUnbondingSig *schnorr.Signature } diff --git a/types/params.go b/types/params.go new file mode 100644 index 00000000..007059be --- /dev/null +++ b/types/params.go @@ -0,0 +1,25 @@ +package types + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" +) + +type StakingParams struct { + // K-deep + ComfirmationTimeBlocks uint64 + // W-deep + FinalizationTimeoutBlocks uint64 + + // Minimum amount of satoshis required for slashing transaction + MinSlashingTxFeeSat btcutil.Amount + + // Bitcoin public key of the current covenant + CovenantPk *btcec.PublicKey + + // Address to which slashing transactions are sent + SlashingAddress string + + // Minimum commission required by the consumer chain + MinCommissionRate string +} diff --git a/valcfg/config.go b/valcfg/config.go index 0ba130e1..8ec070a1 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -83,7 +83,7 @@ type Config struct { ActiveNetParams chaincfg.Params - JuryMode bool `long:"jurymode" description:"If the program is running in Jury mode"` + CovenantMode bool `long:"covenantmode" description:"If the program is running in Covenant mode"` PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` @@ -95,7 +95,7 @@ type Config struct { ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - JuryModeConfig *JuryConfig `group:"jury" namespace:"jury"` + CovenantModeConfig *CovenantConfig `group:"covenant" namespace:"covenant"` GRpcServerConfig *GRpcServerConfig @@ -105,7 +105,7 @@ type Config struct { func DefaultConfig() Config { bbnCfg := DefaultBBNConfig() dbCfg := DefaultDatabaseConfig() - juryCfg := DefaultJuryConfig() + covenantCfg := DefaultCovenantConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() eotsMngrCfg := DefaultEOTSManagerConfig() @@ -119,7 +119,7 @@ func DefaultConfig() Config { DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, ValidatorModeConfig: &valCfg, - JuryModeConfig: &juryCfg, + CovenantModeConfig: &covenantCfg, PollerConfig: &pollerCfg, EOTSManagerConfig: &eotsMngrCfg, NumPubRand: defaultNumPubRand, diff --git a/valcfg/covenant.go b/valcfg/covenant.go new file mode 100644 index 00000000..5bce2123 --- /dev/null +++ b/valcfg/covenant.go @@ -0,0 +1,26 @@ +package valcfg + +import ( + "time" +) + +var ( + defaultCovenantKeyName = "covenant-key" + defaultQueryInterval = 15 * time.Second + defaultDelegationLimit = uint64(100) +) + +type CovenantConfig struct { + CovenantKeyName string `long:"covenantkeyname" description:"The key name of the Covenant if the program is running in Covenant mode"` + QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` + DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` + SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` +} + +func DefaultCovenantConfig() CovenantConfig { + return CovenantConfig{ + CovenantKeyName: defaultCovenantKeyName, + QueryInterval: defaultQueryInterval, + DelegationLimit: defaultDelegationLimit, + } +} diff --git a/valcfg/jury.go b/valcfg/jury.go deleted file mode 100644 index 22e17ea2..00000000 --- a/valcfg/jury.go +++ /dev/null @@ -1,25 +0,0 @@ -package valcfg - -import ( - "time" -) - -var ( - defaultJuryKeyName = "jury-key" - defaultQueryInterval = 15 * time.Second - defaultDelegationLimit = uint64(100) -) - -type JuryConfig struct { - JuryKeyName string `long:"jurykeyname" description:"The key name of the Jury if the program is running in Jury mode"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` - DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Jury processes each time"` -} - -func DefaultJuryConfig() JuryConfig { - return JuryConfig{ - JuryKeyName: defaultJuryKeyName, - QueryInterval: defaultQueryInterval, - DelegationLimit: defaultDelegationLimit, - } -} From d1f1a6f8c542e3953c437e8a6edb65008b806b59 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 17 Nov 2023 12:43:22 +0800 Subject: [PATCH 15/66] feat: Add support for file backend for keyrings (#139) --- cmd/valcli/covenant.go | 13 +- cmd/valcli/daemoncmd.go | 34 ++- eotsmanager/client/rpcclient.go | 26 +- eotsmanager/config/config.go | 3 +- eotsmanager/eotsmanager.go | 19 +- eotsmanager/localmanager.go | 55 +++-- eotsmanager/localmanager_test.go | 19 +- eotsmanager/proto/eotsmanager.pb.go | 206 ++++++++++------ eotsmanager/proto/eotsmanager.proto | 16 +- eotsmanager/service/rpcserver.go | 10 +- itest/babylon_node_handler.go | 6 +- itest/test_manager.go | 17 +- proto/validators.pb.go | 367 +++++++++++++++------------- proto/validators.proto | 14 +- service/app.go | 45 +++- service/app_test.go | 19 +- service/client/rpcclient.go | 27 +- service/keyring.go | 5 +- service/rpcserver.go | 12 +- service/types.go | 3 +- service/utils.go | 27 -- service/validator_instance.go | 10 +- service/validator_instance_test.go | 4 +- service/validator_manager.go | 5 +- service/validator_manager_test.go | 19 +- testutil/datagen.go | 7 +- val/keyringcontroller.go | 24 +- val/keyringcontroller_test.go | 18 +- valcfg/babylon.go | 5 +- 29 files changed, 609 insertions(+), 426 deletions(-) delete mode 100644 service/utils.go diff --git a/cmd/valcli/covenant.go b/cmd/valcli/covenant.go index 790e0931..2ecdbf85 100644 --- a/cmd/valcli/covenant.go +++ b/cmd/valcli/covenant.go @@ -44,6 +44,16 @@ var createCovenant = cli.Command{ Usage: "The unique name of the Covenant key", 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: "Select keyring's backend (os|file|test)", @@ -75,10 +85,11 @@ func createCovenantKey(ctx *cli.Context) error { return err } - sdkCovenantPk, err := krController.CreateChainKey() + sdkCovenantPk, err := krController.CreateChainKey(ctx.String(passphraseFlag), ctx.String(hdPathFlag)) if err != nil { return fmt.Errorf("failed to create Covenant key: %w", err) } + covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) if err != nil { return err diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index d41053c7..97e831e4 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -8,6 +8,7 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" "github.com/babylonchain/babylon/x/checkpointing/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" @@ -38,12 +39,15 @@ const ( valBTCPkFlag = "btc-pk" blockHeightFlag = "height" lastCommitHashFlag = "last-commit-hash" - passPhraseFlag = "pass-phrase" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" chainIdFlag = "chain-id" keyringDirFlag = "keyring-dir" keyringBackendFlag = "keyring-backend" defaultChainID = "chain-test" - defaultKeyringBackend = "test" + defaultKeyringBackend = keyring.BackendTest + defaultPassphrase = "" + defaultHdPath = "" // flags for description monikerFlag = "moniker" @@ -114,8 +118,14 @@ var createValDaemonCmd = cli.Command{ Required: true, }, cli.StringFlag{ - Name: passPhraseFlag, + 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: commissionRateFlag, @@ -153,7 +163,6 @@ var createValDaemonCmd = cli.Command{ func createValDaemon(ctx *cli.Context) error { daemonAddress := ctx.String(valdDaemonAddressFlag) - keyName := ctx.String(keyNameFlag) commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) if err != nil { @@ -171,7 +180,15 @@ func createValDaemon(ctx *cli.Context) error { } defer cleanUp() - info, err := client.CreateValidator(context.Background(), keyName, ctx.String(chainIdFlag), ctx.String(passPhraseFlag), &description, &commissionRate) + info, err := client.CreateValidator( + context.Background(), + ctx.String(keyNameFlag), + ctx.String(chainIdFlag), + ctx.String(passphraseFlag), + ctx.String(hdPathFlag), + &description, + &commissionRate, + ) if err != nil { return err @@ -284,6 +301,11 @@ var registerValDaemonCmd = cli.Command{ Usage: "The hex string of the validator BTC public key", Required: true, }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, }, Action: registerVal, } @@ -302,7 +324,7 @@ func registerVal(ctx *cli.Context) error { } defer cleanUp() - res, err := rpcClient.RegisterValidator(context.Background(), valPk) + res, err := rpcClient.RegisterValidator(context.Background(), valPk, ctx.String(passphraseFlag)) if err != nil { return err } diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 8b055128..b6caf494 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -44,8 +44,8 @@ func (c *EOTSManagerGRpcClient) Ping() error { return nil } -func (c *EOTSManagerGRpcClient) CreateKey(name, passPhrase string) ([]byte, error) { - req := &proto.CreateKeyRequest{Name: name, PassPhrase: passPhrase} +func (c *EOTSManagerGRpcClient) CreateKey(name, passphrase, hdPath string) ([]byte, error) { + req := &proto.CreateKeyRequest{Name: name, Passphrase: passphrase, HdPath: hdPath} res, err := c.client.CreateKey(context.Background(), req) if err != nil { return nil, err @@ -54,12 +54,13 @@ func (c *EOTSManagerGRpcClient) CreateKey(name, passPhrase string) ([]byte, erro return res.Pk, nil } -func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { +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, } res, err := c.client.CreateRandomnessPairList(context.Background(), req) if err != nil { @@ -76,8 +77,8 @@ func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, st return pubRandFieldValList, nil } -func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) { - req := &proto.KeyRecordRequest{Uid: uid, PassPhrase: passPhrase} +func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) { + req := &proto.KeyRecordRequest{Uid: uid, Passphrase: passphrase} res, err := c.client.KeyRecord(context.Background(), req) if err != nil { @@ -92,12 +93,13 @@ func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passPhrase string) (*types }, nil } -func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64) (*btcec.ModNScalar, error) { +func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { req := &proto.SignEOTSRequest{ - Uid: uid, - ChainId: chaiID, - Msg: msg, - Height: height, + Uid: uid, + ChainId: chaiID, + Msg: msg, + Height: height, + Passphrase: passphrase, } res, err := c.client.SignEOTS(context.Background(), req) if err != nil { @@ -110,8 +112,8 @@ func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64) return &s, nil } -func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte) (*schnorr.Signature, error) { - req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg} +func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte, passphrase string) (*schnorr.Signature, error) { + req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg, Passphrase: passphrase} res, err := c.client.SignSchnorrSig(context.Background(), req) if err != nil { return nil, err diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 088c2c8e..82846bd7 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/btcsuite/btcd/btcutil" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/jessevdk/go-flags" "github.com/sirupsen/logrus" ) @@ -22,7 +23,7 @@ const ( defaultLogFilename = "eotsd.log" defaultConfigFileName = "eotsd.conf" DefaultRPCPort = 15813 - defaultKeyringBackend = "test" + defaultKeyringBackend = keyring.BackendFile ) var ( diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index 5c6b7a0a..c24d4fb2 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -11,27 +11,30 @@ type EOTSManager interface { // CreateKey generates a key pair at the given name and persists it in storage. // The key pair is formatted by BIP-340 (Schnorr Signatures) // It fails if there is an existing key Info with the same name or public key. - CreateKey(name, passPhrase string) ([]byte, error) + CreateKey(name, passphrase, hdPath string) ([]byte, error) // CreateRandomnessPairList generates a list of Schnorr randomness pairs from - // startHeight to startHeight+(num-1)*step where step means the gap between each block height - // that the validator wants to finalize and num means the number of public randomness + // startHeight to startHeight+(num-1) where num means the number of public randomness // It fails if the validator does not exist or a randomness pair has been created before - // NOTE: it will overwrite the randomness regardless of whether there's one existed - CreateRandomnessPairList(uid []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) + // 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) // KeyRecord returns the validator record // It fails if the validator does not exist or passPhrase is incorrect - KeyRecord(uid []byte, passPhrase string) (*types.KeyRecord, error) + KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) // SignEOTS signs an EOTS using the private key of the validator and the corresponding // secret randomness of the give chain at the given height // It fails if the validator does not exist or there's no randomness committed to the given height - SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64) (*btcec.ModNScalar, error) + // or passPhrase is incorrect + SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) // SignSchnorrSig signs a Schnorr signature using the private key of the validator // It fails if the validator does not exist or the message size is not 32 bytes - SignSchnorrSig(uid []byte, msg []byte) (*schnorr.Signature, error) + // or passPhrase is incorrect + SignSchnorrSig(uid []byte, msg []byte, passphrase string) (*schnorr.Signature, error) Close() error } diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index ce75711b..be485a94 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -4,12 +4,12 @@ import ( "fmt" "os" "path" + "strings" "github.com/babylonchain/babylon/crypto/eots" bbntypes "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" @@ -32,6 +32,8 @@ type LocalEOTSManager struct { kr keyring.Keyring es *EOTSStore logger *logrus.Logger + // input is to send passphrase to kr + input *strings.Reader } func NewLocalEOTSManager(eotsCfg *config.Config, logger *logrus.Logger) (*LocalEOTSManager, error) { @@ -44,22 +46,18 @@ func NewLocalEOTSManager(eotsCfg *config.Config, logger *logrus.Logger) (*LocalE keyringDir = path.Join(homeDir, ".eots-manager") } - ctx := client.Context{}. - WithCodec(codec.MakeCodec()). - WithKeyringDir(keyringDir) - if eotsCfg.KeyringBackend == "" { return nil, fmt.Errorf("the keyring backend should not be empty") } + inputReader := strings.NewReader("") kr, err := keyring.New( - ctx.ChainID, - // TODO currently only support test backend + "eots-manager", eotsCfg.KeyringBackend, - ctx.KeyringDir, - ctx.Input, - ctx.Codec, - ctx.KeyringOptions...) + keyringDir, + inputReader, + codec.MakeCodec(), + ) if err != nil { return nil, fmt.Errorf("failed to create keyring: %w", err) } @@ -73,10 +71,11 @@ func NewLocalEOTSManager(eotsCfg *config.Config, logger *logrus.Logger) (*LocalE kr: kr, es: es, logger: logger, + input: inputReader, }, nil } -func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { +func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, error) { if lm.keyExists(name) { return nil, eotstypes.ErrValidatorAlreadyExisted } @@ -98,8 +97,11 @@ func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { return nil, err } - // TODO for now we leave and hdPath empty - record, err := lm.kr.NewAccount(name, mnemonic, passPhrase, "", algo) + // we need to repeat the passphrase to mock the re-entry + // as when creating an account, passphrase will be asked twice + // by the keyring + lm.input.Reset(passphrase + "\n" + passphrase) + record, err := lm.kr.NewAccount(name, mnemonic, passphrase, hdPath, algo) if err != nil { return nil, err } @@ -134,12 +136,12 @@ func (lm *LocalEOTSManager) CreateKey(name, passPhrase string) ([]byte, error) { // // a simple anti-slasher mechanism could be that the manager remembers the tuple (valPk, chainID, height) or // the hash of each generated randomness and return error if the same randomness is requested tweice -func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byte, startHeight uint64, num uint32) ([]*btcec.FieldVal, error) { +func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { prList := make([]*btcec.FieldVal, 0, num) for i := uint32(0); i < num; i++ { height := startHeight + uint64(i) - _, pubRand, err := lm.getRandomnessPair(valPk, chainID, height) + _, pubRand, err := lm.getRandomnessPair(valPk, chainID, height, passphrase) if err != nil { return nil, err } @@ -150,13 +152,13 @@ func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byt return prList, nil } -func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, height uint64) (*btcec.ModNScalar, error) { - privRand, _, err := lm.getRandomnessPair(valPk, chainID, height) +func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { + privRand, _, err := lm.getRandomnessPair(valPk, chainID, height, passphrase) if err != nil { return nil, fmt.Errorf("failed to get private randomness: %w", err) } - privKey, err := lm.getEOTSPrivKey(valPk) + privKey, err := lm.getEOTSPrivKey(valPk, passphrase) if err != nil { return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } @@ -164,8 +166,8 @@ func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, h return eots.Sign(privKey, privRand, msg) } -func (lm *LocalEOTSManager) SignSchnorrSig(valPk []byte, msg []byte) (*schnorr.Signature, error) { - privKey, err := lm.getEOTSPrivKey(valPk) +func (lm *LocalEOTSManager) SignSchnorrSig(valPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { + privKey, err := lm.getEOTSPrivKey(valPk, passphrase) if err != nil { return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } @@ -178,8 +180,8 @@ func (lm *LocalEOTSManager) Close() error { } // getRandomnessPair returns a randomness pair generated based on the given validator key, chainID and height -func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, height uint64) (*eots.PrivateRand, *eots.PublicRand, error) { - record, err := lm.KeyRecord(valPk, "") +func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, height uint64, passphrase string) (*eots.PrivateRand, *eots.PublicRand, error) { + record, err := lm.KeyRecord(valPk, passphrase) if err != nil { return nil, nil, err } @@ -188,12 +190,12 @@ func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, heig } // TODO: we ignore passPhrase in local implementation for now -func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passPhrase string) (*eotstypes.KeyRecord, error) { +func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passphrase string) (*eotstypes.KeyRecord, error) { name, err := lm.es.getValidatorKeyName(valPk) if err != nil { return nil, err } - privKey, err := lm.getEOTSPrivKey(valPk) + privKey, err := lm.getEOTSPrivKey(valPk, passphrase) if err != nil { return nil, err } @@ -204,12 +206,13 @@ func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passPhrase string) (*eotstyp }, nil } -func (lm *LocalEOTSManager) getEOTSPrivKey(valPk []byte) (*btcec.PrivateKey, error) { +func (lm *LocalEOTSManager) getEOTSPrivKey(valPk []byte, passphrase string) (*btcec.PrivateKey, error) { keyName, err := lm.es.getValidatorKeyName(valPk) if err != nil { return nil, err } + lm.input.Reset(passphrase) k, err := lm.kr.Key(keyName) if err != nil { return nil, err diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go index 3928a508..f944aeab 100644 --- a/eotsmanager/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -14,6 +14,11 @@ import ( "github.com/babylonchain/btc-validator/testutil" ) +var ( + passphrase = "testpass" + hdPath = "" +) + // FuzzCreateKey tests the creation of an EOTS key func FuzzCreateKey(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) @@ -32,18 +37,18 @@ func FuzzCreateKey(f *testing.F) { lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) require.NoError(t, err) - valPk, err := lm.CreateKey(valName, "") + valPk, err := lm.CreateKey(valName, passphrase, hdPath) require.NoError(t, err) - valRecord, err := lm.KeyRecord(valPk, "") + valRecord, err := lm.KeyRecord(valPk, passphrase) require.NoError(t, err) require.Equal(t, valName, valRecord.Name) - sig, err := lm.SignSchnorrSig(valPk, datagen.GenRandomByteArray(r, 32)) + sig, err := lm.SignSchnorrSig(valPk, datagen.GenRandomByteArray(r, 32), passphrase) require.NoError(t, err) require.NotNil(t, sig) - _, err = lm.CreateKey(valName, "") + _, err = lm.CreateKey(valName, passphrase, hdPath) require.ErrorIs(t, err, types.ErrValidatorAlreadyExisted) }) } @@ -65,18 +70,18 @@ func FuzzCreateRandomnessPairList(f *testing.F) { lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) require.NoError(t, err) - valPk, err := lm.CreateKey(valName, "") + valPk, err := lm.CreateKey(valName, passphrase, hdPath) require.NoError(t, err) chainID := datagen.GenRandomByteArray(r, 10) startHeight := datagen.RandomInt(r, 100) num := r.Intn(10) + 1 - pubRandList, err := lm.CreateRandomnessPairList(valPk, chainID, startHeight, uint32(num)) + pubRandList, err := lm.CreateRandomnessPairList(valPk, chainID, startHeight, uint32(num), passphrase) require.NoError(t, err) require.Len(t, pubRandList, num) for i := 0; i < num; i++ { - sig, err := lm.SignEOTS(valPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i)) + sig, err := lm.SignEOTS(valPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i), passphrase) require.NoError(t, err) require.NotNil(t, sig) } diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index 5a7fd11a..0b7d3a68 100644 --- a/eotsmanager/proto/eotsmanager.pb.go +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -103,8 +103,10 @@ type CreateKeyRequest struct { // name is the identifier key in keyring Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // pass_phrase is used to encrypt the keys - PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` + // passphrase is used to encrypt the EOTS key + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` } func (x *CreateKeyRequest) Reset() { @@ -146,9 +148,16 @@ func (x *CreateKeyRequest) GetName() string { return "" } -func (x *CreateKeyRequest) GetPassPhrase() string { +func (x *CreateKeyRequest) GetPassphrase() string { if x != nil { - return x.PassPhrase + return x.Passphrase + } + return "" +} + +func (x *CreateKeyRequest) GetHdPath() string { + if x != nil { + return x.HdPath } return "" } @@ -214,6 +223,8 @@ type CreateRandomnessPairListRequest struct { 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"` } func (x *CreateRandomnessPairListRequest) Reset() { @@ -276,6 +287,13 @@ func (x *CreateRandomnessPairListRequest) GetNum() uint32 { return 0 } +func (x *CreateRandomnessPairListRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + type CreateRandomnessPairListResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -331,8 +349,8 @@ type KeyRecordRequest struct { // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` - // pass_phrase is used to decrypt the keys - PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` } func (x *KeyRecordRequest) Reset() { @@ -374,9 +392,9 @@ func (x *KeyRecordRequest) GetUid() []byte { return nil } -func (x *KeyRecordRequest) GetPassPhrase() string { +func (x *KeyRecordRequest) GetPassphrase() string { if x != nil { - return x.PassPhrase + return x.Passphrase } return "" } @@ -451,6 +469,8 @@ type SignEOTSRequest struct { Msg []byte `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` // the block height which the EOTS signs Height uint64 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,5,opt,name=passphrase,proto3" json:"passphrase,omitempty"` } func (x *SignEOTSRequest) Reset() { @@ -513,6 +533,13 @@ func (x *SignEOTSRequest) GetHeight() uint64 { return 0 } +func (x *SignEOTSRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + type SignEOTSResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -570,6 +597,8 @@ type SignSchnorrSigRequest struct { Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` // the message which the Schnorr signature signs Msg []byte `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,3,opt,name=passphrase,proto3" json:"passphrase,omitempty"` } func (x *SignSchnorrSigRequest) Reset() { @@ -618,6 +647,13 @@ func (x *SignSchnorrSigRequest) GetMsg() []byte { return nil } +func (x *SignSchnorrSigRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + type SignSchnorrSigResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -672,83 +708,91 @@ var file_eotsmanager_proto_rawDesc = []byte{ 0x0a, 0x11, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0d, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x47, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 0x68, 0x72, 0x61, - 0x73, 0x65, 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, 0x83, 0x01, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, + 0x65, 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, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 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, + 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, 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, 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, 0x45, 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, 0x1f, 0x0a, 0x0b, 0x70, - 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x50, 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, 0x68, 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, - 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, 0x3b, 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, 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, + 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, 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, 0x39, 0x5a, 0x37, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 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, + 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, 0x39, 0x5a, 0x37, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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 ( diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto index 29974bfc..f85e0347 100644 --- a/eotsmanager/proto/eotsmanager.proto +++ b/eotsmanager/proto/eotsmanager.proto @@ -35,8 +35,10 @@ message PingResponse {} message CreateKeyRequest { // name is the identifier key in keyring string name = 1; - // pass_phrase is used to encrypt the keys - string pass_phrase = 2; + // passphrase is used to encrypt the EOTS key + string passphrase = 2; + // hd_path is the hd path for private key derivation + string hd_path = 3; } message CreateKeyResponse { @@ -53,6 +55,8 @@ message CreateRandomnessPairListRequest { 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; } message CreateRandomnessPairListResponse { @@ -63,8 +67,8 @@ message CreateRandomnessPairListResponse { message KeyRecordRequest { // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec bytes uid = 1; - // pass_phrase is used to decrypt the keys - string pass_phrase = 2; + // passphrase is used to decrypt the EOTS key + string passphrase = 2; } message KeyRecordResponse { @@ -83,6 +87,8 @@ message SignEOTSRequest { bytes msg = 3; // the block height which the EOTS signs uint64 height = 4; + // passphrase is used to decrypt the EOTS key + string passphrase = 5; } message SignEOTSResponse { @@ -95,6 +101,8 @@ message SignSchnorrSigRequest { bytes uid = 1; // the message which the Schnorr signature signs bytes msg = 2; + // passphrase is used to decrypt the EOTS key + string passphrase = 3; } message SignSchnorrSigResponse { diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go index e7b57e5d..ee7e0fc3 100644 --- a/eotsmanager/service/rpcserver.go +++ b/eotsmanager/service/rpcserver.go @@ -43,7 +43,7 @@ func (r *rpcServer) Ping(ctx context.Context, req *proto.PingRequest) (*proto.Pi func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) ( *proto.CreateKeyResponse, error) { - pk, err := r.em.CreateKey(req.Name, req.PassPhrase) + pk, err := r.em.CreateKey(req.Name, req.Passphrase, req.HdPath) if err != nil { return nil, err @@ -56,7 +56,7 @@ func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) 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) + pubRandList, err := r.em.CreateRandomnessPairList(req.Uid, req.ChainId, req.StartHeight, req.Num, req.Passphrase) if err != nil { return nil, err @@ -76,7 +76,7 @@ func (r *rpcServer) CreateRandomnessPairList(ctx context.Context, req *proto.Cre func (r *rpcServer) KeyRecord(ctx context.Context, req *proto.KeyRecordRequest) ( *proto.KeyRecordResponse, error) { - record, err := r.em.KeyRecord(req.Uid, req.PassPhrase) + record, err := r.em.KeyRecord(req.Uid, req.Passphrase) if err != nil { return nil, err } @@ -93,7 +93,7 @@ func (r *rpcServer) KeyRecord(ctx context.Context, req *proto.KeyRecordRequest) func (r *rpcServer) SignEOTS(ctx context.Context, req *proto.SignEOTSRequest) ( *proto.SignEOTSResponse, error) { - sig, err := r.em.SignEOTS(req.Uid, req.ChainId, req.Msg, req.Height) + sig, err := r.em.SignEOTS(req.Uid, req.ChainId, req.Msg, req.Height, req.Passphrase) if err != nil { return nil, err } @@ -107,7 +107,7 @@ func (r *rpcServer) SignEOTS(ctx context.Context, req *proto.SignEOTSRequest) ( func (r *rpcServer) SignSchnorrSig(ctx context.Context, req *proto.SignSchnorrSigRequest) ( *proto.SignSchnorrSigResponse, error) { - sig, err := r.em.SignSchnorrSig(req.Uid, req.Msg) + sig, err := r.em.SignSchnorrSig(req.Uid, req.Msg, req.Passphrase) if err != nil { return nil, err } diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index c7442ac7..1aa3e14d 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/require" @@ -124,7 +125,6 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { nodeDataDir := filepath.Join(testDir, "node0", "babylond") // the Covenant key needs to be created before babylond is started - chainID := "chain-test" sdkCtx, err := service.CreateClientCtx( nodeDataDir, chainID, @@ -134,10 +134,10 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { krController, err := val.NewChainKeyringController( sdkCtx, covenantKeyName, - "test", + keyring.BackendTest, ) require.NoError(t, err) - sdkCovenantPk, err := krController.CreateChainKey() + sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) require.NoError(t, err) covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) require.NoError(t, err) diff --git a/itest/test_manager.go b/itest/test_manager.go index f5149f90..cea4b1fb 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -36,6 +36,12 @@ import ( var ( eventuallyWaitTimeOut = 1 * time.Minute eventuallyPollTime = 500 * time.Millisecond + + valNamePrefix = "test-val-" + monikerPrefix = "moniker-" + chainID = "chain-test" + passphrase = "testpass" + hdPath = "" ) var btcNetworkParams = &chaincfg.SimNetParams @@ -129,20 +135,15 @@ func StartManagerWithValidator(t *testing.T, n int, isCovenant bool) *TestManage tm := StartManager(t, isCovenant) app := tm.Va - var ( - valNamePrefix = "test-val-" - monikerPrefix = "moniker-" - chainID = "chain-test" - ) for i := 0; i < n; i++ { valName := valNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) commission := sdktypes.ZeroDec() - res, err := app.CreateValidator(valName, chainID, "", newDescription(moniker), &commission) + res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, newDescription(moniker), &commission) require.NoError(t, err) _, err = app.RegisterValidator(res.ValPk.MarshalHex()) require.NoError(t, err) - err = app.StartHandlingValidator(res.ValPk) + err = app.StartHandlingValidator(res.ValPk, passphrase) require.NoError(t, err) valIns, err := app.GetValidatorInstance(res.ValPk) require.NoError(t, err) @@ -477,7 +478,7 @@ func (tm *TestManager) GetCovenantPrivKey(t *testing.T) *btcec.PrivateKey { } func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { - record, err := tm.EOTSClient.KeyRecord(valPk, "") + record, err := tm.EOTSClient.KeyRecord(valPk, passphrase) require.NoError(t, err) return record.PrivKey } diff --git a/proto/validators.pb.go b/proto/validators.pb.go index d00ecf48..e1928ec0 100644 --- a/proto/validators.pb.go +++ b/proto/validators.pb.go @@ -191,15 +191,17 @@ type CreateValidatorRequest struct { // key_name is the identifier key in keyring KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` - // pass_phrase is used to encrypt the keys - PassPhrase string `protobuf:"bytes,2,opt,name=pass_phrase,json=passPhrase,proto3" json:"pass_phrase,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` // chain_id is the identifier of the consumer chain that the validator connected to - ChainId string `protobuf:"bytes,3,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ChainId string `protobuf:"bytes,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + Description *types.Description `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the validator // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - Commission string `protobuf:"bytes,5,opt,name=commission,proto3" json:"commission,omitempty"` + Commission string `protobuf:"bytes,6,opt,name=commission,proto3" json:"commission,omitempty"` } func (x *CreateValidatorRequest) Reset() { @@ -241,9 +243,16 @@ func (x *CreateValidatorRequest) GetKeyName() string { return "" } -func (x *CreateValidatorRequest) GetPassPhrase() string { +func (x *CreateValidatorRequest) GetPassphrase() string { if x != nil { - return x.PassPhrase + return x.Passphrase + } + return "" +} + +func (x *CreateValidatorRequest) GetHdPath() string { + if x != nil { + return x.HdPath } return "" } @@ -324,6 +333,8 @@ type RegisterValidatorRequest struct { // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` } func (x *RegisterValidatorRequest) Reset() { @@ -365,6 +376,13 @@ func (x *RegisterValidatorRequest) GetBtcPk() string { return "" } +func (x *RegisterValidatorRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + type RegisterValidatorResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1101,177 +1119,180 @@ var file_validators_proto_rawDesc = []byte{ 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0x90, 0x02, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0xa8, 0x02, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x68, - 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, - 0x50, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, - 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, - 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, - 0x74, 0x63, 0x50, 0x6b, 0x22, 0x31, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x76, 0x0a, - 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 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, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, + 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x51, 0x0a, 0x18, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, + 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 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, + 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x76, 0x0a, 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, + 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, + 0x0a, 0x1c, 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, 0x17, + 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, + 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, + 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, + 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, - 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, + 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, + 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, + 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, + 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, + 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, + 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, + 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, + 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 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, + 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 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, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, - 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, + 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, 0x4d, 0x0a, 0x0e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x12, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, + 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, - 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, - 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, - 0x0a, 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, 0x2e, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, - 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, - 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 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, 0x32, 0x0a, - 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, - 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 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, 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, - 0x42, 0x74, 0x63, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x4d, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x59, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, - 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, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/validators.proto b/proto/validators.proto index f461b2e7..8e283723 100644 --- a/proto/validators.proto +++ b/proto/validators.proto @@ -43,15 +43,17 @@ message GetInfoResponse { message CreateValidatorRequest { // key_name is the identifier key in keyring string key_name = 1; - // pass_phrase is used to encrypt the keys - string pass_phrase = 2; + // passphrase is used to encrypt the keys + string passphrase = 2; + // hd_path is the hd path for private key derivation + string hd_path = 3; // chain_id is the identifier of the consumer chain that the validator connected to - string chain_id = 3; + string chain_id = 4; // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 4; + cosmos.staking.v1beta1.Description description = 5; // commission defines the commission rate for the validator // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 5 [ + string commission = 6 [ (cosmos_proto.scalar) = "cosmos.Dec", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" ]; @@ -65,6 +67,8 @@ message CreateValidatorResponse { message RegisterValidatorRequest { // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec string btc_pk = 1; + // passphrase is used to encrypt the keys + string passphrase = 2; } message RegisterValidatorResponse { diff --git a/service/app.go b/service/app.go index 50757f69..01fad2c2 100644 --- a/service/app.go +++ b/service/app.go @@ -2,6 +2,7 @@ package service import ( "fmt" + "strings" "sync" "cosmossdk.io/math" @@ -41,6 +42,7 @@ type ValidatorApp struct { vs *val.ValidatorStore config *valcfg.Config logger *logrus.Logger + input *strings.Reader validatorManager *ValidatorManager eotsManager eotsmanager.EOTSManager @@ -91,9 +93,13 @@ func NewValidatorApp( em eotsmanager.EOTSManager, logger *logrus.Logger, ) (*ValidatorApp, error) { - kr, err := CreateKeyring(config.BabylonConfig.KeyDirectory, + input := strings.NewReader("") + kr, err := CreateKeyring( + config.BabylonConfig.KeyDirectory, config.BabylonConfig.ChainID, - config.BabylonConfig.KeyringBackend) + config.BabylonConfig.KeyringBackend, + input, + ) if err != nil { return nil, fmt.Errorf("failed to create keyring: %w", err) } @@ -104,11 +110,11 @@ func NewValidatorApp( } if config.CovenantMode { - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.CovenantModeConfig.CovenantKeyName) + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.CovenantModeConfig.CovenantKeyName, input) if err != nil { return nil, err } - if _, err := kc.GetChainPrivKey(); err != nil { + if _, err := kc.GetChainPrivKey(""); err != nil { return nil, fmt.Errorf("the program is running in Covenant mode but the Covenant key %s is not found: %w", config.CovenantModeConfig.CovenantKeyName, err) } @@ -125,6 +131,7 @@ func NewValidatorApp( kr: kr, config: config, logger: logger, + input: input, validatorManager: vm, eotsManager: em, quit: make(chan struct{}), @@ -148,6 +155,10 @@ func (app *ValidatorApp) GetKeyring() keyring.Keyring { return app.kr } +func (app *ValidatorApp) GetInput() *strings.Reader { + return app.input +} + func (app *ValidatorApp) ListValidatorInstances() []*ValidatorInstance { return app.validatorManager.ListValidatorInstances() } @@ -212,8 +223,8 @@ func (app *ValidatorApp) RegisterValidator(valPkStr string) (*RegisterValidatorR // StartHandlingValidator starts a validator instance with the given Babylon public key // Note: this should be called right after the validator is registered -func (app *ValidatorApp) StartHandlingValidator(valPk *bbntypes.BIP340PubKey) error { - return app.validatorManager.addValidatorInstance(valPk) +func (app *ValidatorApp) StartHandlingValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { + return app.validatorManager.addValidatorInstance(valPk, passphrase) } func (app *ValidatorApp) StartHandlingValidators() error { @@ -419,12 +430,13 @@ func (app *ValidatorApp) AddCovenantUnbondingSignatures(del *types.Delegation) ( } func (app *ValidatorApp) getCovenantPrivKey() (*btcec.PrivateKey, error) { - kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.CovenantModeConfig.CovenantKeyName) + kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.CovenantModeConfig.CovenantKeyName, app.input) if err != nil { return nil, err } - sdkPrivKey, err := kc.GetChainPrivKey() + // TODO use empty passphrase for covenant for now, covenant should be run in a separate application + sdkPrivKey, err := kc.GetChainPrivKey("") if err != nil { return nil, err } @@ -434,6 +446,7 @@ func (app *ValidatorApp) getCovenantPrivKey() (*btcec.PrivateKey, error) { return privKey, nil } +// NOTE: this is not safe in production, so only used for testing purpose func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) { record, err := app.eotsManager.KeyRecord(valPk, "") if err != nil { @@ -513,11 +526,17 @@ func (app *ValidatorApp) Stop() error { return stopErr } -func (app *ValidatorApp) CreateValidator(keyName, chainID, passPhrase string, description *stakingtypes.Description, commission *sdktypes.Dec) (*CreateValidatorResult, error) { +func (app *ValidatorApp) CreateValidator( + keyName, chainID, passPhrase, hdPath string, + description *stakingtypes.Description, + commission *sdktypes.Dec, +) (*CreateValidatorResult, error) { + req := &createValidatorRequest{ keyName: keyName, chainID: chainID, passPhrase: passPhrase, + hdPath: hdPath, description: description, commission: commission, errResponse: make(chan error, 1), @@ -543,7 +562,7 @@ func (app *ValidatorApp) IsCovenant() bool { } func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { - valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase) + valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) if err != nil { return nil, err } @@ -553,12 +572,12 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, err } - kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName) + kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) if err != nil { return nil, err } - bbnPk, err := kr.CreateChainKey() + bbnPk, err := kr.CreateChainKey(req.passPhrase, req.hdPath) if err != nil { return nil, fmt.Errorf("failed to create chain key for the validator: %w", err) } @@ -568,7 +587,7 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, fmt.Errorf("failed to get validator record: %w", err) } - pop, err := kr.CreatePop(valRecord.PrivKey) + pop, err := kr.CreatePop(valRecord.PrivKey, req.passPhrase) if err != nil { return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) } diff --git a/service/app_test.go b/service/app_test.go index 526641ee..f8fa5f4d 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -23,6 +23,11 @@ import ( "github.com/babylonchain/btc-validator/valcfg" ) +var ( + passphrase = "testpass" + hdPath = "" +) + func FuzzRegisterValidator(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { @@ -61,7 +66,7 @@ func FuzzRegisterValidator(f *testing.F) { }() // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app) + validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) btcSig := new(bbntypes.BIP340Signature) err = btcSig.Unmarshal(validator.Pop.BtcSig) require.NoError(t, err) @@ -87,7 +92,7 @@ func FuzzRegisterValidator(f *testing.F) { require.NoError(t, err) require.Equal(t, txHash, res.TxHash) - err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK()) + err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK(), passphrase) require.NoError(t, err) valAfterReg, err := app.GetValidatorInstance(validator.MustGetBIP340BTCPK()) @@ -126,9 +131,13 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) // create a Covenant key pair in the keyring - covenantKc, err := val.NewChainKeyringControllerWithKeyring(app.GetKeyring(), cfg.CovenantModeConfig.CovenantKeyName) + covenantKc, err := val.NewChainKeyringControllerWithKeyring( + app.GetKeyring(), + cfg.CovenantModeConfig.CovenantKeyName, + app.GetInput(), + ) require.NoError(t, err) - sdkJurPk, err := covenantKc.CreateChainKey() + sdkJurPk, err := covenantKc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) covenantPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) require.NoError(t, err) @@ -143,7 +152,7 @@ func FuzzAddCovenantSig(f *testing.F) { }() // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app) + validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) btcPkBIP340 := validator.MustGetBIP340BTCPK() btcPk := validator.MustGetBTCPK() diff --git a/service/client/rpcclient.go b/service/client/rpcclient.go index e262bdda..5cd5bf04 100644 --- a/service/client/rpcclient.go +++ b/service/client/rpcclient.go @@ -42,8 +42,13 @@ func (c *ValidatorServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInf return res, nil } -func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, valPk *bbntypes.BIP340PubKey) (*proto.RegisterValidatorResponse, error) { - req := &proto.RegisterValidatorRequest{BtcPk: valPk.MarshalHex()} +func (c *ValidatorServiceGRpcClient) RegisterValidator( + ctx context.Context, + valPk *bbntypes.BIP340PubKey, + passphrase string, +) (*proto.RegisterValidatorResponse, error) { + + req := &proto.RegisterValidatorRequest{BtcPk: valPk.MarshalHex(), Passphrase: passphrase} res, err := c.client.RegisterValidator(ctx, req) if err != nil { return nil, err @@ -52,8 +57,22 @@ func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, valP return res, nil } -func (c *ValidatorServiceGRpcClient) CreateValidator(ctx context.Context, keyName, chainID, passPhrase string, description *stakingtypes.Description, commission *sdktypes.Dec) (*proto.CreateValidatorResponse, error) { - req := &proto.CreateValidatorRequest{KeyName: keyName, ChainId: chainID, PassPhrase: passPhrase, Description: description, Commission: commission.String()} +func (c *ValidatorServiceGRpcClient) CreateValidator( + ctx context.Context, + keyName, chainID, passphrase, hdPath string, + description *stakingtypes.Description, + commission *sdktypes.Dec, +) (*proto.CreateValidatorResponse, error) { + + req := &proto.CreateValidatorRequest{ + KeyName: keyName, + ChainId: chainID, + Passphrase: passphrase, + HdPath: hdPath, + Description: description, + Commission: commission.String(), + } + res, err := c.client.CreateValidator(ctx, req) if err != nil { return nil, err diff --git a/service/keyring.go b/service/keyring.go index bef3a482..8de0a551 100644 --- a/service/keyring.go +++ b/service/keyring.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path" + "strings" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -11,7 +12,7 @@ import ( "github.com/babylonchain/btc-validator/codec" ) -func CreateKeyring(keyringDir string, chainId string, backend string) (keyring.Keyring, error) { +func CreateKeyring(keyringDir string, chainId string, backend string, input *strings.Reader) (keyring.Keyring, error) { ctx, err := CreateClientCtx(keyringDir, chainId) if err != nil { return nil, err @@ -25,7 +26,7 @@ func CreateKeyring(keyringDir string, chainId string, backend string) (keyring.K ctx.ChainID, backend, ctx.KeyringDir, - ctx.Input, + input, ctx.Codec, ctx.KeyringOptions...) if err != nil { diff --git a/service/rpcserver.go b/service/rpcserver.go index eeae0a95..9a1fadce 100644 --- a/service/rpcserver.go +++ b/service/rpcserver.go @@ -107,7 +107,15 @@ func (r *rpcServer) CreateValidator(ctx context.Context, req *proto.CreateValida if err != nil { return nil, err } - result, err := r.app.CreateValidator(req.KeyName, req.ChainId, req.PassPhrase, req.Description, &commissionRate) + + result, err := r.app.CreateValidator( + req.KeyName, + req.ChainId, + req.Passphrase, + req.HdPath, + req.Description, + &commissionRate, + ) if err != nil { return nil, err @@ -129,7 +137,7 @@ func (r *rpcServer) RegisterValidator(ctx context.Context, req *proto.RegisterVa } // the validator instance should be started right after registration - if err := r.app.StartHandlingValidator(txRes.btcPubKey); err != nil { + if err := r.app.StartHandlingValidator(txRes.btcPubKey, req.Passphrase); err != nil { return nil, fmt.Errorf("failed to start the registered validator %s: %w", hex.EncodeToString(txRes.bbnPubKey.Key), err) } diff --git a/service/types.go b/service/types.go index 534bbeca..f1505801 100644 --- a/service/types.go +++ b/service/types.go @@ -21,6 +21,7 @@ type createValidatorResponse struct { type createValidatorRequest struct { keyName string passPhrase string + hdPath string chainID string description *stakingtypes.Description commission *sdktypes.Dec @@ -214,7 +215,7 @@ func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uin func (v *ValidatorInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { // TODO ignore pass phrase for now - record, err := v.em.KeyRecord(v.btcPk.MustMarshal(), "") + record, err := v.em.KeyRecord(v.btcPk.MustMarshal(), v.passphrase) if err != nil { return nil, err } diff --git a/service/utils.go b/service/utils.go deleted file mode 100644 index e9fa6a3b..00000000 --- a/service/utils.go +++ /dev/null @@ -1,27 +0,0 @@ -package service - -import ( - "math/rand" - "time" - - "github.com/babylonchain/babylon/crypto/eots" - "github.com/babylonchain/babylon/types" -) - -func GenerateRandPairList(num uint64) ([]*eots.PrivateRand, []types.SchnorrPubRand, error) { - srList := make([]*eots.PrivateRand, num) - prList := make([]types.SchnorrPubRand, num) - - r := rand.New(rand.NewSource(time.Now().UnixNano())) - - for i := uint64(0); i < num; i++ { - eotsSR, eotsPR, err := eots.RandGen(r) - if err != nil { - return nil, nil, err - } - pr := types.NewSchnorrPubRandFromFieldVal(eotsPR) - srList[i] = eotsSR - prList[i] = *pr - } - return srList, prList, nil -} diff --git a/service/validator_instance.go b/service/validator_instance.go index a734a02b..14bbb86a 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -38,6 +38,9 @@ type ValidatorInstance struct { cc clientcontroller.ClientController poller *ChainPoller + // passphrase is used to unlock private keys + passphrase string + laggingTargetChan chan *types.BlockInfo criticalErrChan chan<- *CriticalError @@ -57,6 +60,7 @@ func NewValidatorInstance( s *val.ValidatorStore, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, + passphrase string, errChan chan<- *CriticalError, logger *logrus.Logger, ) (*ValidatorInstance, error) { @@ -83,6 +87,7 @@ func NewValidatorInstance( inSync: atomic.NewBool(false), isLagging: atomic.NewBool(false), criticalErrChan: errChan, + passphrase: passphrase, em: em, cc: cc, }, nil @@ -757,7 +762,7 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxR } // sign the message hash using the validator's BTC private key - schnorrSig, err := v.em.SignSchnorrSig(v.btcPk.MustMarshal(), hash) + schnorrSig, err := v.em.SignSchnorrSig(v.btcPk.MustMarshal(), hash, v.passphrase) if err != nil { return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) } @@ -785,6 +790,7 @@ func (v *ValidatorInstance) createPubRandList(startHeight uint64) ([]bbntypes.Sc v.GetChainID(), startHeight, uint32(v.cfg.NumPubRand), + v.passphrase, ) if err != nil { return nil, err @@ -854,7 +860,7 @@ func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEO BlockLastCommitHash: b.Hash, } msgToSign := msg.MsgToSign() - sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height) + sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height, v.passphrase) if err != nil { return nil, fmt.Errorf("failed to sign EOTS: %w", err) } diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go index 39c448a8..44279223 100644 --- a/service/validator_instance_test.go +++ b/service/validator_instance_test.go @@ -115,10 +115,10 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli require.NoError(t, err) // create registered validator - validator := testutil.GenStoredValidator(r, t, app) + validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) err = app.GetValidatorStore().SetValidatorStatus(validator, proto.ValidatorStatus_REGISTERED) require.NoError(t, err) - err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK()) + err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK(), passphrase) require.NoError(t, err) config := app.GetConfig() diff --git a/service/validator_manager.go b/service/validator_manager.go index e1e4d844..8bacc030 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -209,7 +209,7 @@ func (vm *ValidatorManager) Start() error { go vm.monitorStatusUpdate() for _, v := range storedValidators { - if err := vm.addValidatorInstance(v.MustGetBIP340BTCPK()); err != nil { + if err := vm.addValidatorInstance(v.MustGetBIP340BTCPK(), ""); err != nil { return err } } @@ -287,6 +287,7 @@ func (vm *ValidatorManager) removeValidatorInstance(valPk *bbntypes.BIP340PubKey // addValidatorInstance creates a validator instance, starts it and adds it into the validator manager func (vm *ValidatorManager) addValidatorInstance( pk *bbntypes.BIP340PubKey, + passphrase string, ) error { vm.mu.Lock() defer vm.mu.Unlock() @@ -296,7 +297,7 @@ func (vm *ValidatorManager) addValidatorInstance( return fmt.Errorf("validator instance already exists") } - valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.cc, vm.em, vm.criticalErrChan, vm.logger) + valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.cc, vm.em, passphrase, vm.criticalErrChan, vm.logger) if err != nil { return fmt.Errorf("failed to create validator %s instance: %w", pkHex, err) } diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index 50984056..ffdb99a6 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -3,6 +3,7 @@ package service_test import ( "math/rand" "os" + "strings" "testing" "time" @@ -92,9 +93,13 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c cfg.BabylonConfig.KeyDirectory = t.TempDir() logger := logrus.New() - kr, err := service.CreateKeyring(cfg.BabylonConfig.KeyDirectory, + input := strings.NewReader("") + kr, err := service.CreateKeyring( + cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, - cfg.BabylonConfig.KeyringBackend) + cfg.BabylonConfig.KeyringBackend, + input, + ) require.NoError(t, err) valStore, err := val.NewValidatorStore(cfg.DatabaseConfig) @@ -111,17 +116,17 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c // create registered validator keyName := datagen.GenRandomHexStr(r, 10) chainID := datagen.GenRandomHexStr(r, 10) - kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName) + kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName, input) require.NoError(t, err) - btcPkBytes, err := em.CreateKey(keyName, "") + btcPkBytes, err := em.CreateKey(keyName, passphrase, hdPath) require.NoError(t, err) btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - bbnPk, err := kc.CreateChainKey() + bbnPk, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) - valRecord, err := em.KeyRecord(btcPk.MustMarshal(), "") + valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) - pop, err := kc.CreatePop(valRecord.PrivKey) + pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) require.NoError(t, err) storedValidator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) diff --git a/testutil/datagen.go b/testutil/datagen.go index d5f160bd..98408059 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -12,6 +12,7 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/codec" @@ -83,12 +84,12 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { } // GenStoredValidator generates a random validator from the keyring and store it in DB -func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp) *proto.StoreValidator { +func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp, passphrase, hdPath string) *proto.StoreValidator { // generate keyring keyName := GenRandomHexStr(r, 4) chainID := GenRandomHexStr(r, 4) - res, err := app.CreateValidator(keyName, chainID, "", EmptyDescription(), ZeroCommissionRate()) + res, err := app.CreateValidator(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) storedVal, err := app.GetValidatorStore().GetStoreValidator(res.ValPk.MustMarshal()) @@ -116,7 +117,7 @@ func GenEOTSConfig(r *rand.Rand, t *testing.T) *config.Config { require.NoError(t, err) eotsCfg := &config.Config{ KeyDirectory: dir, - KeyringBackend: "test", + KeyringBackend: keyring.BackendTest, DatabaseConfig: dbCfg, } return eotsCfg diff --git a/val/keyringcontroller.go b/val/keyringcontroller.go index 5be803ef..7c8a2c34 100644 --- a/val/keyringcontroller.go +++ b/val/keyringcontroller.go @@ -2,6 +2,7 @@ package val import ( "fmt" + "strings" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" @@ -19,6 +20,8 @@ const ( type ChainKeyringController struct { kr keyring.Keyring valName string + // input is to send passphrase to kr + input *strings.Reader } func NewChainKeyringController(ctx client.Context, name, keyringBackend string) (*ChainKeyringController, error) { @@ -30,11 +33,12 @@ func NewChainKeyringController(ctx client.Context, name, keyringBackend string) return nil, fmt.Errorf("the keyring backend should not be empty") } + inputReader := strings.NewReader("") kr, err := keyring.New( ctx.ChainID, keyringBackend, ctx.KeyringDir, - ctx.Input, + inputReader, ctx.Codec, ctx.KeyringOptions...) if err != nil { @@ -44,10 +48,11 @@ func NewChainKeyringController(ctx client.Context, name, keyringBackend string) return &ChainKeyringController{ valName: name, kr: kr, + input: inputReader, }, nil } -func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string) (*ChainKeyringController, error) { +func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string, input *strings.Reader) (*ChainKeyringController, error) { if name == "" { return nil, fmt.Errorf("the key name should not be empty") } @@ -55,6 +60,7 @@ func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string) (*Cha return &ChainKeyringController{ kr: kr, valName: name, + input: input, }, nil } @@ -62,7 +68,7 @@ func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { return kc.kr } -func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { +func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*secp256k1.PubKey, error) { keyringAlgos, _ := kc.kr.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { @@ -83,8 +89,9 @@ func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { // TODO use a better way to remind the user to keep it fmt.Printf("Generated mnemonic for the validator %s is:\n%s\n", kc.valName, mnemonic) - // TODO for now we leave bip39Passphrase and hdPath empty - record, err := kc.kr.NewAccount(kc.valName, mnemonic, "", "", algo) + // we need to repeat the passphrase to mock the reentry + kc.input.Reset(passphrase + "\n" + passphrase) + record, err := kc.kr.NewAccount(kc.valName, mnemonic, passphrase, hdPath, algo) if err != nil { return nil, err } @@ -105,8 +112,8 @@ func (kc *ChainKeyringController) CreateChainKey() (*secp256k1.PubKey, error) { // CreatePop creates proof-of-possession of Babylon and BTC public keys // the input is the bytes of BTC public key used to sign // this requires both keys created beforehand -func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey) (*bstypes.ProofOfPossession, error) { - bbnPrivKey, err := kc.GetChainPrivKey() +func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey, passphrase string) (*bstypes.ProofOfPossession, error) { + bbnPrivKey, err := kc.GetChainPrivKey(passphrase) if err != nil { return nil, err } @@ -114,7 +121,8 @@ func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey) (*bsty return bstypes.NewPoP(bbnPrivKey, btcPrivKey) } -func (kc *ChainKeyringController) GetChainPrivKey() (*secp256k1.PrivKey, error) { +func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*secp256k1.PrivKey, error) { + kc.input.Reset(passphrase) k, err := kc.kr.Key(kc.valName) if err != nil { return nil, fmt.Errorf("failed to get private key: %w", err) diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index c52e5fe7..9f473c12 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -7,6 +7,7 @@ import ( "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -15,6 +16,11 @@ import ( "github.com/babylonchain/btc-validator/val" ) +var ( + passphrase = "testpass" + hdPath = "" +) + // FuzzCreatePoP tests the creation of PoP func FuzzCreatePoP(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) @@ -25,7 +31,7 @@ func FuzzCreatePoP(f *testing.F) { sdkCtx := testutil.GenSdkContext(r, t) chainID := testutil.GenRandomHexStr(r, 4) - kc, err := val.NewChainKeyringController(sdkCtx, keyName, "test") + kc, err := val.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) require.NoError(t, err) cfg := testutil.GenEOTSConfig(r, t) @@ -38,17 +44,17 @@ func FuzzCreatePoP(f *testing.F) { err = os.RemoveAll(cfg.DatabaseConfig.Path) require.NoError(t, err) }() - require.NoError(t, err) - btcPkBytes, err := em.CreateKey(keyName, "") + + btcPkBytes, err := em.CreateKey(keyName, passphrase, hdPath) require.NoError(t, err) btcPk, err := types.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - bbnPk, err := kc.CreateChainKey() + bbnPk, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) - valRecord, err := em.KeyRecord(btcPk.MustMarshal(), "") + valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) - pop, err := kc.CreatePop(valRecord.PrivKey) + pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) require.NoError(t, err) validator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) diff --git a/valcfg/babylon.go b/valcfg/babylon.go index 12d40483..2fb59ded 100644 --- a/valcfg/babylon.go +++ b/valcfg/babylon.go @@ -3,6 +3,7 @@ package valcfg import ( "time" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" ) @@ -24,14 +25,14 @@ type BBNConfig struct { } func DefaultBBNConfig() BBNConfig { - //fill up the config from dc config + // fill up the config from dc config return BBNConfig{ Key: "node0", ChainID: "chain-test", RPCAddr: "http://localhost:26657", GRPCAddr: "https://localhost:9090", AccountPrefix: "bbn", - KeyringBackend: "test", + KeyringBackend: keyring.BackendTest, GasAdjustment: 1.2, GasPrices: "0.01ubbn", KeyDirectory: defaultDataDir, From cc2650b251315d79afffe7607fabfc16a774ebab Mon Sep 17 00:00:00 2001 From: Fangyu Gai Date: Mon, 20 Nov 2023 19:43:39 +0800 Subject: [PATCH 16/66] fix e2e --- cmd/valcli/daemoncmd.go | 5 - cmd/valcli/main.go | 1 - covenant/cmd/covcli/admin.go | 57 +++ covenant/cmd/covcli/main.go | 25 ++ .../covenant.go => covenant/cmd/covcli/new.go | 51 ++- covenant/cmd/covd/main.go | 24 ++ covenant/cmd/covd/start.go | 76 ++++ covenant/config/config.go | 197 +++++++++ covenant/covenant.go | 383 ++++++++++++++++++ covenant/service/server.go | 59 +++ eotsmanager/cmd/eotscli/main.go | 2 +- itest/babylon_node_handler.go | 62 +-- itest/e2e_test.go | 41 +- itest/test_manager.go | 129 +++--- service/app.go | 252 +----------- service/app_test.go | 17 +- service/event_loop.go | 84 ---- valcfg/config.go | 6 - valcfg/covenant.go | 26 -- 19 files changed, 973 insertions(+), 524 deletions(-) create mode 100644 covenant/cmd/covcli/admin.go create mode 100644 covenant/cmd/covcli/main.go rename cmd/valcli/covenant.go => covenant/cmd/covcli/new.go (68%) create mode 100644 covenant/cmd/covd/main.go create mode 100644 covenant/cmd/covd/start.go create mode 100644 covenant/config/config.go create mode 100644 covenant/covenant.go create mode 100644 covenant/service/server.go delete mode 100644 valcfg/covenant.go diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index 97e831e4..2dd3ab8b 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -8,7 +8,6 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" "github.com/babylonchain/babylon/x/checkpointing/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" @@ -42,10 +41,6 @@ const ( passphraseFlag = "passphrase" hdPathFlag = "hd-path" chainIdFlag = "chain-id" - keyringDirFlag = "keyring-dir" - keyringBackendFlag = "keyring-backend" - defaultChainID = "chain-test" - defaultKeyringBackend = keyring.BackendTest defaultPassphrase = "" defaultHdPath = "" diff --git a/cmd/valcli/main.go b/cmd/valcli/main.go index 08627427..0e60380b 100644 --- a/cmd/valcli/main.go +++ b/cmd/valcli/main.go @@ -55,7 +55,6 @@ func main() { app.Commands = append(app.Commands, daemonCommands...) app.Commands = append(app.Commands, adminCommands...) - app.Commands = append(app.Commands, covenantCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/covenant/cmd/covcli/admin.go b/covenant/cmd/covcli/admin.go new file mode 100644 index 00000000..a92520a0 --- /dev/null +++ b/covenant/cmd/covcli/admin.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + covcfg "github.com/babylonchain/btc-validator/covenant/config" +) + +const configFileFlag = "config" + +var adminCommands = []cli.Command{ + { + Name: "admin", + ShortName: "ad", + Usage: "Different utility and admin commands.", + Category: "Admin", + Subcommands: []cli.Command{ + dumpCfgCommand, + }, + }, +} + +var dumpCfgCommand = cli.Command{ + Name: "dump-config", + ShortName: "dc", + Usage: "Dump default configuration file.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: configFileFlag, + Usage: "Path to where the default config file will be dumped", + Value: covcfg.DefaultConfigFile, + }, + }, + Action: dumpCfg, +} + +func dumpCfg(c *cli.Context) error { + configPath := c.String(configFileFlag) + + if covcfg.FileExists(configPath) { + return fmt.Errorf("config already exists under provided path: %s", configPath) + } + + defaultConfig := covcfg.DefaultConfig() + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) + + if err != nil { + return err + } + + return nil +} diff --git a/covenant/cmd/covcli/main.go b/covenant/cmd/covcli/main.go new file mode 100644 index 00000000..11aa55e4 --- /dev/null +++ b/covenant/cmd/covcli/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[covenant-emulator cli] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "covcli" + app.Usage = "Control plane for the Covenant Emulator Daemon (covd)." + app.Commands = append(app.Commands, adminCommands...) + app.Commands = append(app.Commands, createCovenant) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/cmd/valcli/covenant.go b/covenant/cmd/covcli/new.go similarity index 68% rename from cmd/valcli/covenant.go rename to covenant/cmd/covcli/new.go index 2ecdbf85..190e4128 100644 --- a/cmd/valcli/covenant.go +++ b/covenant/cmd/covcli/new.go @@ -1,34 +1,38 @@ package main import ( + "encoding/json" "fmt" "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/urfave/cli" + covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/val" ) +const ( + keyNameFlag = "key-name" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + keyringDirFlag = "keyring-dir" + keyringBackendFlag = "keyring-backend" + defaultChainID = "chain-test" + defaultKeyringBackend = keyring.BackendTest + defaultPassphrase = "" + defaultHdPath = "" +) + type covenantKey struct { Name string `json:"name"` PublicKey string `json:"public-key"` } -var covenantCommands = []cli.Command{ - { - Name: "covenant", - ShortName: "c", - Usage: "Control Babylon Covenant.", - Category: "Covenant", - Subcommands: []cli.Command{ - createCovenant, - }, - }, -} - var createCovenant = cli.Command{ Name: "create-covenant", ShortName: "cc", @@ -56,12 +60,13 @@ var createCovenant = cli.Command{ }, cli.StringFlag{ Name: keyringBackendFlag, - Usage: "Select keyring's backend (os|file|test)", + Usage: "Select keyring's backend", Value: defaultKeyringBackend, }, cli.StringFlag{ Name: keyringDirFlag, Usage: "The directory where the keyring is stored", + Value: covcfg.DefaultCovenantDir, }, }, Action: createCovenantKey, @@ -96,10 +101,22 @@ func createCovenantKey(ctx *cli.Context) error { } bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) - printRespJSON(&covenantKey{ - Name: ctx.String(keyNameFlag), - PublicKey: bip340Key.MarshalHex(), - }) + printRespJSON( + &covenantKey{ + Name: ctx.String(keyNameFlag), + PublicKey: bip340Key.MarshalHex(), + }, + ) return err } + +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/covenant/cmd/covd/main.go b/covenant/cmd/covd/main.go new file mode 100644 index 00000000..9f4cd2a4 --- /dev/null +++ b/covenant/cmd/covd/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[covenant-emulator] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "covd" + app.Usage = "Covenant Emulator Daemon (covd)." + app.Commands = append(app.Commands, startCovenant) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go new file mode 100644 index 00000000..cdf1ccff --- /dev/null +++ b/covenant/cmd/covd/start.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "os" + + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + + "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + covsrv "github.com/babylonchain/btc-validator/covenant/service" +) + +const ( + passphraseFlag = "passphrase" + configFileFlag = "config" + + defaultPassphrase = "" +) + +var startCovenant = cli.Command{ + Name: "start", + Usage: "covd start", + Description: "Start the Covenant Emulator Daemon. Note that the Covenant should be created beforehand", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: configFileFlag, + Usage: "The path to the covenant config file", + Value: covcfg.DefaultConfigFile, + }, + }, + Action: startCovenantFn, +} + +func startCovenantFn(ctx *cli.Context) error { + configFilePath := ctx.String(configFileFlag) + cfg, cfgLogger, err := covcfg.LoadConfig(configFilePath) + if err != nil { + return fmt.Errorf("failed to load config at %s: %w", configFilePath, err) + } + + bbnClient, err := clientcontroller.NewBabylonController(cfg.CovenantDir, cfg.BabylonConfig, cfgLogger) + if err != nil { + return fmt.Errorf("failed to create rpc client for the consumer chain: %w", err) + } + + ce, err := covenant.NewCovenantEmulator(cfg, bbnClient, ctx.String(passphraseFlag), cfgLogger) + if err != nil { + return fmt.Errorf("failed to start the covenant emulator: %w", err) + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + srv := covsrv.NewCovenantServer(cfgLogger, ce, shutdownInterceptor) + if err != nil { + return fmt.Errorf("failed to create covenant server: %w", err) + } + + if err := srv.RunUntilShutdown(); err != nil { + return err + } + + return ce.Start() +} diff --git a/covenant/config/config.go b/covenant/config/config.go new file mode 100644 index 00000000..d92622b5 --- /dev/null +++ b/covenant/config/config.go @@ -0,0 +1,197 @@ +package config + +import ( + "fmt" + "io" + "os" + "path/filepath" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/jessevdk/go-flags" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/valcfg" +) + +const ( + defaultLogLevel = "debug" + defaultLogFilename = "covd.log" + defaultConfigFileName = "covd.conf" + defaultCovenantKeyName = "covenant-key" + defaultQueryInterval = 15 * time.Second + defaultDelegationLimit = uint64(100) + defaultBitcoinNetwork = "simnet" + emptySlashingAddress = "" +) + +var ( + // C:\Users\\AppData\Local\ on Windows + // ~/.vald on Linux + // ~/Library/Application Support/Covd on MacOS + DefaultCovenantDir = btcutil.AppDataDir("covd", false) + + DefaultConfigFile = filepath.Join(DefaultCovenantDir, defaultConfigFileName) +) + +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"` + CovenantDir string `long:"covenantdir" description:"The base directory of the Covenant emulator"` + DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` + QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` + DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` + // slashing address can be empty as it will be set from Babylon params + SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` + BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` + + ActiveNetParams chaincfg.Params + + BabylonConfig *valcfg.BBNConfig `group:"babylon" namespace:"babylon"` +} + +// LoadConfig initializes and parses the config using a config file and command +// line options. +// +// The configuration proceeds as follows: +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options +func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { + // Pre-parse the command line options to pick up an alternative config + // file. + preCfg := DefaultConfig() + if _, err := flags.Parse(&preCfg); err != nil { + return nil, nil, err + } + + if !FileExists(filePath) { + return nil, nil, fmt.Errorf("specified config file does "+ + "not exist in %s", filePath) + } + + // Next, load any additional configuration options from the file. + var configFileError error + cfg := preCfg + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).ParseFile(filePath) + if err != nil { + // If it's a parsing related error, then we'll return + // immediately, otherwise we can proceed as possibly the config + // file doesn't exist which is OK. + if _, ok := err.(*flags.IniError); ok { + return nil, nil, err + } + + configFileError = err + } + + cfgLogger := logrus.New() + cfgLogger.Out = os.Stdout + // Make sure everything we just loaded makes sense. + if err := cfg.Validate(); err != nil { + return nil, nil, err + } + + logRuslLevel, err := logrus.ParseLevel(cfg.LogLevel) + if err != nil { + return nil, nil, err + } + + // At this point we know config is valid, create logger which also log to file + logFilePath := filepath.Join(cfg.CovenantDir, defaultLogFilename) + f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, nil, err + } + mw := io.MultiWriter(os.Stdout, f) + + cfgLogger.SetOutput(mw) + cfgLogger.SetLevel(logRuslLevel) + + // Warn about missing config file only after all other configuration is + // done. This prevents the warning on help messages and invalid + // options. Note this should go directly before the return. + if configFileError != nil { + cfgLogger.Warnf("%v", configFileError) + if cfg.DumpCfg { + cfgLogger.Infof("Writing configuration file to %s", filePath) + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) + if err != nil { + cfgLogger.Warnf("Error writing configuration file: %v", err) + return nil, nil, err + } + } + } + + return &cfg, cfgLogger, nil +} + +// Validate check the given configuration to be sane. This makes sure no +// illegal values or combination of values are set. All file system paths are +// normalized. The cleaned up config is returned on success. +func (cfg *Config) Validate() error { + err := os.MkdirAll(cfg.CovenantDir, 0700) + if err != nil { + // Show a nicer error message if it's because a symlink + // is linked to a directory that does not exist + // (probably because it's not mounted). + if e, ok := err.(*os.PathError); ok && os.IsExist(err) { + link, lerr := os.Readlink(e.Path) + if lerr == nil { + str := "is symlink %s -> %s mounted?" + err = fmt.Errorf(str, e.Path, link) + } + } + + return fmt.Errorf("failed to create covd directory '%s': %w", cfg.CovenantDir, err) + } + + switch cfg.BitcoinNetwork { + case "testnet": + cfg.ActiveNetParams = chaincfg.TestNet3Params + case "regtest": + cfg.ActiveNetParams = chaincfg.RegressionNetParams + case "simnet": + cfg.ActiveNetParams = chaincfg.SimNetParams + case "signet": + cfg.ActiveNetParams = chaincfg.SigNetParams + default: + return fmt.Errorf("unsupported Bitcoin network: %s", cfg.BitcoinNetwork) + } + + _, err = logrus.ParseLevel(cfg.LogLevel) + if err != nil { + return err + } + + return nil +} + +func FileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + +func DefaultConfig() Config { + bbnCfg := valcfg.DefaultBBNConfig() + bbnCfg.Key = defaultCovenantKeyName + bbnCfg.KeyDirectory = DefaultCovenantDir + return Config{ + LogLevel: defaultLogLevel, + CovenantDir: DefaultCovenantDir, + DumpCfg: false, + QueryInterval: defaultQueryInterval, + DelegationLimit: defaultDelegationLimit, + SlashingAddress: emptySlashingAddress, + BitcoinNetwork: defaultBitcoinNetwork, + ActiveNetParams: chaincfg.Params{}, + BabylonConfig: &bbnCfg, + } +} diff --git a/covenant/covenant.go b/covenant/covenant.go new file mode 100644 index 00000000..67a03372 --- /dev/null +++ b/covenant/covenant.go @@ -0,0 +1,383 @@ +package covenant + +import ( + "fmt" + "strings" + "sync" + "time" + + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/clientcontroller" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/btc-validator/service" + "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/val" +) + +type CovenantEmulator struct { + startOnce sync.Once + stopOnce sync.Once + + wg sync.WaitGroup + quit chan struct{} + + cc clientcontroller.ClientController + kc *val.ChainKeyringController + + config *covcfg.Config + logger *logrus.Logger + + // input is used to pass passphrase to the keyring + input *strings.Reader + passphrase string +} + +func NewCovenantEmulator( + config *covcfg.Config, + cc clientcontroller.ClientController, + passphrase string, + logger *logrus.Logger, +) (*CovenantEmulator, error) { + input := strings.NewReader("") + kr, err := service.CreateKeyring( + config.BabylonConfig.KeyDirectory, + config.BabylonConfig.ChainID, + config.BabylonConfig.KeyringBackend, + input, + ) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.BabylonConfig.Key, input) + if err != nil { + return nil, err + } + + if _, err := kc.GetChainPrivKey(passphrase); err != nil { + return nil, fmt.Errorf("covenant key %s is not found: %w", config.BabylonConfig.Key, err) + } + + return &CovenantEmulator{ + cc: cc, + kc: kc, + config: config, + logger: logger, + input: input, + passphrase: passphrase, + quit: make(chan struct{}), + }, nil +} + +// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO the logic will be largely replaced when new staking utilities are introduced +func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*service.AddCovenantSigResponse, error) { + if btcDel.CovenantSig != nil { + return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") + } + + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) + if err != nil { + return nil, err + } + err = slashingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) + if err != nil { + return nil, fmt.Errorf("invalid delegation: %w", err) + } + + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) + if err != nil { + return nil, err + } + stakingMsgTx, err := stakingTx.ToMsgTx() + if err != nil { + return nil, err + } + + // get Covenant private key from the keyring + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + + covenantSig, err := slashingTx.Sign( + stakingMsgTx, + stakingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + if err != nil { + return nil, err + } + + stakingTxHash := stakingMsgTx.TxHash().String() + + covenantSchnorrSig, err := covenantSig.ToBTCSig() + if err != nil { + return nil, err + } + res, err := ce.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) + + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "validator_pk": valPkHex, + "delegator_pk": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, err + } + + return &service.AddCovenantSigResponse{TxHash: res.TxHash}, nil +} + +// AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO the logic will be largely replaced when new staking utilities are introduced +func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*service.AddCovenantSigResponse, error) { + if del == nil { + return nil, fmt.Errorf("btc delegation is nil") + } + + if del.BtcUndelegation == nil { + return nil, fmt.Errorf("delegation does not have an unbonding transaction") + } + + if del.BtcUndelegation.ValidatorUnbondingSig == nil { + return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") + } + + // In normal operation it is not possible to have one of this signatures and not have the other + // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg + // which should update both fields at atomically in case of successfull transaction. + if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { + return nil, fmt.Errorf("delegation already has required covenant signatures") + } + + // get Covenant private key from the keyring + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + + // 1. Sign unbonding transaction + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + if err != nil { + return nil, err + } + stakingMsgTx, err := stakingTx.ToMsgTx() + + if err != nil { + return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) + } + + unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) + if err != nil { + return nil, err + } + covenantUnbondingSig, err := unbondingTx.Sign( + stakingMsgTx, + stakingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + + if err != nil { + return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) + } + + // 2. Sign slash unbonding transaction + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + if err != nil { + return nil, err + } + err = slashUnbondingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) + if err != nil { + return nil, err + } + + unbondingMsgTx, err := unbondingTx.ToMsgTx() + + if err != nil { + return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) + } + + covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( + unbondingMsgTx, + unbondingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + if err != nil { + return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) + } + + stakingTxHash := stakingMsgTx.TxHash().String() + + covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } + covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } + res, err := ce.cc.SubmitCovenantUnbondingSigs( + del.ValBtcPk, + del.BtcPk, + stakingTxHash, + covenantUnbondingSchnorrSig, + covenantSlashingUnbondingShcnorrSig, + ) + + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() + + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, err + } + + if res == nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, fmt.Errorf("failed to submit Covenant signature due to known error") + } + + return &service.AddCovenantSigResponse{ + TxHash: res.TxHash, + }, nil +} + +func (ce *CovenantEmulator) getPrivKey() (*btcec.PrivateKey, error) { + sdkPrivKey, err := ce.kc.GetChainPrivKey(ce.passphrase) + if err != nil { + return nil, err + } + + privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) + + return privKey, nil +} + +// covenantSigSubmissionLoop is the reactor to submit Covenant signature for BTC delegations +func (ce *CovenantEmulator) covenantSigSubmissionLoop() { + defer ce.wg.Done() + + interval := ce.config.QueryInterval + limit := ce.config.DelegationLimit + covenantSigTicker := time.NewTicker(interval) + + for { + select { + case <-covenantSigTicker.C: + // 0. Update slashing address in case it is changed upon governance proposal + params, err := ce.cc.QueryStakingParams() + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get slashing address") + continue + } + slashingAddress := params.SlashingAddress + _, err = btcutil.DecodeAddress(slashingAddress, &ce.config.ActiveNetParams) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("invalid slashing address") + continue + } + ce.config.SlashingAddress = slashingAddress + + // 1. Get all pending delegations first, these are more important than the unbonding ones + dels, err := ce.cc.QueryPendingDelegations(limit) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get pending delegations") + continue + } + if len(dels) == 0 { + ce.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") + } + + for _, d := range dels { + _, err := ce.AddCovenantSignature(d) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "del_btc_pk": d.BtcPk, + }).Error("failed to submit Covenant sig to the Bitcoin delegation") + } + } + + // 2. Get all unbonding delegations + unbondingDels, err := ce.cc.QueryUnbondingDelegations(limit) + + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get pending delegations") + continue + } + + if len(unbondingDels) == 0 { + ce.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") + } + + for _, d := range unbondingDels { + _, err := ce.AddCovenantUnbondingSignatures(d) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "del_btc_pk": d.BtcPk, + }).Error("failed to submit Covenant sig to the Bitcoin delegation") + } + } + + case <-ce.quit: + ce.logger.Debug("exiting covenant signature submission loop") + return + } + } + +} + +func (ce *CovenantEmulator) Start() error { + var startErr error + ce.startOnce.Do(func() { + ce.logger.Infof("Starting Covenant Emulator") + + ce.wg.Add(1) + go ce.covenantSigSubmissionLoop() + }) + + return startErr +} + +func (ce *CovenantEmulator) Stop() error { + var stopErr error + ce.stopOnce.Do(func() { + ce.logger.Infof("Stopping Covenant Emulator") + + // Always stop the submission loop first to not generate additional events and actions + ce.logger.Debug("Stopping submission loop") + close(ce.quit) + ce.wg.Wait() + + ce.logger.Debug("Covenant Emulator successfully stopped") + }) + return stopErr +} diff --git a/covenant/service/server.go b/covenant/service/server.go new file mode 100644 index 00000000..66a2edc3 --- /dev/null +++ b/covenant/service/server.go @@ -0,0 +1,59 @@ +package service + +import ( + "fmt" + "sync/atomic" + + "github.com/lightningnetwork/lnd/signal" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/covenant" +) + +// CovenantServer is the main daemon construct for the covenant emulator. +type CovenantServer struct { + started int32 + + ce *covenant.CovenantEmulator + + logger *logrus.Logger + + interceptor signal.Interceptor + + quit chan struct{} +} + +// NewCovenantServer creates a new server with the given config. +func NewCovenantServer(l *logrus.Logger, ce *covenant.CovenantEmulator, sig signal.Interceptor) *CovenantServer { + return &CovenantServer{ + logger: l, + ce: ce, + interceptor: sig, + quit: make(chan struct{}, 1), + } +} + +// RunUntilShutdown runs the main EOTS manager server loop until a signal is +// received to shut down the process. +func (s *CovenantServer) RunUntilShutdown() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + + defer func() { + s.ce.Stop() + s.logger.Info("Shutdown covenant emulator server complete") + }() + + if err := s.ce.Start(); err != nil { + return fmt.Errorf("failed to start covenant emulator: %w", err) + } + + s.logger.Infof("Covenant Emulator Daemon is fully active!") + + // Wait for shutdown signal from either a graceful server stop or from + // the interrupt handler. + <-s.interceptor.ShutdownChannel() + + return nil +} diff --git a/eotsmanager/cmd/eotscli/main.go b/eotsmanager/cmd/eotscli/main.go index fe31581c..e26988ce 100644 --- a/eotsmanager/cmd/eotscli/main.go +++ b/eotsmanager/cmd/eotscli/main.go @@ -8,7 +8,7 @@ import ( ) func fatal(err error) { - fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + fmt.Fprintf(os.Stderr, "[eots-manager] %v\n", err) os.Exit(1) } diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 1aa3e14d..07c88b98 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -11,30 +11,25 @@ import ( "testing" "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" ) type babylonNode struct { - cmd *exec.Cmd - pidFile string - dataDir string - covenantKeyName string - chainID string - slashingAddr string + cmd *exec.Cmd + pidFile string + dataDir string + chainID string + slashingAddr string + covenantPk *types.BIP340PubKey } -func newBabylonNode(dataDir string, cmd *exec.Cmd, covenantKeyName, chainID string, slashingAddr string) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd, chainID string, slashingAddr string, covenantPk *types.BIP340PubKey) *babylonNode { return &babylonNode{ - dataDir: dataDir, - cmd: cmd, - covenantKeyName: covenantKeyName, - chainID: chainID, - slashingAddr: slashingAddr, + dataDir: dataDir, + cmd: cmd, + chainID: chainID, + slashingAddr: slashingAddr, + covenantPk: covenantPk, } } @@ -112,7 +107,7 @@ type BabylonNodeHandler struct { babylonNode *babylonNode } -func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { +func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *BabylonNodeHandler { testDir, err := baseDir("zBabylonTest") require.NoError(t, err) defer func() { @@ -124,25 +119,6 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { nodeDataDir := filepath.Join(testDir, "node0", "babylond") - // the Covenant key needs to be created before babylond is started - sdkCtx, err := service.CreateClientCtx( - nodeDataDir, - chainID, - ) - require.NoError(t, err) - covenantKeyName := "covenant-key" - krController, err := val.NewChainKeyringController( - sdkCtx, - covenantKeyName, - keyring.BackendTest, - ) - require.NoError(t, err) - sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) - require.NoError(t, err) - covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) - require.NoError(t, err) - covenantPkBip340 := types.NewBIP340PubKeyFromBTCPK(covenantPk) - slashingAddr := "SZtRT4BySL3o4efdGLh3k7Kny8GAnsBrSW" initTestnetCmd := exec.Command( @@ -155,7 +131,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--covenant-pk=%s", covenantPkBip340.MarshalHex()), + fmt.Sprintf("--covenant-pk=%s", covenantPk.MarshalHex()), ) var stderr bytes.Buffer @@ -180,7 +156,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, covenantKeyName, chainID, slashingAddr), + babylonNode: newBabylonNode(testDir, startCmd, chainID, slashingAddr, covenantPk), } } @@ -206,10 +182,10 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { return dir } -func (w *BabylonNodeHandler) GetCovenantKeyName() string { - return w.babylonNode.covenantKeyName -} - func (w *BabylonNodeHandler) GetSlashingAddress() string { return w.babylonNode.slashingAddr } + +func (w *BabylonNodeHandler) GetCovenantPk() *types.BIP340PubKey { + return w.babylonNode.covenantPk +} diff --git a/itest/e2e_test.go b/itest/e2e_test.go index ca357940..5b461185 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -25,7 +25,7 @@ var ( // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestValidatorLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -38,13 +38,10 @@ func TestValidatorLifeCycle(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -55,7 +52,7 @@ func TestValidatorLifeCycle(t *testing.T) { // TestMultipleValidators tests starting with multiple validators func TestMultipleValidators(t *testing.T) { n := 3 - tm := StartManagerWithValidator(t, n, false) + tm := StartManagerWithValidator(t, n) defer tm.Stop(t) app := tm.Va @@ -83,7 +80,6 @@ func TestMultipleValidators(t *testing.T) { tm.Wg.Add(1) go func(btcDel *types.Delegation) { defer tm.Wg.Done() - _ = tm.AddCovenantSignature(t, btcDel) }(del) } tm.Wg.Wait() @@ -105,7 +101,7 @@ func TestMultipleValidators(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 := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -118,13 +114,10 @@ func TestDoubleSigning(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -151,7 +144,7 @@ func TestDoubleSigning(t *testing.T) { // TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -164,12 +157,9 @@ func TestFastSync(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) + _ = tm.WaitForNPendingDels(t, 1) - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) - - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -197,7 +187,7 @@ func TestFastSync(t *testing.T) { } func TestValidatorUnbondingSigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -210,12 +200,9 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) @@ -223,7 +210,7 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { } func TestCovenantLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1, true) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va valIns := app.ListValidatorInstances()[0] diff --git a/itest/test_manager.go b/itest/test_manager.go index cea4b1fb..6dd761e9 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -19,17 +19,22 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "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" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + dcrecsecp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager/client" eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -50,8 +55,10 @@ type TestManager struct { Wg sync.WaitGroup BabylonHandler *BabylonNodeHandler EOTSServerHandler *EOTSServerHandler + CovenantEmulator *covenant.CovenantEmulator ValConfig *valcfg.Config EOTSConfig *eotsconfig.Config + CovenanConfig *covcfg.Config Va *service.ValidatorApp EOTSClient *client.EOTSManagerGRpcClient BabylonClient *clientcontroller.BabylonController @@ -72,45 +79,55 @@ type TestDelegationData struct { StakingAmount int64 } -func StartManager(t *testing.T, isCovenant bool) *TestManager { - bh := NewBabylonNodeHandler(t) - - err := bh.Start() +func StartManager(t *testing.T) *TestManager { + testDir, err := tempDirWithName("vale2etest") require.NoError(t, err) logger := logrus.New() logger.SetLevel(logrus.DebugLevel) logger.Out = os.Stdout - // setup validator config - testDir, err := tempDirWithName("vale2etest") + // 1. prepare covenant key, which will be used as input of Babylon node + covenantConfig := defaultCovenantConfig(testDir) + err = covenantConfig.Validate() require.NoError(t, err) + covenantPk := createCovenantKey(t, testDir) - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isCovenant) - + // 2. prepare Babylon node + bh := NewBabylonNodeHandler(t, covenantPk) + err = bh.Start() + require.NoError(t, err) + cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir) bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) + // 3. prepare EOTS manager eotsCfg := defaultEOTSConfig(t) - eh := NewEOTSServerHandler(t, eotsCfg) eh.Start() - eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) + // 4. prepare validator valApp, err := service.NewValidatorApp(cfg, bc, eotsCli, logger) require.NoError(t, err) - err = valApp.Start() require.NoError(t, err) + // 5. prepare covenant emulator + ce, err := covenant.NewCovenantEmulator(covenantConfig, bc, passphrase, logger) + require.NoError(t, err) + err = ce.Start() + require.NoError(t, err) + tm := &TestManager{ BabylonHandler: bh, EOTSServerHandler: eh, ValConfig: cfg, EOTSConfig: eotsCfg, Va: valApp, + CovenantEmulator: ce, + CovenanConfig: covenantConfig, EOTSClient: eotsCli, BabylonClient: bc, } @@ -120,6 +137,27 @@ func StartManager(t *testing.T, isCovenant bool) *TestManager { return tm } +func createCovenantKey(t *testing.T, keyringDir string) *bbntypes.BIP340PubKey { + // the Covenant key needs to be created before babylond is started + sdkCtx, err := service.CreateClientCtx( + keyringDir, + chainID, + ) + require.NoError(t, err) + covenantKeyName := "covenant-key" + krController, err := val.NewChainKeyringController( + sdkCtx, + covenantKeyName, + keyring.BackendTest, + ) + require.NoError(t, err) + sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) + require.NoError(t, err) + covenantPk, err := dcrecsecp256k1.ParsePubKey(sdkCovenantPk.Key) + require.NoError(t, err) + return bbntypes.NewBIP340PubKeyFromBTCPK(covenantPk) +} + func (tm *TestManager) WaitForServicesStart(t *testing.T) { // wait for Babylon node starts require.Eventually(t, func() bool { @@ -131,8 +169,8 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int, isCovenant bool) *TestManager { - tm := StartManager(t, isCovenant) +func StartManagerWithValidator(t *testing.T, n int) *TestManager { + tm := StartManager(t) app := tm.Va for i := 0; i < n; i++ { @@ -194,6 +232,8 @@ func (tm *TestManager) Stop(t *testing.T) { tm.EOTSServerHandler.Stop() err = os.RemoveAll(tm.EOTSServerHandler.baseDir) require.NoError(t, err) + err = tm.CovenantEmulator.Stop() + require.NoError(t, err) } func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { @@ -223,7 +263,7 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegat ) require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryPendingDelegations( - tm.ValConfig.CovenantModeConfig.DelegationLimit, + tm.CovenanConfig.DelegationLimit, ) if err != nil { return false @@ -399,38 +439,6 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, require.NoError(t, err) } -func (tm *TestManager) AddCovenantSignature(t *testing.T, del *types.Delegation) *types.TxResponse { - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(del.SlashingTxHex) - require.NoError(t, err) - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) - require.NoError(t, err) - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - - // get Covenant private key from the keyring - covenantPrivKey := tm.GetCovenantPrivKey(t) - - covenantSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &tm.ValConfig.ActiveNetParams, - ) - require.NoError(t, err) - - covenantSchnorrSig, err := covenantSig.ToBTCSig() - require.NoError(t, err) - res, err := tm.BabylonClient.SubmitCovenantSig( - del.ValBtcPk, - del.BtcPk, - stakingMsgTx.TxHash().String(), - covenantSchnorrSig, - ) - require.NoError(t, err) - - return res -} - // delegation must containt undelgation object func (tm *TestManager) AddValidatorUnbondingSignature( t *testing.T, @@ -466,17 +474,6 @@ func (tm *TestManager) AddValidatorUnbondingSignature( require.NoError(t, err) } -func (tm *TestManager) GetCovenantPrivKey(t *testing.T) *btcec.PrivateKey { - kr := tm.Va.GetKeyring() - covenantKeyName := tm.BabylonHandler.GetCovenantKeyName() - k, err := kr.Key(covenantKeyName) - require.NoError(t, err) - localKey := k.GetLocal().PrivKey.GetCachedValue() - require.IsType(t, &secp256k1.PrivKey{}, localKey) - covenantPrivKey, _ := btcec.PrivKeyFromBytes(localKey.(*secp256k1.PrivKey).Key) - return covenantPrivKey -} - func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { record, err := tm.EOTSClient.KeyRecord(valPk, passphrase) require.NoError(t, err) @@ -492,7 +489,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK require.NoError(t, err) require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - covenantPk := tm.GetCovenantPrivKey(t).PubKey() + covenantPk := tm.BabylonHandler.GetCovenantPk().MustToBTCPK() require.NoError(t, err) require.Equal(t, params.CovenantPk.SerializeCompressed()[1:], covenantPk.SerializeCompressed()[1:]) @@ -500,7 +497,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx( - r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, tm.BabylonHandler.GetSlashingAddress()) + r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, slashingAddr) require.NoError(t, err) // get msgTx @@ -621,7 +618,7 @@ func (tm *TestManager) InsertBTCUnbonding( require.NoError(t, err) } -func defaultValidatorConfig(keyringDir, testDir string, isCovenant bool) *valcfg.Config { +func defaultValidatorConfig(keyringDir, testDir string) *valcfg.Config { cfg := valcfg.DefaultConfig() cfg.ValidatorModeConfig.AutoChainScanningMode = false @@ -633,20 +630,26 @@ func defaultValidatorConfig(keyringDir, testDir string, isCovenant bool) *valcfg // Big adjustment to make sure we have enough gas in our transactions cfg.BabylonConfig.GasAdjustment = 20 cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") - cfg.CovenantMode = isCovenant - cfg.CovenantModeConfig.QueryInterval = 7 * time.Second cfg.UnbondingSigSubmissionInterval = 3 * time.Second return &cfg } +func defaultCovenantConfig(testDir string) *covcfg.Config { + cfg := covcfg.DefaultConfig() + cfg.CovenantDir = testDir + cfg.BabylonConfig.KeyDirectory = testDir + + return &cfg +} + func defaultEOTSConfig(t *testing.T) *eotsconfig.Config { cfg := eotsconfig.DefaultConfig() eotsDir, err := baseDir("zEOTSTest") require.NoError(t, err) - configFile := filepath.Join(eotsDir, "eotsd-test.conf") + configFile := filepath.Join(eotsDir, "covd-test.conf") dataDir := filepath.Join(eotsDir, "data") logDir := filepath.Join(eotsDir, "log") diff --git a/service/app.go b/service/app.go index 01fad2c2..03638e0c 100644 --- a/service/app.go +++ b/service/app.go @@ -18,7 +18,6 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/client" "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" "github.com/babylonchain/btc-validator/val" @@ -109,17 +108,6 @@ func NewValidatorApp( return nil, fmt.Errorf("failed to open the store for validators: %w", err) } - if config.CovenantMode { - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.CovenantModeConfig.CovenantKeyName, input) - if err != nil { - return nil, err - } - if _, err := kc.GetChainPrivKey(""); err != nil { - return nil, fmt.Errorf("the program is running in Covenant mode but the Covenant key %s is not found: %w", - config.CovenantModeConfig.CovenantKeyName, err) - } - } - vm, err := NewValidatorManager(valStore, config, cc, em, logger) if err != nil { return nil, fmt.Errorf("failed to create validator manager: %w", err) @@ -231,221 +219,6 @@ func (app *ValidatorApp) StartHandlingValidators() error { return app.validatorManager.Start() } -// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Covenant mode -func (app *ValidatorApp) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { - if btcDel.CovenantSig != nil { - return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") - } - - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) - if err != nil { - return nil, err - } - err = slashingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) - if err != nil { - return nil, fmt.Errorf("invalid delegation: %w", err) - } - - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) - if err != nil { - return nil, err - } - stakingMsgTx, err := stakingTx.ToMsgTx() - if err != nil { - return nil, err - } - - // get Covenant private key from the keyring - covenantPrivKey, err := app.getCovenantPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - covenantSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, err - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantSchnorrSig, err := covenantSig.ToBTCSig() - if err != nil { - return nil, err - } - res, err := app.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) - - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, fmt.Errorf("failed to submit Covenant signature due to known error") - } - - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil -} - -// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Covenant mode -func (app *ValidatorApp) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { - if del == nil { - return nil, fmt.Errorf("btc delegation is nil") - } - - if del.BtcUndelegation == nil { - return nil, fmt.Errorf("delegation does not have an unbonding transaction") - } - - if del.BtcUndelegation.ValidatorUnbondingSig == nil { - return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") - } - - // In normal operation it is not possible to have one of this signatures and not have the other - // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg - // which should update both fields at atomically in case of successfull transaction. - if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { - return nil, fmt.Errorf("delegation already has required covenant signatures") - } - - // get Covenant private key from the keyring - covenantPrivKey, err := app.getCovenantPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - // 1. Sign unbonding transaction - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) - if err != nil { - return nil, err - } - stakingMsgTx, err := stakingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) - } - - unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) - if err != nil { - return nil, err - } - covenantUnbondingSig, err := unbondingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - // 2. Sign slash unbonding transaction - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) - if err != nil { - return nil, err - } - err = slashUnbondingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) - if err != nil { - return nil, err - } - - unbondingMsgTx, err := unbondingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) - } - - covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( - unbondingMsgTx, - unbondingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() - if err != nil { - return nil, err - } - covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() - if err != nil { - return nil, err - } - res, err := app.cc.SubmitCovenantUnbondingSigs( - del.ValBtcPk, - del.BtcPk, - stakingTxHash, - covenantUnbondingSchnorrSig, - covenantSlashingUnbondingShcnorrSig, - ) - - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, fmt.Errorf("failed to submit Covenant signature due to known error") - } - - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil -} - -func (app *ValidatorApp) getCovenantPrivKey() (*btcec.PrivateKey, error) { - kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.CovenantModeConfig.CovenantKeyName, app.input) - if err != nil { - return nil, err - } - - // TODO use empty passphrase for covenant for now, covenant should be run in a separate application - sdkPrivKey, err := kc.GetChainPrivKey("") - if err != nil { - return nil, err - } - - privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) - - return privKey, nil -} - // NOTE: this is not safe in production, so only used for testing purpose func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) { record, err := app.eotsManager.KeyRecord(valPk, "") @@ -467,14 +240,9 @@ func (app *ValidatorApp) Start() error { app.sentWg.Add(1) go app.registrationLoop() - if app.IsCovenant() { - app.wg.Add(1) - go app.covenantSigSubmissionLoop() - } else { - if err := app.StartHandlingValidators(); err != nil { - startErr = err - return - } + if err := app.StartHandlingValidators(); err != nil { + startErr = err + return } }) @@ -491,12 +259,10 @@ func (app *ValidatorApp) Stop() error { close(app.quit) app.wg.Wait() - if !app.IsCovenant() { - app.logger.Debug("Stopping validators") - if err := app.validatorManager.Stop(); err != nil { - stopErr = err - return - } + app.logger.Debug("Stopping validators") + if err := app.validatorManager.Stop(); err != nil { + stopErr = err + return } app.logger.Debug("Sent to Babylon loop stopped") @@ -557,10 +323,6 @@ func (app *ValidatorApp) CreateValidator( } } -func (app *ValidatorApp) IsCovenant() bool { - return app.config.CovenantMode -} - func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) if err != nil { diff --git a/service/app_test.go b/service/app_test.go index f8fa5f4d..23e9ce60 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -14,6 +14,8 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" @@ -131,9 +133,10 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) // create a Covenant key pair in the keyring + covenantConfig := covcfg.DefaultConfig() covenantKc, err := val.NewChainKeyringControllerWithKeyring( app.GetKeyring(), - cfg.CovenantModeConfig.CovenantKeyName, + covenantConfig.BabylonConfig.Key, app.GetInput(), ) require.NoError(t, err) @@ -142,13 +145,17 @@ func FuzzAddCovenantSig(f *testing.F) { covenantPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) require.NoError(t, err) require.NotNil(t, covenantPk) - cfg.CovenantMode = true + ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logger) + require.NoError(t, err) err = app.Start() + err = ce.Start() require.NoError(t, err) defer func() { err = app.Stop() require.NoError(t, err) + err = ce.Stop() + require.NoError(t, err) }() // create a validator object and save it to db @@ -187,9 +194,7 @@ func FuzzAddCovenantSig(f *testing.F) { gomock.Any(), ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - cfg.CovenantModeConfig.SlashingAddress = slashingAddr.String() - res, err := app.AddCovenantSignature(delegation) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) + covenantConfig.SlashingAddress = slashingAddr.String() + // TODO create covenant emulator }) } diff --git a/service/event_loop.go b/service/event_loop.go index c8ad7ca3..17c3b07d 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -2,96 +2,12 @@ package service import ( "encoding/hex" - "time" - "github.com/btcsuite/btcd/btcutil" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" ) -// covenantSigSubmissionLoop is the reactor to submit Covenant signature for pending BTC delegations -func (app *ValidatorApp) covenantSigSubmissionLoop() { - defer app.wg.Done() - - interval := app.config.CovenantModeConfig.QueryInterval - limit := app.config.CovenantModeConfig.DelegationLimit - covenantSigTicker := time.NewTicker(interval) - - for { - select { - case <-covenantSigTicker.C: - // 0. Update slashing address in case it is changed upon governance proposal - params, err := app.cc.QueryStakingParams() - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get slashing address") - continue - } - slashingAddress := params.SlashingAddress - _, err = btcutil.DecodeAddress(slashingAddress, &app.config.ActiveNetParams) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("invalid slashing address") - continue - } - app.config.CovenantModeConfig.SlashingAddress = slashingAddress - - // 1. Get all pending delegations first, this are more important than the unbonding ones - dels, err := app.cc.QueryPendingDelegations(limit) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - if len(dels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") - } - - for _, d := range dels { - _, err := app.AddCovenantSignature(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") - } - } - // 2. Get all unbonding delegations - unbondingDels, err := app.cc.QueryUnbondingDelegations(limit) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - - if len(unbondingDels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") - } - - for _, d := range unbondingDels { - _, err := app.AddCovenantUnbondingSignatures(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") - } - } - - case <-app.quit: - app.logger.Debug("exiting covenantSigSubmissionLoop") - return - } - } - -} - // main event loop for the validator app func (app *ValidatorApp) eventLoop() { defer app.eventWg.Done() diff --git a/valcfg/config.go b/valcfg/config.go index 8ec070a1..3e82cd13 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -83,8 +83,6 @@ type Config struct { ActiveNetParams chaincfg.Params - CovenantMode bool `long:"covenantmode" description:"If the program is running in Covenant mode"` - PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` @@ -95,8 +93,6 @@ type Config struct { ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - CovenantModeConfig *CovenantConfig `group:"covenant" namespace:"covenant"` - GRpcServerConfig *GRpcServerConfig RpcListeners []net.Addr @@ -105,7 +101,6 @@ type Config struct { func DefaultConfig() Config { bbnCfg := DefaultBBNConfig() dbCfg := DefaultDatabaseConfig() - covenantCfg := DefaultCovenantConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() eotsMngrCfg := DefaultEOTSManagerConfig() @@ -119,7 +114,6 @@ func DefaultConfig() Config { DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, ValidatorModeConfig: &valCfg, - CovenantModeConfig: &covenantCfg, PollerConfig: &pollerCfg, EOTSManagerConfig: &eotsMngrCfg, NumPubRand: defaultNumPubRand, diff --git a/valcfg/covenant.go b/valcfg/covenant.go deleted file mode 100644 index 5bce2123..00000000 --- a/valcfg/covenant.go +++ /dev/null @@ -1,26 +0,0 @@ -package valcfg - -import ( - "time" -) - -var ( - defaultCovenantKeyName = "covenant-key" - defaultQueryInterval = 15 * time.Second - defaultDelegationLimit = uint64(100) -) - -type CovenantConfig struct { - CovenantKeyName string `long:"covenantkeyname" description:"The key name of the Covenant if the program is running in Covenant mode"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` - DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` - SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` -} - -func DefaultCovenantConfig() CovenantConfig { - return CovenantConfig{ - CovenantKeyName: defaultCovenantKeyName, - QueryInterval: defaultQueryInterval, - DelegationLimit: defaultDelegationLimit, - } -} From 8ade83f61ccc3ac16dd790c19b6e1588a9adacd9 Mon Sep 17 00:00:00 2001 From: Fangyu Gai Date: Mon, 20 Nov 2023 19:55:08 +0800 Subject: [PATCH 17/66] fix linter --- covenant/service/server.go | 2 +- service/app_test.go | 1 + testutil/datagen.go | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/covenant/service/server.go b/covenant/service/server.go index 66a2edc3..b0ed3b4a 100644 --- a/covenant/service/server.go +++ b/covenant/service/server.go @@ -41,7 +41,7 @@ func (s *CovenantServer) RunUntilShutdown() error { } defer func() { - s.ce.Stop() + _ = s.ce.Stop() s.logger.Info("Shutdown covenant emulator server complete") }() diff --git a/service/app_test.go b/service/app_test.go index 23e9ce60..d9468ec3 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -149,6 +149,7 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) err = app.Start() + require.NoError(t, err) err = ce.Start() require.NoError(t, err) defer func() { diff --git a/testutil/datagen.go b/testutil/datagen.go index 98408059..90485015 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -94,6 +94,7 @@ func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp, p storedVal, err := app.GetValidatorStore().GetStoreValidator(res.ValPk.MustMarshal()) require.NoError(t, err) + return storedVal } From 26e413d661b673da87ebd59f84ca5f285e567a6f Mon Sep 17 00:00:00 2001 From: Fangyu Gai Date: Mon, 20 Nov 2023 20:20:31 +0800 Subject: [PATCH 18/66] fix --- covenant/cmd/covcli/new.go | 40 +++++++++++++--------------------- covenant/covenant.go | 31 +++++++++++++++++++++++++++ itest/test_manager.go | 44 ++++++++++---------------------------- service/app_test.go | 18 ++++++---------- 4 files changed, 64 insertions(+), 69 deletions(-) diff --git a/covenant/cmd/covcli/new.go b/covenant/cmd/covcli/new.go index 190e4128..d0621aa1 100644 --- a/covenant/cmd/covcli/new.go +++ b/covenant/cmd/covcli/new.go @@ -6,13 +6,10 @@ import ( "github.com/babylonchain/babylon/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/decred/dcrd/dcrec/secp256k1/v4" - "github.com/urfave/cli" + "github.com/babylonchain/btc-validator/covenant" covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" ) const ( @@ -73,31 +70,24 @@ var createCovenant = cli.Command{ } func createCovenantKey(ctx *cli.Context) error { - sdkCtx, err := service.CreateClientCtx( - ctx.String(keyringDirFlag), - ctx.String(chainIdFlag), - ) - if err != nil { - return err - } + keyringDir := ctx.String(keyringDirFlag) + chainID := ctx.String(chainIdFlag) + keyName := ctx.String(keyNameFlag) + backend := ctx.String(keyringBackendFlag) + passphrase := ctx.String(passphraseFlag) + hdPath := ctx.String(hdPathFlag) - krController, err := val.NewChainKeyringController( - sdkCtx, - ctx.String(keyNameFlag), - ctx.String(keyringBackendFlag), + covenantPk, err := covenant.CreateCovenantKey( + keyringDir, + chainID, + keyName, + backend, + passphrase, + hdPath, ) - if err != nil { - return err - } - - sdkCovenantPk, err := krController.CreateChainKey(ctx.String(passphraseFlag), ctx.String(hdPathFlag)) - if err != nil { - return fmt.Errorf("failed to create Covenant key: %w", err) - } - covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) if err != nil { - return err + return fmt.Errorf("failed to create covenant key: %w", err) } bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) diff --git a/covenant/covenant.go b/covenant/covenant.go index 67a03372..801a70ad 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -10,6 +10,7 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" @@ -355,6 +356,36 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } +func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*btcec.PublicKey, error) { + sdkCtx, err := service.CreateClientCtx( + keyringDir, chainID, + ) + if err != nil { + return nil, err + } + + krController, err := val.NewChainKeyringController( + sdkCtx, + keyName, + backend, + ) + if err != nil { + return nil, err + } + + sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) + if err != nil { + return nil, err + } + + covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) + if err != nil { + return nil, err + } + + return covenantPk, nil +} + func (ce *CovenantEmulator) Start() error { var startErr error ce.startOnce.Do(func() { diff --git a/itest/test_manager.go b/itest/test_manager.go index 6dd761e9..c1ca393a 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -23,7 +23,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - dcrecsecp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -34,23 +33,22 @@ import ( eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) var ( eventuallyWaitTimeOut = 1 * time.Minute eventuallyPollTime = 500 * time.Millisecond - - valNamePrefix = "test-val-" - monikerPrefix = "moniker-" - chainID = "chain-test" - passphrase = "testpass" - hdPath = "" + btcNetworkParams = &chaincfg.SimNetParams + + valNamePrefix = "test-val-" + monikerPrefix = "moniker-" + covenantKeyName = "covenant-key" + chainID = "chain-test" + passphrase = "testpass" + hdPath = "" ) -var btcNetworkParams = &chaincfg.SimNetParams - type TestManager struct { Wg sync.WaitGroup BabylonHandler *BabylonNodeHandler @@ -91,10 +89,11 @@ func StartManager(t *testing.T) *TestManager { covenantConfig := defaultCovenantConfig(testDir) err = covenantConfig.Validate() require.NoError(t, err) - covenantPk := createCovenantKey(t, testDir) + covenantPk, err := covenant.CreateCovenantKey(testDir, chainID, covenantKeyName, keyring.BackendTest, passphrase, hdPath) + require.NoError(t, err) // 2. prepare Babylon node - bh := NewBabylonNodeHandler(t, covenantPk) + bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covenantPk)) err = bh.Start() require.NoError(t, err) cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir) @@ -137,27 +136,6 @@ func StartManager(t *testing.T) *TestManager { return tm } -func createCovenantKey(t *testing.T, keyringDir string) *bbntypes.BIP340PubKey { - // the Covenant key needs to be created before babylond is started - sdkCtx, err := service.CreateClientCtx( - keyringDir, - chainID, - ) - require.NoError(t, err) - covenantKeyName := "covenant-key" - krController, err := val.NewChainKeyringController( - sdkCtx, - covenantKeyName, - keyring.BackendTest, - ) - require.NoError(t, err) - sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) - require.NoError(t, err) - covenantPk, err := dcrecsecp256k1.ParsePubKey(sdkCovenantPk.Key) - require.NoError(t, err) - return bbntypes.NewBIP340PubKeyFromBTCPK(covenantPk) -} - func (tm *TestManager) WaitForServicesStart(t *testing.T) { // wait for Babylon node starts require.Eventually(t, func() bool { diff --git a/service/app_test.go b/service/app_test.go index d9468ec3..33643027 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -9,7 +9,6 @@ import ( bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/chaincfg" - secp256k12 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -21,7 +20,6 @@ import ( "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -134,17 +132,15 @@ func FuzzAddCovenantSig(f *testing.F) { // create a Covenant key pair in the keyring covenantConfig := covcfg.DefaultConfig() - covenantKc, err := val.NewChainKeyringControllerWithKeyring( - app.GetKeyring(), - covenantConfig.BabylonConfig.Key, - app.GetInput(), + covenantPk, err := covenant.CreateCovenantKey( + cfg.BabylonConfig.KeyDirectory, + cfg.BabylonConfig.ChainID, + cfg.BabylonConfig.Key, + cfg.BabylonConfig.KeyringBackend, + passphrase, + hdPath, ) require.NoError(t, err) - sdkJurPk, err := covenantKc.CreateChainKey(passphrase, hdPath) - require.NoError(t, err) - covenantPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) - require.NoError(t, err) - require.NotNil(t, covenantPk) ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logger) require.NoError(t, err) From 9870ef4f11f744fed385e367dcc71e61fcc81af5 Mon Sep 17 00:00:00 2001 From: Fangyu Gai Date: Mon, 20 Nov 2023 20:34:44 +0800 Subject: [PATCH 19/66] minor --- covenant/Dockerfile | 57 +++++++++++++++++++++++++++++++++++++++++++++ covenant/Makefile | 38 ++++++++++++++++++++++++++++++ service/app_test.go | 8 +++---- 3 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 covenant/Dockerfile create mode 100644 covenant/Makefile diff --git a/covenant/Dockerfile b/covenant/Dockerfile new file mode 100644 index 00000000..dc9cd19a --- /dev/null +++ b/covenant/Dockerfile @@ -0,0 +1,57 @@ +FROM golang:1.20.5-alpine as builder + +# Version to build. Default is the Git HEAD. +ARG VERSION="HEAD" + +# Use muslc for static libs +ARG BUILD_TAGS="muslc" + + +RUN apk add --no-cache --update openssh git make build-base linux-headers libc-dev \ + pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \ + libzmq-static libsodium-static gcc + + +RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts +RUN git config --global url."git@github.com:".insteadOf "https://github.com/" +ENV GOPRIVATE=github.com/babylonchain/babylon-private + +# Build +WORKDIR /go/src/github.com/babylonchain/covenant +# Cache dependencies +COPY ./../go.mod ./../go.sum /go/src/github.com/babylonchain/covenant/ +RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download +# Copy the rest of the files +COPY ./ /go/src/github.com/babylonchain/covenant/ + +# Cosmwasm - Download correct libwasmvm version +RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ + -O /lib/libwasmvm_muslc.a && \ + # verify checksum + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ + sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) + +RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ + CGO_ENABLED=1 \ + BUILD_TAGS=$BUILD_TAGS \ + LINK_STATICALLY=true \ + make build + +# FINAL IMAGE +FROM alpine:3.16 AS run + +RUN addgroup --gid 1138 -S covenant && adduser --uid 1138 -S covenant -G covenant + +RUN apk add bash curl jq + +COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covd /bin/covd +COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covcli /bin/covcli + +WORKDIR /home/covenant +RUN chown -R covenant /home/covenant +USER covenant + +ENTRYPOINT ["/bin/covd"] +CMD [] +STOPSIGNAL SIGTERM diff --git a/covenant/Makefile b/covenant/Makefile new file mode 100644 index 00000000..daf2edcf --- /dev/null +++ b/covenant/Makefile @@ -0,0 +1,38 @@ +BUILDDIR ?= $(CURDIR)/build + +DOCKER := $(shell which docker) +CUR_DIR := $(shell pwd) + +ldflags := $(LDFLAGS) +build_tags := $(BUILD_TAGS) +build_args := $(BUILD_ARGS) + +ifeq ($(LINK_STATICALLY),true) + ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v +endif + +ifeq ($(VERBOSE),true) + build_args += -v +endif + +BUILD_TARGETS := build install +BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' + +all: build install + +build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) + +$(BUILD_TARGETS): go.sum $(BUILDDIR)/ + go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... + +$(BUILDDIR)/: + mkdir -p $(BUILDDIR)/ + +build-docker: + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/covenant -f Dockerfile \ + $(shell git rev-parse --show-toplevel) + +.PHONY: build build-docker clean diff --git a/service/app_test.go b/service/app_test.go index 33643027..7f659db0 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -133,10 +133,10 @@ func FuzzAddCovenantSig(f *testing.F) { // create a Covenant key pair in the keyring covenantConfig := covcfg.DefaultConfig() covenantPk, err := covenant.CreateCovenantKey( - cfg.BabylonConfig.KeyDirectory, - cfg.BabylonConfig.ChainID, - cfg.BabylonConfig.Key, - cfg.BabylonConfig.KeyringBackend, + covenantConfig.BabylonConfig.KeyDirectory, + covenantConfig.BabylonConfig.ChainID, + covenantConfig.BabylonConfig.Key, + covenantConfig.BabylonConfig.KeyringBackend, passphrase, hdPath, ) From 7c261c54f5000bbfd10d6ddf26e7021722440f2d Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 23 Nov 2023 11:21:22 +0800 Subject: [PATCH 20/66] chore: Separate covenant functionalities into a different binary (#144) --- cmd/valcli/covenant.go | 105 -------- cmd/valcli/daemoncmd.go | 5 - cmd/valcli/main.go | 1 - covenant/Dockerfile | 57 +++++ covenant/Makefile | 38 +++ covenant/cmd/covcli/admin.go | 57 +++++ covenant/cmd/covcli/main.go | 25 ++ covenant/cmd/covcli/new.go | 112 +++++++++ covenant/cmd/covd/main.go | 24 ++ covenant/cmd/covd/start.go | 76 ++++++ covenant/config/config.go | 197 +++++++++++++++ covenant/covenant.go | 414 ++++++++++++++++++++++++++++++++ covenant/service/server.go | 59 +++++ eotsmanager/cmd/eotscli/main.go | 2 +- itest/babylon_node_handler.go | 62 ++--- itest/e2e_test.go | 41 ++-- itest/test_manager.go | 123 ++++------ service/app.go | 252 +------------------ service/app_test.go | 32 +-- service/event_loop.go | 84 ------- testutil/datagen.go | 1 + valcfg/config.go | 6 - valcfg/covenant.go | 26 -- 23 files changed, 1170 insertions(+), 629 deletions(-) delete mode 100644 cmd/valcli/covenant.go create mode 100644 covenant/Dockerfile create mode 100644 covenant/Makefile create mode 100644 covenant/cmd/covcli/admin.go create mode 100644 covenant/cmd/covcli/main.go create mode 100644 covenant/cmd/covcli/new.go create mode 100644 covenant/cmd/covd/main.go create mode 100644 covenant/cmd/covd/start.go create mode 100644 covenant/config/config.go create mode 100644 covenant/covenant.go create mode 100644 covenant/service/server.go delete mode 100644 valcfg/covenant.go diff --git a/cmd/valcli/covenant.go b/cmd/valcli/covenant.go deleted file mode 100644 index 2ecdbf85..00000000 --- a/cmd/valcli/covenant.go +++ /dev/null @@ -1,105 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/babylonchain/babylon/types" - "github.com/decred/dcrd/dcrec/secp256k1/v4" - - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" -) - -type covenantKey struct { - Name string `json:"name"` - PublicKey string `json:"public-key"` -} - -var covenantCommands = []cli.Command{ - { - Name: "covenant", - ShortName: "c", - Usage: "Control Babylon Covenant.", - Category: "Covenant", - Subcommands: []cli.Command{ - createCovenant, - }, - }, -} - -var createCovenant = cli.Command{ - Name: "create-covenant", - ShortName: "cc", - Usage: "Create a Covenant account in the keyring.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: chainIdFlag, - Usage: "The chainID of the consumer chain", - Value: defaultChainID, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the Covenant key", - 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: "Select keyring's backend (os|file|test)", - Value: defaultKeyringBackend, - }, - cli.StringFlag{ - Name: keyringDirFlag, - Usage: "The directory where the keyring is stored", - }, - }, - Action: createCovenantKey, -} - -func createCovenantKey(ctx *cli.Context) error { - sdkCtx, err := service.CreateClientCtx( - ctx.String(keyringDirFlag), - ctx.String(chainIdFlag), - ) - if err != nil { - return err - } - - krController, err := val.NewChainKeyringController( - sdkCtx, - ctx.String(keyNameFlag), - ctx.String(keyringBackendFlag), - ) - if err != nil { - return err - } - - sdkCovenantPk, err := krController.CreateChainKey(ctx.String(passphraseFlag), ctx.String(hdPathFlag)) - if err != nil { - return fmt.Errorf("failed to create Covenant key: %w", err) - } - - covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) - if err != nil { - return err - } - - bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) - printRespJSON(&covenantKey{ - Name: ctx.String(keyNameFlag), - PublicKey: bip340Key.MarshalHex(), - }) - - return err -} diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index 97e831e4..2dd3ab8b 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -8,7 +8,6 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" "github.com/babylonchain/babylon/x/checkpointing/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" @@ -42,10 +41,6 @@ const ( passphraseFlag = "passphrase" hdPathFlag = "hd-path" chainIdFlag = "chain-id" - keyringDirFlag = "keyring-dir" - keyringBackendFlag = "keyring-backend" - defaultChainID = "chain-test" - defaultKeyringBackend = keyring.BackendTest defaultPassphrase = "" defaultHdPath = "" diff --git a/cmd/valcli/main.go b/cmd/valcli/main.go index 08627427..0e60380b 100644 --- a/cmd/valcli/main.go +++ b/cmd/valcli/main.go @@ -55,7 +55,6 @@ func main() { app.Commands = append(app.Commands, daemonCommands...) app.Commands = append(app.Commands, adminCommands...) - app.Commands = append(app.Commands, covenantCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/covenant/Dockerfile b/covenant/Dockerfile new file mode 100644 index 00000000..dc9cd19a --- /dev/null +++ b/covenant/Dockerfile @@ -0,0 +1,57 @@ +FROM golang:1.20.5-alpine as builder + +# Version to build. Default is the Git HEAD. +ARG VERSION="HEAD" + +# Use muslc for static libs +ARG BUILD_TAGS="muslc" + + +RUN apk add --no-cache --update openssh git make build-base linux-headers libc-dev \ + pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \ + libzmq-static libsodium-static gcc + + +RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts +RUN git config --global url."git@github.com:".insteadOf "https://github.com/" +ENV GOPRIVATE=github.com/babylonchain/babylon-private + +# Build +WORKDIR /go/src/github.com/babylonchain/covenant +# Cache dependencies +COPY ./../go.mod ./../go.sum /go/src/github.com/babylonchain/covenant/ +RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download +# Copy the rest of the files +COPY ./ /go/src/github.com/babylonchain/covenant/ + +# Cosmwasm - Download correct libwasmvm version +RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ + -O /lib/libwasmvm_muslc.a && \ + # verify checksum + wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ + sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) + +RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ + CGO_ENABLED=1 \ + BUILD_TAGS=$BUILD_TAGS \ + LINK_STATICALLY=true \ + make build + +# FINAL IMAGE +FROM alpine:3.16 AS run + +RUN addgroup --gid 1138 -S covenant && adduser --uid 1138 -S covenant -G covenant + +RUN apk add bash curl jq + +COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covd /bin/covd +COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covcli /bin/covcli + +WORKDIR /home/covenant +RUN chown -R covenant /home/covenant +USER covenant + +ENTRYPOINT ["/bin/covd"] +CMD [] +STOPSIGNAL SIGTERM diff --git a/covenant/Makefile b/covenant/Makefile new file mode 100644 index 00000000..daf2edcf --- /dev/null +++ b/covenant/Makefile @@ -0,0 +1,38 @@ +BUILDDIR ?= $(CURDIR)/build + +DOCKER := $(shell which docker) +CUR_DIR := $(shell pwd) + +ldflags := $(LDFLAGS) +build_tags := $(BUILD_TAGS) +build_args := $(BUILD_ARGS) + +ifeq ($(LINK_STATICALLY),true) + ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v +endif + +ifeq ($(VERBOSE),true) + build_args += -v +endif + +BUILD_TARGETS := build install +BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' + +all: build install + +build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) + +$(BUILD_TARGETS): go.sum $(BUILDDIR)/ + go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... + +$(BUILDDIR)/: + mkdir -p $(BUILDDIR)/ + +build-docker: + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/covenant -f Dockerfile \ + $(shell git rev-parse --show-toplevel) + +.PHONY: build build-docker clean diff --git a/covenant/cmd/covcli/admin.go b/covenant/cmd/covcli/admin.go new file mode 100644 index 00000000..a92520a0 --- /dev/null +++ b/covenant/cmd/covcli/admin.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + covcfg "github.com/babylonchain/btc-validator/covenant/config" +) + +const configFileFlag = "config" + +var adminCommands = []cli.Command{ + { + Name: "admin", + ShortName: "ad", + Usage: "Different utility and admin commands.", + Category: "Admin", + Subcommands: []cli.Command{ + dumpCfgCommand, + }, + }, +} + +var dumpCfgCommand = cli.Command{ + Name: "dump-config", + ShortName: "dc", + Usage: "Dump default configuration file.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: configFileFlag, + Usage: "Path to where the default config file will be dumped", + Value: covcfg.DefaultConfigFile, + }, + }, + Action: dumpCfg, +} + +func dumpCfg(c *cli.Context) error { + configPath := c.String(configFileFlag) + + if covcfg.FileExists(configPath) { + return fmt.Errorf("config already exists under provided path: %s", configPath) + } + + defaultConfig := covcfg.DefaultConfig() + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) + + if err != nil { + return err + } + + return nil +} diff --git a/covenant/cmd/covcli/main.go b/covenant/cmd/covcli/main.go new file mode 100644 index 00000000..11aa55e4 --- /dev/null +++ b/covenant/cmd/covcli/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[covenant-emulator cli] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "covcli" + app.Usage = "Control plane for the Covenant Emulator Daemon (covd)." + app.Commands = append(app.Commands, adminCommands...) + app.Commands = append(app.Commands, createCovenant) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/covenant/cmd/covcli/new.go b/covenant/cmd/covcli/new.go new file mode 100644 index 00000000..d0621aa1 --- /dev/null +++ b/covenant/cmd/covcli/new.go @@ -0,0 +1,112 @@ +package main + +import ( + "encoding/json" + "fmt" + + "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/urfave/cli" + + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" +) + +const ( + keyNameFlag = "key-name" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + keyringDirFlag = "keyring-dir" + keyringBackendFlag = "keyring-backend" + defaultChainID = "chain-test" + defaultKeyringBackend = keyring.BackendTest + defaultPassphrase = "" + defaultHdPath = "" +) + +type covenantKey struct { + Name string `json:"name"` + PublicKey string `json:"public-key"` +} + +var createCovenant = cli.Command{ + Name: "create-covenant", + ShortName: "cc", + Usage: "Create a Covenant account in the keyring.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: chainIdFlag, + Usage: "The chainID of the consumer chain", + Value: defaultChainID, + }, + cli.StringFlag{ + Name: keyNameFlag, + Usage: "The unique name of the Covenant key", + 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: "Select keyring's backend", + Value: defaultKeyringBackend, + }, + cli.StringFlag{ + Name: keyringDirFlag, + Usage: "The directory where the keyring is stored", + Value: covcfg.DefaultCovenantDir, + }, + }, + Action: createCovenantKey, +} + +func createCovenantKey(ctx *cli.Context) error { + keyringDir := ctx.String(keyringDirFlag) + chainID := ctx.String(chainIdFlag) + keyName := ctx.String(keyNameFlag) + backend := ctx.String(keyringBackendFlag) + passphrase := ctx.String(passphraseFlag) + hdPath := ctx.String(hdPathFlag) + + covenantPk, err := covenant.CreateCovenantKey( + keyringDir, + chainID, + keyName, + backend, + passphrase, + hdPath, + ) + + if err != nil { + return fmt.Errorf("failed to create covenant key: %w", err) + } + + bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) + printRespJSON( + &covenantKey{ + Name: ctx.String(keyNameFlag), + PublicKey: bip340Key.MarshalHex(), + }, + ) + + return err +} + +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/covenant/cmd/covd/main.go b/covenant/cmd/covd/main.go new file mode 100644 index 00000000..9f4cd2a4 --- /dev/null +++ b/covenant/cmd/covd/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[covenant-emulator] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "covd" + app.Usage = "Covenant Emulator Daemon (covd)." + app.Commands = append(app.Commands, startCovenant) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go new file mode 100644 index 00000000..cdf1ccff --- /dev/null +++ b/covenant/cmd/covd/start.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "os" + + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + + "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + covsrv "github.com/babylonchain/btc-validator/covenant/service" +) + +const ( + passphraseFlag = "passphrase" + configFileFlag = "config" + + defaultPassphrase = "" +) + +var startCovenant = cli.Command{ + Name: "start", + Usage: "covd start", + Description: "Start the Covenant Emulator Daemon. Note that the Covenant should be created beforehand", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: configFileFlag, + Usage: "The path to the covenant config file", + Value: covcfg.DefaultConfigFile, + }, + }, + Action: startCovenantFn, +} + +func startCovenantFn(ctx *cli.Context) error { + configFilePath := ctx.String(configFileFlag) + cfg, cfgLogger, err := covcfg.LoadConfig(configFilePath) + if err != nil { + return fmt.Errorf("failed to load config at %s: %w", configFilePath, err) + } + + bbnClient, err := clientcontroller.NewBabylonController(cfg.CovenantDir, cfg.BabylonConfig, cfgLogger) + if err != nil { + return fmt.Errorf("failed to create rpc client for the consumer chain: %w", err) + } + + ce, err := covenant.NewCovenantEmulator(cfg, bbnClient, ctx.String(passphraseFlag), cfgLogger) + if err != nil { + return fmt.Errorf("failed to start the covenant emulator: %w", err) + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + srv := covsrv.NewCovenantServer(cfgLogger, ce, shutdownInterceptor) + if err != nil { + return fmt.Errorf("failed to create covenant server: %w", err) + } + + if err := srv.RunUntilShutdown(); err != nil { + return err + } + + return ce.Start() +} diff --git a/covenant/config/config.go b/covenant/config/config.go new file mode 100644 index 00000000..d92622b5 --- /dev/null +++ b/covenant/config/config.go @@ -0,0 +1,197 @@ +package config + +import ( + "fmt" + "io" + "os" + "path/filepath" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/jessevdk/go-flags" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/valcfg" +) + +const ( + defaultLogLevel = "debug" + defaultLogFilename = "covd.log" + defaultConfigFileName = "covd.conf" + defaultCovenantKeyName = "covenant-key" + defaultQueryInterval = 15 * time.Second + defaultDelegationLimit = uint64(100) + defaultBitcoinNetwork = "simnet" + emptySlashingAddress = "" +) + +var ( + // C:\Users\\AppData\Local\ on Windows + // ~/.vald on Linux + // ~/Library/Application Support/Covd on MacOS + DefaultCovenantDir = btcutil.AppDataDir("covd", false) + + DefaultConfigFile = filepath.Join(DefaultCovenantDir, defaultConfigFileName) +) + +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"` + CovenantDir string `long:"covenantdir" description:"The base directory of the Covenant emulator"` + DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` + QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` + DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` + // slashing address can be empty as it will be set from Babylon params + SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` + BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` + + ActiveNetParams chaincfg.Params + + BabylonConfig *valcfg.BBNConfig `group:"babylon" namespace:"babylon"` +} + +// LoadConfig initializes and parses the config using a config file and command +// line options. +// +// The configuration proceeds as follows: +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options +func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { + // Pre-parse the command line options to pick up an alternative config + // file. + preCfg := DefaultConfig() + if _, err := flags.Parse(&preCfg); err != nil { + return nil, nil, err + } + + if !FileExists(filePath) { + return nil, nil, fmt.Errorf("specified config file does "+ + "not exist in %s", filePath) + } + + // Next, load any additional configuration options from the file. + var configFileError error + cfg := preCfg + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).ParseFile(filePath) + if err != nil { + // If it's a parsing related error, then we'll return + // immediately, otherwise we can proceed as possibly the config + // file doesn't exist which is OK. + if _, ok := err.(*flags.IniError); ok { + return nil, nil, err + } + + configFileError = err + } + + cfgLogger := logrus.New() + cfgLogger.Out = os.Stdout + // Make sure everything we just loaded makes sense. + if err := cfg.Validate(); err != nil { + return nil, nil, err + } + + logRuslLevel, err := logrus.ParseLevel(cfg.LogLevel) + if err != nil { + return nil, nil, err + } + + // At this point we know config is valid, create logger which also log to file + logFilePath := filepath.Join(cfg.CovenantDir, defaultLogFilename) + f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, nil, err + } + mw := io.MultiWriter(os.Stdout, f) + + cfgLogger.SetOutput(mw) + cfgLogger.SetLevel(logRuslLevel) + + // Warn about missing config file only after all other configuration is + // done. This prevents the warning on help messages and invalid + // options. Note this should go directly before the return. + if configFileError != nil { + cfgLogger.Warnf("%v", configFileError) + if cfg.DumpCfg { + cfgLogger.Infof("Writing configuration file to %s", filePath) + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) + if err != nil { + cfgLogger.Warnf("Error writing configuration file: %v", err) + return nil, nil, err + } + } + } + + return &cfg, cfgLogger, nil +} + +// Validate check the given configuration to be sane. This makes sure no +// illegal values or combination of values are set. All file system paths are +// normalized. The cleaned up config is returned on success. +func (cfg *Config) Validate() error { + err := os.MkdirAll(cfg.CovenantDir, 0700) + if err != nil { + // Show a nicer error message if it's because a symlink + // is linked to a directory that does not exist + // (probably because it's not mounted). + if e, ok := err.(*os.PathError); ok && os.IsExist(err) { + link, lerr := os.Readlink(e.Path) + if lerr == nil { + str := "is symlink %s -> %s mounted?" + err = fmt.Errorf(str, e.Path, link) + } + } + + return fmt.Errorf("failed to create covd directory '%s': %w", cfg.CovenantDir, err) + } + + switch cfg.BitcoinNetwork { + case "testnet": + cfg.ActiveNetParams = chaincfg.TestNet3Params + case "regtest": + cfg.ActiveNetParams = chaincfg.RegressionNetParams + case "simnet": + cfg.ActiveNetParams = chaincfg.SimNetParams + case "signet": + cfg.ActiveNetParams = chaincfg.SigNetParams + default: + return fmt.Errorf("unsupported Bitcoin network: %s", cfg.BitcoinNetwork) + } + + _, err = logrus.ParseLevel(cfg.LogLevel) + if err != nil { + return err + } + + return nil +} + +func FileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + +func DefaultConfig() Config { + bbnCfg := valcfg.DefaultBBNConfig() + bbnCfg.Key = defaultCovenantKeyName + bbnCfg.KeyDirectory = DefaultCovenantDir + return Config{ + LogLevel: defaultLogLevel, + CovenantDir: DefaultCovenantDir, + DumpCfg: false, + QueryInterval: defaultQueryInterval, + DelegationLimit: defaultDelegationLimit, + SlashingAddress: emptySlashingAddress, + BitcoinNetwork: defaultBitcoinNetwork, + ActiveNetParams: chaincfg.Params{}, + BabylonConfig: &bbnCfg, + } +} diff --git a/covenant/covenant.go b/covenant/covenant.go new file mode 100644 index 00000000..801a70ad --- /dev/null +++ b/covenant/covenant.go @@ -0,0 +1,414 @@ +package covenant + +import ( + "fmt" + "strings" + "sync" + "time" + + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/clientcontroller" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/btc-validator/service" + "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/val" +) + +type CovenantEmulator struct { + startOnce sync.Once + stopOnce sync.Once + + wg sync.WaitGroup + quit chan struct{} + + cc clientcontroller.ClientController + kc *val.ChainKeyringController + + config *covcfg.Config + logger *logrus.Logger + + // input is used to pass passphrase to the keyring + input *strings.Reader + passphrase string +} + +func NewCovenantEmulator( + config *covcfg.Config, + cc clientcontroller.ClientController, + passphrase string, + logger *logrus.Logger, +) (*CovenantEmulator, error) { + input := strings.NewReader("") + kr, err := service.CreateKeyring( + config.BabylonConfig.KeyDirectory, + config.BabylonConfig.ChainID, + config.BabylonConfig.KeyringBackend, + input, + ) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.BabylonConfig.Key, input) + if err != nil { + return nil, err + } + + if _, err := kc.GetChainPrivKey(passphrase); err != nil { + return nil, fmt.Errorf("covenant key %s is not found: %w", config.BabylonConfig.Key, err) + } + + return &CovenantEmulator{ + cc: cc, + kc: kc, + config: config, + logger: logger, + input: input, + passphrase: passphrase, + quit: make(chan struct{}), + }, nil +} + +// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO the logic will be largely replaced when new staking utilities are introduced +func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*service.AddCovenantSigResponse, error) { + if btcDel.CovenantSig != nil { + return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") + } + + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) + if err != nil { + return nil, err + } + err = slashingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) + if err != nil { + return nil, fmt.Errorf("invalid delegation: %w", err) + } + + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) + if err != nil { + return nil, err + } + stakingMsgTx, err := stakingTx.ToMsgTx() + if err != nil { + return nil, err + } + + // get Covenant private key from the keyring + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + + covenantSig, err := slashingTx.Sign( + stakingMsgTx, + stakingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + if err != nil { + return nil, err + } + + stakingTxHash := stakingMsgTx.TxHash().String() + + covenantSchnorrSig, err := covenantSig.ToBTCSig() + if err != nil { + return nil, err + } + res, err := ce.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) + + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "validator_pk": valPkHex, + "delegator_pk": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, err + } + + return &service.AddCovenantSigResponse{TxHash: res.TxHash}, nil +} + +// AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO the logic will be largely replaced when new staking utilities are introduced +func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*service.AddCovenantSigResponse, error) { + if del == nil { + return nil, fmt.Errorf("btc delegation is nil") + } + + if del.BtcUndelegation == nil { + return nil, fmt.Errorf("delegation does not have an unbonding transaction") + } + + if del.BtcUndelegation.ValidatorUnbondingSig == nil { + return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") + } + + // In normal operation it is not possible to have one of this signatures and not have the other + // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg + // which should update both fields at atomically in case of successfull transaction. + if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { + return nil, fmt.Errorf("delegation already has required covenant signatures") + } + + // get Covenant private key from the keyring + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + + // 1. Sign unbonding transaction + stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + if err != nil { + return nil, err + } + stakingMsgTx, err := stakingTx.ToMsgTx() + + if err != nil { + return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) + } + + unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) + if err != nil { + return nil, err + } + covenantUnbondingSig, err := unbondingTx.Sign( + stakingMsgTx, + stakingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + + if err != nil { + return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) + } + + // 2. Sign slash unbonding transaction + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + if err != nil { + return nil, err + } + err = slashUnbondingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) + if err != nil { + return nil, err + } + + unbondingMsgTx, err := unbondingTx.ToMsgTx() + + if err != nil { + return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) + } + + covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( + unbondingMsgTx, + unbondingTx.Script, + covenantPrivKey, + &ce.config.ActiveNetParams, + ) + if err != nil { + return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) + } + + stakingTxHash := stakingMsgTx.TxHash().String() + + covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } + covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() + if err != nil { + return nil, err + } + res, err := ce.cc.SubmitCovenantUnbondingSigs( + del.ValBtcPk, + del.BtcPk, + stakingTxHash, + covenantUnbondingSchnorrSig, + covenantSlashingUnbondingShcnorrSig, + ) + + valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() + + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, err + } + + if res == nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "valBtcPubKey": valPkHex, + "delBtcPubKey": delPkHex, + }).Error("failed to submit Covenant signature") + return nil, fmt.Errorf("failed to submit Covenant signature due to known error") + } + + return &service.AddCovenantSigResponse{ + TxHash: res.TxHash, + }, nil +} + +func (ce *CovenantEmulator) getPrivKey() (*btcec.PrivateKey, error) { + sdkPrivKey, err := ce.kc.GetChainPrivKey(ce.passphrase) + if err != nil { + return nil, err + } + + privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) + + return privKey, nil +} + +// covenantSigSubmissionLoop is the reactor to submit Covenant signature for BTC delegations +func (ce *CovenantEmulator) covenantSigSubmissionLoop() { + defer ce.wg.Done() + + interval := ce.config.QueryInterval + limit := ce.config.DelegationLimit + covenantSigTicker := time.NewTicker(interval) + + for { + select { + case <-covenantSigTicker.C: + // 0. Update slashing address in case it is changed upon governance proposal + params, err := ce.cc.QueryStakingParams() + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get slashing address") + continue + } + slashingAddress := params.SlashingAddress + _, err = btcutil.DecodeAddress(slashingAddress, &ce.config.ActiveNetParams) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("invalid slashing address") + continue + } + ce.config.SlashingAddress = slashingAddress + + // 1. Get all pending delegations first, these are more important than the unbonding ones + dels, err := ce.cc.QueryPendingDelegations(limit) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get pending delegations") + continue + } + if len(dels) == 0 { + ce.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") + } + + for _, d := range dels { + _, err := ce.AddCovenantSignature(d) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "del_btc_pk": d.BtcPk, + }).Error("failed to submit Covenant sig to the Bitcoin delegation") + } + } + + // 2. Get all unbonding delegations + unbondingDels, err := ce.cc.QueryUnbondingDelegations(limit) + + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + }).Error("failed to get pending delegations") + continue + } + + if len(unbondingDels) == 0 { + ce.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") + } + + for _, d := range unbondingDels { + _, err := ce.AddCovenantUnbondingSignatures(d) + if err != nil { + ce.logger.WithFields(logrus.Fields{ + "err": err, + "del_btc_pk": d.BtcPk, + }).Error("failed to submit Covenant sig to the Bitcoin delegation") + } + } + + case <-ce.quit: + ce.logger.Debug("exiting covenant signature submission loop") + return + } + } + +} + +func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*btcec.PublicKey, error) { + sdkCtx, err := service.CreateClientCtx( + keyringDir, chainID, + ) + if err != nil { + return nil, err + } + + krController, err := val.NewChainKeyringController( + sdkCtx, + keyName, + backend, + ) + if err != nil { + return nil, err + } + + sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) + if err != nil { + return nil, err + } + + covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) + if err != nil { + return nil, err + } + + return covenantPk, nil +} + +func (ce *CovenantEmulator) Start() error { + var startErr error + ce.startOnce.Do(func() { + ce.logger.Infof("Starting Covenant Emulator") + + ce.wg.Add(1) + go ce.covenantSigSubmissionLoop() + }) + + return startErr +} + +func (ce *CovenantEmulator) Stop() error { + var stopErr error + ce.stopOnce.Do(func() { + ce.logger.Infof("Stopping Covenant Emulator") + + // Always stop the submission loop first to not generate additional events and actions + ce.logger.Debug("Stopping submission loop") + close(ce.quit) + ce.wg.Wait() + + ce.logger.Debug("Covenant Emulator successfully stopped") + }) + return stopErr +} diff --git a/covenant/service/server.go b/covenant/service/server.go new file mode 100644 index 00000000..b0ed3b4a --- /dev/null +++ b/covenant/service/server.go @@ -0,0 +1,59 @@ +package service + +import ( + "fmt" + "sync/atomic" + + "github.com/lightningnetwork/lnd/signal" + "github.com/sirupsen/logrus" + + "github.com/babylonchain/btc-validator/covenant" +) + +// CovenantServer is the main daemon construct for the covenant emulator. +type CovenantServer struct { + started int32 + + ce *covenant.CovenantEmulator + + logger *logrus.Logger + + interceptor signal.Interceptor + + quit chan struct{} +} + +// NewCovenantServer creates a new server with the given config. +func NewCovenantServer(l *logrus.Logger, ce *covenant.CovenantEmulator, sig signal.Interceptor) *CovenantServer { + return &CovenantServer{ + logger: l, + ce: ce, + interceptor: sig, + quit: make(chan struct{}, 1), + } +} + +// RunUntilShutdown runs the main EOTS manager server loop until a signal is +// received to shut down the process. +func (s *CovenantServer) RunUntilShutdown() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + + defer func() { + _ = s.ce.Stop() + s.logger.Info("Shutdown covenant emulator server complete") + }() + + if err := s.ce.Start(); err != nil { + return fmt.Errorf("failed to start covenant emulator: %w", err) + } + + s.logger.Infof("Covenant Emulator Daemon is fully active!") + + // Wait for shutdown signal from either a graceful server stop or from + // the interrupt handler. + <-s.interceptor.ShutdownChannel() + + return nil +} diff --git a/eotsmanager/cmd/eotscli/main.go b/eotsmanager/cmd/eotscli/main.go index fe31581c..e26988ce 100644 --- a/eotsmanager/cmd/eotscli/main.go +++ b/eotsmanager/cmd/eotscli/main.go @@ -8,7 +8,7 @@ import ( ) func fatal(err error) { - fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + fmt.Fprintf(os.Stderr, "[eots-manager] %v\n", err) os.Exit(1) } diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 1aa3e14d..07c88b98 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -11,30 +11,25 @@ import ( "testing" "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" ) type babylonNode struct { - cmd *exec.Cmd - pidFile string - dataDir string - covenantKeyName string - chainID string - slashingAddr string + cmd *exec.Cmd + pidFile string + dataDir string + chainID string + slashingAddr string + covenantPk *types.BIP340PubKey } -func newBabylonNode(dataDir string, cmd *exec.Cmd, covenantKeyName, chainID string, slashingAddr string) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd, chainID string, slashingAddr string, covenantPk *types.BIP340PubKey) *babylonNode { return &babylonNode{ - dataDir: dataDir, - cmd: cmd, - covenantKeyName: covenantKeyName, - chainID: chainID, - slashingAddr: slashingAddr, + dataDir: dataDir, + cmd: cmd, + chainID: chainID, + slashingAddr: slashingAddr, + covenantPk: covenantPk, } } @@ -112,7 +107,7 @@ type BabylonNodeHandler struct { babylonNode *babylonNode } -func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { +func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *BabylonNodeHandler { testDir, err := baseDir("zBabylonTest") require.NoError(t, err) defer func() { @@ -124,25 +119,6 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { nodeDataDir := filepath.Join(testDir, "node0", "babylond") - // the Covenant key needs to be created before babylond is started - sdkCtx, err := service.CreateClientCtx( - nodeDataDir, - chainID, - ) - require.NoError(t, err) - covenantKeyName := "covenant-key" - krController, err := val.NewChainKeyringController( - sdkCtx, - covenantKeyName, - keyring.BackendTest, - ) - require.NoError(t, err) - sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) - require.NoError(t, err) - covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) - require.NoError(t, err) - covenantPkBip340 := types.NewBIP340PubKeyFromBTCPK(covenantPk) - slashingAddr := "SZtRT4BySL3o4efdGLh3k7Kny8GAnsBrSW" initTestnetCmd := exec.Command( @@ -155,7 +131,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--covenant-pk=%s", covenantPkBip340.MarshalHex()), + fmt.Sprintf("--covenant-pk=%s", covenantPk.MarshalHex()), ) var stderr bytes.Buffer @@ -180,7 +156,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, covenantKeyName, chainID, slashingAddr), + babylonNode: newBabylonNode(testDir, startCmd, chainID, slashingAddr, covenantPk), } } @@ -206,10 +182,10 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { return dir } -func (w *BabylonNodeHandler) GetCovenantKeyName() string { - return w.babylonNode.covenantKeyName -} - func (w *BabylonNodeHandler) GetSlashingAddress() string { return w.babylonNode.slashingAddr } + +func (w *BabylonNodeHandler) GetCovenantPk() *types.BIP340PubKey { + return w.babylonNode.covenantPk +} diff --git a/itest/e2e_test.go b/itest/e2e_test.go index ca357940..5b461185 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -25,7 +25,7 @@ var ( // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestValidatorLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -38,13 +38,10 @@ func TestValidatorLifeCycle(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -55,7 +52,7 @@ func TestValidatorLifeCycle(t *testing.T) { // TestMultipleValidators tests starting with multiple validators func TestMultipleValidators(t *testing.T) { n := 3 - tm := StartManagerWithValidator(t, n, false) + tm := StartManagerWithValidator(t, n) defer tm.Stop(t) app := tm.Va @@ -83,7 +80,6 @@ func TestMultipleValidators(t *testing.T) { tm.Wg.Add(1) go func(btcDel *types.Delegation) { defer tm.Wg.Done() - _ = tm.AddCovenantSignature(t, btcDel) }(del) } tm.Wg.Wait() @@ -105,7 +101,7 @@ func TestMultipleValidators(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 := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -118,13 +114,10 @@ func TestDoubleSigning(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -151,7 +144,7 @@ func TestDoubleSigning(t *testing.T) { // TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -164,12 +157,9 @@ func TestFastSync(t *testing.T) { _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) + _ = tm.WaitForNPendingDels(t, 1) - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) - - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) @@ -197,7 +187,7 @@ func TestFastSync(t *testing.T) { } func TestValidatorUnbondingSigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va @@ -210,12 +200,9 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Covenant sig - _ = tm.AddCovenantSignature(t, dels[0]) + _ = tm.WaitForNPendingDels(t, 1) - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) @@ -223,7 +210,7 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { } func TestCovenantLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1, true) + tm := StartManagerWithValidator(t, 1) defer tm.Stop(t) app := tm.Va valIns := app.ListValidatorInstances()[0] diff --git a/itest/test_manager.go b/itest/test_manager.go index cea4b1fb..c1ca393a 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -19,6 +19,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "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" sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -26,6 +27,8 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager/client" eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/service" @@ -36,22 +39,24 @@ import ( var ( eventuallyWaitTimeOut = 1 * time.Minute eventuallyPollTime = 500 * time.Millisecond - - valNamePrefix = "test-val-" - monikerPrefix = "moniker-" - chainID = "chain-test" - passphrase = "testpass" - hdPath = "" + btcNetworkParams = &chaincfg.SimNetParams + + valNamePrefix = "test-val-" + monikerPrefix = "moniker-" + covenantKeyName = "covenant-key" + chainID = "chain-test" + passphrase = "testpass" + hdPath = "" ) -var btcNetworkParams = &chaincfg.SimNetParams - type TestManager struct { Wg sync.WaitGroup BabylonHandler *BabylonNodeHandler EOTSServerHandler *EOTSServerHandler + CovenantEmulator *covenant.CovenantEmulator ValConfig *valcfg.Config EOTSConfig *eotsconfig.Config + CovenanConfig *covcfg.Config Va *service.ValidatorApp EOTSClient *client.EOTSManagerGRpcClient BabylonClient *clientcontroller.BabylonController @@ -72,45 +77,56 @@ type TestDelegationData struct { StakingAmount int64 } -func StartManager(t *testing.T, isCovenant bool) *TestManager { - bh := NewBabylonNodeHandler(t) - - err := bh.Start() +func StartManager(t *testing.T) *TestManager { + testDir, err := tempDirWithName("vale2etest") require.NoError(t, err) logger := logrus.New() logger.SetLevel(logrus.DebugLevel) logger.Out = os.Stdout - // setup validator config - testDir, err := tempDirWithName("vale2etest") + // 1. prepare covenant key, which will be used as input of Babylon node + covenantConfig := defaultCovenantConfig(testDir) + err = covenantConfig.Validate() + require.NoError(t, err) + covenantPk, err := covenant.CreateCovenantKey(testDir, chainID, covenantKeyName, keyring.BackendTest, passphrase, hdPath) require.NoError(t, err) - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isCovenant) - + // 2. prepare Babylon node + bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covenantPk)) + err = bh.Start() + require.NoError(t, err) + cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir) bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) require.NoError(t, err) + // 3. prepare EOTS manager eotsCfg := defaultEOTSConfig(t) - eh := NewEOTSServerHandler(t, eotsCfg) eh.Start() - eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) + // 4. prepare validator valApp, err := service.NewValidatorApp(cfg, bc, eotsCli, logger) require.NoError(t, err) - err = valApp.Start() require.NoError(t, err) + // 5. prepare covenant emulator + ce, err := covenant.NewCovenantEmulator(covenantConfig, bc, passphrase, logger) + require.NoError(t, err) + err = ce.Start() + require.NoError(t, err) + tm := &TestManager{ BabylonHandler: bh, EOTSServerHandler: eh, ValConfig: cfg, EOTSConfig: eotsCfg, Va: valApp, + CovenantEmulator: ce, + CovenanConfig: covenantConfig, EOTSClient: eotsCli, BabylonClient: bc, } @@ -131,8 +147,8 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int, isCovenant bool) *TestManager { - tm := StartManager(t, isCovenant) +func StartManagerWithValidator(t *testing.T, n int) *TestManager { + tm := StartManager(t) app := tm.Va for i := 0; i < n; i++ { @@ -194,6 +210,8 @@ func (tm *TestManager) Stop(t *testing.T) { tm.EOTSServerHandler.Stop() err = os.RemoveAll(tm.EOTSServerHandler.baseDir) require.NoError(t, err) + err = tm.CovenantEmulator.Stop() + require.NoError(t, err) } func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { @@ -223,7 +241,7 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegat ) require.Eventually(t, func() bool { dels, err = tm.BabylonClient.QueryPendingDelegations( - tm.ValConfig.CovenantModeConfig.DelegationLimit, + tm.CovenanConfig.DelegationLimit, ) if err != nil { return false @@ -399,38 +417,6 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, require.NoError(t, err) } -func (tm *TestManager) AddCovenantSignature(t *testing.T, del *types.Delegation) *types.TxResponse { - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(del.SlashingTxHex) - require.NoError(t, err) - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) - require.NoError(t, err) - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - - // get Covenant private key from the keyring - covenantPrivKey := tm.GetCovenantPrivKey(t) - - covenantSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &tm.ValConfig.ActiveNetParams, - ) - require.NoError(t, err) - - covenantSchnorrSig, err := covenantSig.ToBTCSig() - require.NoError(t, err) - res, err := tm.BabylonClient.SubmitCovenantSig( - del.ValBtcPk, - del.BtcPk, - stakingMsgTx.TxHash().String(), - covenantSchnorrSig, - ) - require.NoError(t, err) - - return res -} - // delegation must containt undelgation object func (tm *TestManager) AddValidatorUnbondingSignature( t *testing.T, @@ -466,17 +452,6 @@ func (tm *TestManager) AddValidatorUnbondingSignature( require.NoError(t, err) } -func (tm *TestManager) GetCovenantPrivKey(t *testing.T) *btcec.PrivateKey { - kr := tm.Va.GetKeyring() - covenantKeyName := tm.BabylonHandler.GetCovenantKeyName() - k, err := kr.Key(covenantKeyName) - require.NoError(t, err) - localKey := k.GetLocal().PrivKey.GetCachedValue() - require.IsType(t, &secp256k1.PrivKey{}, localKey) - covenantPrivKey, _ := btcec.PrivKeyFromBytes(localKey.(*secp256k1.PrivKey).Key) - return covenantPrivKey -} - func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { record, err := tm.EOTSClient.KeyRecord(valPk, passphrase) require.NoError(t, err) @@ -492,7 +467,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK require.NoError(t, err) require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - covenantPk := tm.GetCovenantPrivKey(t).PubKey() + covenantPk := tm.BabylonHandler.GetCovenantPk().MustToBTCPK() require.NoError(t, err) require.Equal(t, params.CovenantPk.SerializeCompressed()[1:], covenantPk.SerializeCompressed()[1:]) @@ -500,7 +475,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx( - r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, tm.BabylonHandler.GetSlashingAddress()) + r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, slashingAddr) require.NoError(t, err) // get msgTx @@ -621,7 +596,7 @@ func (tm *TestManager) InsertBTCUnbonding( require.NoError(t, err) } -func defaultValidatorConfig(keyringDir, testDir string, isCovenant bool) *valcfg.Config { +func defaultValidatorConfig(keyringDir, testDir string) *valcfg.Config { cfg := valcfg.DefaultConfig() cfg.ValidatorModeConfig.AutoChainScanningMode = false @@ -633,20 +608,26 @@ func defaultValidatorConfig(keyringDir, testDir string, isCovenant bool) *valcfg // Big adjustment to make sure we have enough gas in our transactions cfg.BabylonConfig.GasAdjustment = 20 cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") - cfg.CovenantMode = isCovenant - cfg.CovenantModeConfig.QueryInterval = 7 * time.Second cfg.UnbondingSigSubmissionInterval = 3 * time.Second return &cfg } +func defaultCovenantConfig(testDir string) *covcfg.Config { + cfg := covcfg.DefaultConfig() + cfg.CovenantDir = testDir + cfg.BabylonConfig.KeyDirectory = testDir + + return &cfg +} + func defaultEOTSConfig(t *testing.T) *eotsconfig.Config { cfg := eotsconfig.DefaultConfig() eotsDir, err := baseDir("zEOTSTest") require.NoError(t, err) - configFile := filepath.Join(eotsDir, "eotsd-test.conf") + configFile := filepath.Join(eotsDir, "covd-test.conf") dataDir := filepath.Join(eotsDir, "data") logDir := filepath.Join(eotsDir, "log") diff --git a/service/app.go b/service/app.go index 01fad2c2..03638e0c 100644 --- a/service/app.go +++ b/service/app.go @@ -18,7 +18,6 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/client" "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" "github.com/babylonchain/btc-validator/val" @@ -109,17 +108,6 @@ func NewValidatorApp( return nil, fmt.Errorf("failed to open the store for validators: %w", err) } - if config.CovenantMode { - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.CovenantModeConfig.CovenantKeyName, input) - if err != nil { - return nil, err - } - if _, err := kc.GetChainPrivKey(""); err != nil { - return nil, fmt.Errorf("the program is running in Covenant mode but the Covenant key %s is not found: %w", - config.CovenantModeConfig.CovenantKeyName, err) - } - } - vm, err := NewValidatorManager(valStore, config, cc, em, logger) if err != nil { return nil, fmt.Errorf("failed to create validator manager: %w", err) @@ -231,221 +219,6 @@ func (app *ValidatorApp) StartHandlingValidators() error { return app.validatorManager.Start() } -// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Covenant mode -func (app *ValidatorApp) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { - if btcDel.CovenantSig != nil { - return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") - } - - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) - if err != nil { - return nil, err - } - err = slashingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) - if err != nil { - return nil, fmt.Errorf("invalid delegation: %w", err) - } - - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) - if err != nil { - return nil, err - } - stakingMsgTx, err := stakingTx.ToMsgTx() - if err != nil { - return nil, err - } - - // get Covenant private key from the keyring - covenantPrivKey, err := app.getCovenantPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - covenantSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, err - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantSchnorrSig, err := covenantSig.ToBTCSig() - if err != nil { - return nil, err - } - res, err := app.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) - - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, fmt.Errorf("failed to submit Covenant signature due to known error") - } - - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil -} - -// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Covenant mode -func (app *ValidatorApp) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { - if del == nil { - return nil, fmt.Errorf("btc delegation is nil") - } - - if del.BtcUndelegation == nil { - return nil, fmt.Errorf("delegation does not have an unbonding transaction") - } - - if del.BtcUndelegation.ValidatorUnbondingSig == nil { - return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") - } - - // In normal operation it is not possible to have one of this signatures and not have the other - // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg - // which should update both fields at atomically in case of successfull transaction. - if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { - return nil, fmt.Errorf("delegation already has required covenant signatures") - } - - // get Covenant private key from the keyring - covenantPrivKey, err := app.getCovenantPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - // 1. Sign unbonding transaction - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) - if err != nil { - return nil, err - } - stakingMsgTx, err := stakingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) - } - - unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) - if err != nil { - return nil, err - } - covenantUnbondingSig, err := unbondingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - // 2. Sign slash unbonding transaction - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) - if err != nil { - return nil, err - } - err = slashUnbondingTx.Validate(&app.config.ActiveNetParams, app.config.CovenantModeConfig.SlashingAddress) - if err != nil { - return nil, err - } - - unbondingMsgTx, err := unbondingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) - } - - covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( - unbondingMsgTx, - unbondingTx.Script, - covenantPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() - if err != nil { - return nil, err - } - covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() - if err != nil { - return nil, err - } - res, err := app.cc.SubmitCovenantUnbondingSigs( - del.ValBtcPk, - del.BtcPk, - stakingTxHash, - covenantUnbondingSchnorrSig, - covenantSlashingUnbondingShcnorrSig, - ) - - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, fmt.Errorf("failed to submit Covenant signature due to known error") - } - - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil -} - -func (app *ValidatorApp) getCovenantPrivKey() (*btcec.PrivateKey, error) { - kc, err := val.NewChainKeyringControllerWithKeyring(app.kr, app.config.CovenantModeConfig.CovenantKeyName, app.input) - if err != nil { - return nil, err - } - - // TODO use empty passphrase for covenant for now, covenant should be run in a separate application - sdkPrivKey, err := kc.GetChainPrivKey("") - if err != nil { - return nil, err - } - - privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) - - return privKey, nil -} - // NOTE: this is not safe in production, so only used for testing purpose func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) { record, err := app.eotsManager.KeyRecord(valPk, "") @@ -467,14 +240,9 @@ func (app *ValidatorApp) Start() error { app.sentWg.Add(1) go app.registrationLoop() - if app.IsCovenant() { - app.wg.Add(1) - go app.covenantSigSubmissionLoop() - } else { - if err := app.StartHandlingValidators(); err != nil { - startErr = err - return - } + if err := app.StartHandlingValidators(); err != nil { + startErr = err + return } }) @@ -491,12 +259,10 @@ func (app *ValidatorApp) Stop() error { close(app.quit) app.wg.Wait() - if !app.IsCovenant() { - app.logger.Debug("Stopping validators") - if err := app.validatorManager.Stop(); err != nil { - stopErr = err - return - } + app.logger.Debug("Stopping validators") + if err := app.validatorManager.Stop(); err != nil { + stopErr = err + return } app.logger.Debug("Sent to Babylon loop stopped") @@ -557,10 +323,6 @@ func (app *ValidatorApp) CreateValidator( } } -func (app *ValidatorApp) IsCovenant() bool { - return app.config.CovenantMode -} - func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) if err != nil { diff --git a/service/app_test.go b/service/app_test.go index f8fa5f4d..7f659db0 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -9,17 +9,17 @@ import ( bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/chaincfg" - secp256k12 "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" "github.com/babylonchain/btc-validator/valcfg" ) @@ -131,24 +131,28 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) // create a Covenant key pair in the keyring - covenantKc, err := val.NewChainKeyringControllerWithKeyring( - app.GetKeyring(), - cfg.CovenantModeConfig.CovenantKeyName, - app.GetInput(), + covenantConfig := covcfg.DefaultConfig() + covenantPk, err := covenant.CreateCovenantKey( + covenantConfig.BabylonConfig.KeyDirectory, + covenantConfig.BabylonConfig.ChainID, + covenantConfig.BabylonConfig.Key, + covenantConfig.BabylonConfig.KeyringBackend, + passphrase, + hdPath, ) require.NoError(t, err) - sdkJurPk, err := covenantKc.CreateChainKey(passphrase, hdPath) + ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logger) require.NoError(t, err) - covenantPk, err := secp256k12.ParsePubKey(sdkJurPk.Key) - require.NoError(t, err) - require.NotNil(t, covenantPk) - cfg.CovenantMode = true err = app.Start() require.NoError(t, err) + err = ce.Start() + require.NoError(t, err) defer func() { err = app.Stop() require.NoError(t, err) + err = ce.Stop() + require.NoError(t, err) }() // create a validator object and save it to db @@ -187,9 +191,7 @@ func FuzzAddCovenantSig(f *testing.F) { gomock.Any(), ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - cfg.CovenantModeConfig.SlashingAddress = slashingAddr.String() - res, err := app.AddCovenantSignature(delegation) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) + covenantConfig.SlashingAddress = slashingAddr.String() + // TODO create covenant emulator }) } diff --git a/service/event_loop.go b/service/event_loop.go index c8ad7ca3..17c3b07d 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -2,96 +2,12 @@ package service import ( "encoding/hex" - "time" - "github.com/btcsuite/btcd/btcutil" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" ) -// covenantSigSubmissionLoop is the reactor to submit Covenant signature for pending BTC delegations -func (app *ValidatorApp) covenantSigSubmissionLoop() { - defer app.wg.Done() - - interval := app.config.CovenantModeConfig.QueryInterval - limit := app.config.CovenantModeConfig.DelegationLimit - covenantSigTicker := time.NewTicker(interval) - - for { - select { - case <-covenantSigTicker.C: - // 0. Update slashing address in case it is changed upon governance proposal - params, err := app.cc.QueryStakingParams() - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get slashing address") - continue - } - slashingAddress := params.SlashingAddress - _, err = btcutil.DecodeAddress(slashingAddress, &app.config.ActiveNetParams) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("invalid slashing address") - continue - } - app.config.CovenantModeConfig.SlashingAddress = slashingAddress - - // 1. Get all pending delegations first, this are more important than the unbonding ones - dels, err := app.cc.QueryPendingDelegations(limit) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - if len(dels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") - } - - for _, d := range dels { - _, err := app.AddCovenantSignature(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") - } - } - // 2. Get all unbonding delegations - unbondingDels, err := app.cc.QueryUnbondingDelegations(limit) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - - if len(unbondingDels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") - } - - for _, d := range unbondingDels { - _, err := app.AddCovenantUnbondingSignatures(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") - } - } - - case <-app.quit: - app.logger.Debug("exiting covenantSigSubmissionLoop") - return - } - } - -} - // main event loop for the validator app func (app *ValidatorApp) eventLoop() { defer app.eventWg.Done() diff --git a/testutil/datagen.go b/testutil/datagen.go index 98408059..90485015 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -94,6 +94,7 @@ func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp, p storedVal, err := app.GetValidatorStore().GetStoreValidator(res.ValPk.MustMarshal()) require.NoError(t, err) + return storedVal } diff --git a/valcfg/config.go b/valcfg/config.go index 8ec070a1..3e82cd13 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -83,8 +83,6 @@ type Config struct { ActiveNetParams chaincfg.Params - CovenantMode bool `long:"covenantmode" description:"If the program is running in Covenant mode"` - PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` @@ -95,8 +93,6 @@ type Config struct { ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - CovenantModeConfig *CovenantConfig `group:"covenant" namespace:"covenant"` - GRpcServerConfig *GRpcServerConfig RpcListeners []net.Addr @@ -105,7 +101,6 @@ type Config struct { func DefaultConfig() Config { bbnCfg := DefaultBBNConfig() dbCfg := DefaultDatabaseConfig() - covenantCfg := DefaultCovenantConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() eotsMngrCfg := DefaultEOTSManagerConfig() @@ -119,7 +114,6 @@ func DefaultConfig() Config { DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, ValidatorModeConfig: &valCfg, - CovenantModeConfig: &covenantCfg, PollerConfig: &pollerCfg, EOTSManagerConfig: &eotsMngrCfg, NumPubRand: defaultNumPubRand, diff --git a/valcfg/covenant.go b/valcfg/covenant.go deleted file mode 100644 index 5bce2123..00000000 --- a/valcfg/covenant.go +++ /dev/null @@ -1,26 +0,0 @@ -package valcfg - -import ( - "time" -) - -var ( - defaultCovenantKeyName = "covenant-key" - defaultQueryInterval = 15 * time.Second - defaultDelegationLimit = uint64(100) -) - -type CovenantConfig struct { - CovenantKeyName string `long:"covenantkeyname" description:"The key name of the Covenant if the program is running in Covenant mode"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` - DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` - SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` -} - -func DefaultCovenantConfig() CovenantConfig { - return CovenantConfig{ - CovenantKeyName: defaultCovenantKeyName, - QueryInterval: defaultQueryInterval, - DelegationLimit: defaultDelegationLimit, - } -} From 922e2c5567a9a1db9b4edb2c73874c4725fc7bb3 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 23 Nov 2023 11:44:12 +0800 Subject: [PATCH 21/66] chore: Refactor validator app (#146) --- cmd/valcli/admin.go | 8 ++ cmd/valcli/daemoncmd.go | 4 +- cmd/vald/main.go | 54 +++---------- cmd/vald/start.go | 87 ++++++++++++++++++++ covenant/cmd/covcli/admin.go | 8 ++ covenant/cmd/covd/start.go | 10 +-- covenant/config/config.go | 6 +- covenant/covenant_test.go | 89 +++++++++++++++++++++ eotsmanager/cmd/eotscli/admin.go | 8 ++ itest/e2e_test.go | 73 ++--------------- itest/test_manager.go | 74 +++++++++-------- service/app.go | 12 +-- service/app_test.go | 99 ----------------------- service/rpcserver.go | 27 +------ service/server.go | 119 +++------------------------- service/validator_manager.go | 18 ++--- service/validator_manager_test.go | 8 +- valcfg/config.go | 127 +++++++----------------------- 18 files changed, 316 insertions(+), 515 deletions(-) create mode 100644 cmd/vald/start.go create mode 100644 covenant/covenant_test.go diff --git a/cmd/valcli/admin.go b/cmd/valcli/admin.go index ae535c7e..9ed4e15a 100644 --- a/cmd/valcli/admin.go +++ b/cmd/valcli/admin.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "os" + "path/filepath" "github.com/jessevdk/go-flags" "github.com/urfave/cli" @@ -53,6 +55,12 @@ func dumpCfg(c *cli.Context) error { ) } + // ensure the directory exists + configDir := filepath.Dir(configPath) + if err := os.MkdirAll(configDir, 0700); err != nil { + return err + } + defaultConfig := valcfg.DefaultConfig() fileParser := flags.NewParser(&defaultConfig, flags.Default) diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index 2dd3ab8b..c2c2de51 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -164,7 +164,7 @@ func createValDaemon(ctx *cli.Context) error { return err } - description, err := getDesciptionFromContext(ctx) + description, err := getDescriptionFromContext(ctx) if err != nil { return err } @@ -194,7 +194,7 @@ func createValDaemon(ctx *cli.Context) error { return nil } -func getDesciptionFromContext(ctx *cli.Context) (stakingtypes.Description, error) { +func getDescriptionFromContext(ctx *cli.Context) (stakingtypes.Description, error) { // get information for description monikerStr := ctx.String(monikerFlag) identityStr := ctx.String(identityFlag) diff --git a/cmd/vald/main.go b/cmd/vald/main.go index a2366ce6..717d82cf 100644 --- a/cmd/vald/main.go +++ b/cmd/vald/main.go @@ -4,51 +4,21 @@ import ( "fmt" "os" - "github.com/jessevdk/go-flags" - "github.com/lightningnetwork/lnd/signal" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/valcfg" + "github.com/urfave/cli" ) -func main() { - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - cfg, cfgLogger, err := valcfg.LoadConfig() - if err != nil { - if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { - // Print error if not due to help request. - err = fmt.Errorf("failed to load config: %w", err) - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - // Help was requested, exit normally. - os.Exit(0) - } - - valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger) - if err != nil { - cfgLogger.Errorf("failed to create validator app: %v", err) - os.Exit(1) - } - // start app event loop - // TODO: graceful shutdown - if err := valApp.Start(); err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + os.Exit(1) +} - valServer := service.NewValidatorServer(cfg, cfgLogger, valApp, shutdownInterceptor) +func main() { + app := cli.NewApp() + app.Name = "vald" + app.Usage = "BTC Validator Daemon (vald)." + app.Commands = append(app.Commands, startValidator) - err = valServer.RunUntilShutdown() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) + if err := app.Run(os.Args); err != nil { + fatal(err) } } diff --git a/cmd/vald/start.go b/cmd/vald/start.go new file mode 100644 index 00000000..6fb43ac6 --- /dev/null +++ b/cmd/vald/start.go @@ -0,0 +1,87 @@ +package main + +import ( + "fmt" + + "github.com/babylonchain/babylon/types" + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + + covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/btc-validator/service" + "github.com/babylonchain/btc-validator/valcfg" +) + +const ( + passphraseFlag = "passphrase" + configFileFlag = "config" + valPkFlag = "validator-pk" + + defaultPassphrase = "" +) + +var startValidator = cli.Command{ + Name: "start", + Usage: "vald start", + Description: "Start the validator daemon. Note that eotsd should be started beforehand", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to decrypt the private key", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: configFileFlag, + Usage: "The path to the covenant config file", + Value: covcfg.DefaultConfigFile, + }, + cli.StringFlag{ + Name: valPkFlag, + Usage: "The public key of the validator to start", + }, + }, + Action: startValidatorFn, +} + +func startValidatorFn(ctx *cli.Context) error { + passphrase := ctx.String(passphraseFlag) + configFilePath := ctx.String(configFileFlag) + valPkStr := ctx.String(valPkFlag) + + cfg, cfgLogger, err := valcfg.LoadConfig(configFilePath) + if err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + + valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger) + if err != nil { + return fmt.Errorf("failed to create validator app: %v", err) + } + + // only start the daemon without starting any validator instance + // as there might be no validator registered yet + if err := valApp.Start(); err != nil { + return fmt.Errorf("failed to start the validator daemon: %w", err) + } + + if valPkStr != "" { + // start the validator instance with the given public key + valPk, err := types.NewBIP340PubKeyFromHex(valPkStr) + if err != nil { + return fmt.Errorf("invalid validator public key %s: %w", valPkStr, err) + } + if err := valApp.StartHandlingValidator(valPk, passphrase); err != nil { + return fmt.Errorf("failed to start the validator instance %s: %w", valPkStr, err) + } + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + return err + } + + valServer := service.NewValidatorServer(cfg, cfgLogger, valApp, shutdownInterceptor) + + return valServer.RunUntilShutdown() +} diff --git a/covenant/cmd/covcli/admin.go b/covenant/cmd/covcli/admin.go index a92520a0..bf85a9a2 100644 --- a/covenant/cmd/covcli/admin.go +++ b/covenant/cmd/covcli/admin.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "os" + "path/filepath" "github.com/jessevdk/go-flags" "github.com/urfave/cli" @@ -44,6 +46,12 @@ func dumpCfg(c *cli.Context) error { return fmt.Errorf("config already exists under provided path: %s", configPath) } + // ensure the directory exists + configDir := filepath.Dir(configPath) + if err := os.MkdirAll(configDir, 0700); err != nil { + return err + } + defaultConfig := covcfg.DefaultConfig() fileParser := flags.NewParser(&defaultConfig, flags.Default) diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go index cdf1ccff..e86e0c88 100644 --- a/covenant/cmd/covd/start.go +++ b/covenant/cmd/covd/start.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "os" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" @@ -59,8 +58,7 @@ func startCovenantFn(ctx *cli.Context) error { // Hook interceptor for os signals. shutdownInterceptor, err := signal.Intercept() if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) + return err } srv := covsrv.NewCovenantServer(cfgLogger, ce, shutdownInterceptor) @@ -68,9 +66,5 @@ func startCovenantFn(ctx *cli.Context) error { return fmt.Errorf("failed to create covenant server: %w", err) } - if err := srv.RunUntilShutdown(); err != nil { - return err - } - - return ce.Start() + return srv.RunUntilShutdown() } diff --git a/covenant/config/config.go b/covenant/config/config.go index d92622b5..b8fc3ffc 100644 --- a/covenant/config/config.go +++ b/covenant/config/config.go @@ -183,7 +183,7 @@ func DefaultConfig() Config { bbnCfg := valcfg.DefaultBBNConfig() bbnCfg.Key = defaultCovenantKeyName bbnCfg.KeyDirectory = DefaultCovenantDir - return Config{ + cfg := Config{ LogLevel: defaultLogLevel, CovenantDir: DefaultCovenantDir, DumpCfg: false, @@ -194,4 +194,8 @@ func DefaultConfig() Config { ActiveNetParams: chaincfg.Params{}, BabylonConfig: &bbnCfg, } + + _ = cfg.Validate() + + return cfg } diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go new file mode 100644 index 00000000..e912c716 --- /dev/null +++ b/covenant/covenant_test.go @@ -0,0 +1,89 @@ +package covenant_test + +import ( + "math/rand" + "testing" + + "github.com/babylonchain/babylon/testutil/datagen" + "github.com/btcsuite/btcd/chaincfg" + "github.com/golang/mock/gomock" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/btc-validator/covenant" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/btc-validator/testutil" + "github.com/babylonchain/btc-validator/types" +) + +const ( + passphrase = "testpass" + hdPath = "" +) + +func FuzzAddCovenantSig(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + // prepare mocked babylon client + randomStartingHeight := uint64(r.Int63n(100) + 1) + finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) + currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) + mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) + + // create a Covenant key pair in the keyring + slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) + require.NoError(t, err) + covenantConfig := covcfg.DefaultConfig() + covenantConfig.SlashingAddress = slashingAddr.String() + covenantPk, err := covenant.CreateCovenantKey( + covenantConfig.BabylonConfig.KeyDirectory, + covenantConfig.BabylonConfig.ChainID, + covenantConfig.BabylonConfig.Key, + covenantConfig.BabylonConfig.KeyringBackend, + passphrase, + hdPath, + ) + require.NoError(t, err) + ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logrus.New()) + require.NoError(t, err) + + btcPk, err := datagen.GenRandomBIP340PubKey(r) + require.NoError(t, err) + + // generate BTC delegation + delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + stakingTimeBlocks := uint16(5) + stakingValue := int64(2 * 10e8) + stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk.MustToBTCPK(), covenantPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) + require.NoError(t, err) + require.NoError(t, err) + stakingTxHex, err := stakingTx.ToHexStr() + require.NoError(t, err) + delegation := &types.Delegation{ + ValBtcPk: btcPk.MustToBTCPK(), + BtcPk: delPK, + StakingTxHex: stakingTxHex, + SlashingTxHex: slashingTx.ToHexStr(), + } + + stakingMsgTx, err := stakingTx.ToMsgTx() + require.NoError(t, err) + expectedTxHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT().QueryPendingDelegations(gomock.Any()). + Return([]*types.Delegation{delegation}, nil).AnyTimes() + mockClientController.EXPECT().SubmitCovenantSig( + delegation.ValBtcPk, + delegation.BtcPk, + stakingMsgTx.TxHash().String(), + gomock.Any(), + ). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + + res, err := ce.AddCovenantSignature(delegation) + require.NoError(t, err) + require.Equal(t, expectedTxHash, res.TxHash) + }) +} diff --git a/eotsmanager/cmd/eotscli/admin.go b/eotsmanager/cmd/eotscli/admin.go index bb04aa00..5701b7cb 100644 --- a/eotsmanager/cmd/eotscli/admin.go +++ b/eotsmanager/cmd/eotscli/admin.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "os" + "path/filepath" "github.com/jessevdk/go-flags" "github.com/urfave/cli" @@ -53,6 +55,12 @@ func dumpCfg(c *cli.Context) error { ) } + // ensure the directory exists + configDir := filepath.Dir(configPath) + if err := os.MkdirAll(configDir, 0700); err != nil { + return err + } + defaultConfig := eotscfg.DefaultConfig() fileParser := flags.NewParser(&defaultConfig, flags.Default) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 5b461185..eaec847e 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -11,7 +11,6 @@ import ( "github.com/babylonchain/babylon/testutil/datagen" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" ) @@ -25,12 +24,9 @@ var ( // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestValidatorLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1) + tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] - // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) @@ -49,64 +45,13 @@ func TestValidatorLifeCycle(t *testing.T) { t.Logf("the block at height %v is finalized", lastVotedHeight) } -// TestMultipleValidators tests starting with multiple validators -func TestMultipleValidators(t *testing.T) { - n := 3 - tm := StartManagerWithValidator(t, n) - defer tm.Stop(t) - - app := tm.Va - valInstances := app.ListValidatorInstances() - - // submit BTC delegations for each validator - for _, valIns := range valInstances { - tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { - defer tm.Wg.Done() - // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, v) - - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, v.MustGetBtcPk(), stakingTime, stakingAmount) - }(valIns) - } - tm.Wg.Wait() - - // check the 3 BTC delegations are pending - dels := tm.WaitForNPendingDels(t, 3) - - // submit Covenant sigs for each delegation - for _, del := range dels { - tm.Wg.Add(1) - go func(btcDel *types.Delegation) { - defer tm.Wg.Done() - }(del) - } - tm.Wg.Wait() - - for _, valIns := range valInstances { - tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { - defer tm.Wg.Done() - _ = tm.WaitForValNActiveDels(t, v.GetBtcPkBIP340(), 1) - }(valIns) - } - tm.Wg.Wait() - - // check there's a block finalized - _ = tm.WaitForNFinalizedBlocks(t, 1) -} - // TestDoubleSigning tests the attack scenario where the validator // 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 := StartManagerWithValidator(t, 1) + tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] - // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) @@ -144,12 +89,9 @@ func TestDoubleSigning(t *testing.T) { // TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm := StartManagerWithValidator(t, 1) + tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] - // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) @@ -187,12 +129,9 @@ func TestFastSync(t *testing.T) { } func TestValidatorUnbondingSigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1) + tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] - // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) @@ -210,10 +149,8 @@ func TestValidatorUnbondingSigSubmission(t *testing.T) { } func TestCovenantLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1) + tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] // send BTC delegation and make sure it's deep enough in btclightclient module delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) diff --git a/itest/test_manager.go b/itest/test_manager.go index c1ca393a..b2856ecb 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -147,55 +147,53 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int) *TestManager { +func StartManagerWithValidator(t *testing.T) (*TestManager, *service.ValidatorInstance) { tm := StartManager(t) app := tm.Va - for i := 0; i < n; i++ { - valName := valNamePrefix + strconv.Itoa(i) - moniker := monikerPrefix + strconv.Itoa(i) - commission := sdktypes.ZeroDec() - res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, newDescription(moniker), &commission) - require.NoError(t, err) - _, err = app.RegisterValidator(res.ValPk.MarshalHex()) - require.NoError(t, err) - err = app.StartHandlingValidator(res.ValPk, passphrase) - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(res.ValPk) - require.NoError(t, err) - require.True(t, valIns.IsRunning()) - require.NoError(t, err) - - // check validators on Babylon side - require.Eventually(t, func() bool { - vals, err := tm.BabylonClient.QueryValidators() - if err != nil { - t.Logf("failed to query validtors from Babylon %s", err.Error()) - return false - } + valName := valNamePrefix + strconv.Itoa(0) + moniker := monikerPrefix + strconv.Itoa(0) + commission := sdktypes.ZeroDec() + res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, newDescription(moniker), &commission) + require.NoError(t, err) + _, err = app.RegisterValidator(res.ValPk.MarshalHex()) + require.NoError(t, err) + err = app.StartHandlingValidator(res.ValPk, passphrase) + require.NoError(t, err) + valIns, err := app.GetValidatorInstance(res.ValPk) + require.NoError(t, err) + require.True(t, valIns.IsRunning()) + require.NoError(t, err) + + // check validators on Babylon side + require.Eventually(t, func() bool { + vals, err := tm.BabylonClient.QueryValidators() + if err != nil { + t.Logf("failed to query validtors from Babylon %s", err.Error()) + return false + } + + if len(vals) != 1 { + return false + } - if len(vals) != i+1 { + for _, v := range vals { + if !strings.Contains(v.Description.Moniker, monikerPrefix) { return false } - - for _, v := range vals { - if !strings.Contains(v.Description.Moniker, monikerPrefix) { - return false - } - if !v.Commission.Equal(sdktypes.ZeroDec()) { - return false - } + if !v.Commission.Equal(sdktypes.ZeroDec()) { + return false } + } - return true - }, eventuallyWaitTimeOut, eventuallyPollTime) - } + return true + }, eventuallyWaitTimeOut, eventuallyPollTime) - require.Equal(t, n, len(app.ListValidatorInstances())) + require.Equal(t, 1, len(app.ListValidatorInstances())) - t.Logf("the test manager is running with %v validators", n) + t.Logf("the test manager is running with a validator") - return tm + return tm, valIns } func (tm *TestManager) Stop(t *testing.T) { diff --git a/service/app.go b/service/app.go index 03638e0c..323cf4ba 100644 --- a/service/app.go +++ b/service/app.go @@ -212,11 +212,7 @@ func (app *ValidatorApp) RegisterValidator(valPkStr string) (*RegisterValidatorR // StartHandlingValidator starts a validator instance with the given Babylon public key // Note: this should be called right after the validator is registered func (app *ValidatorApp) StartHandlingValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { - return app.validatorManager.addValidatorInstance(valPk, passphrase) -} - -func (app *ValidatorApp) StartHandlingValidators() error { - return app.validatorManager.Start() + return app.validatorManager.StartValidator(valPk, passphrase) } // NOTE: this is not safe in production, so only used for testing purpose @@ -229,6 +225,7 @@ func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) return record.PrivKey, nil } +// Start starts only the validator daemon without any validator instances func (app *ValidatorApp) Start() error { var startErr error app.startOnce.Do(func() { @@ -239,11 +236,6 @@ func (app *ValidatorApp) Start() error { app.sentWg.Add(1) go app.registrationLoop() - - if err := app.StartHandlingValidators(); err != nil { - startErr = err - return - } }) return startErr diff --git a/service/app_test.go b/service/app_test.go index 7f659db0..ed19ef5d 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -5,16 +5,12 @@ import ( "os" "testing" - "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/chaincfg" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/covenant" - covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/service" @@ -100,98 +96,3 @@ func FuzzRegisterValidator(f *testing.F) { require.Equal(t, valAfterReg.GetStoreValidator().Status, proto.ValidatorStatus_REGISTERED) }) } - -func FuzzAddCovenantSig(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - // create validator app with db and mocked Babylon client - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - cfg.BabylonConfig.KeyDirectory = t.TempDir() - defer func() { - err := os.RemoveAll(cfg.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) - require.NoError(t, err) - err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) - require.NoError(t, err) - }() - randomStartingHeight := uint64(r.Int63n(100) + 1) - finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) - currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) - require.NoError(t, err) - logger := logrus.New() - em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) - require.NoError(t, err) - app, err := service.NewValidatorApp(&cfg, mockClientController, em, logrus.New()) - require.NoError(t, err) - - // create a Covenant key pair in the keyring - covenantConfig := covcfg.DefaultConfig() - covenantPk, err := covenant.CreateCovenantKey( - covenantConfig.BabylonConfig.KeyDirectory, - covenantConfig.BabylonConfig.ChainID, - covenantConfig.BabylonConfig.Key, - covenantConfig.BabylonConfig.KeyringBackend, - passphrase, - hdPath, - ) - require.NoError(t, err) - ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logger) - require.NoError(t, err) - - err = app.Start() - require.NoError(t, err) - err = ce.Start() - require.NoError(t, err) - defer func() { - err = app.Stop() - require.NoError(t, err) - err = ce.Stop() - require.NoError(t, err) - }() - - // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) - btcPkBIP340 := validator.MustGetBIP340BTCPK() - btcPk := validator.MustGetBTCPK() - - // generate BTC delegation - slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - stakingTimeBlocks := uint16(5) - stakingValue := int64(2 * 10e8) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, covenantPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) - require.NoError(t, err) - require.NoError(t, err) - stakingTxHex, err := stakingTx.ToHexStr() - require.NoError(t, err) - delegation := &types.Delegation{ - ValBtcPk: btcPkBIP340.MustToBTCPK(), - BtcPk: delPK, - StakingTxHex: stakingTxHex, - SlashingTxHex: slashingTx.ToHexStr(), - } - - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryPendingDelegations(gomock.Any()). - Return([]*types.Delegation{delegation}, nil).AnyTimes() - mockClientController.EXPECT().SubmitCovenantSig( - delegation.ValBtcPk, - delegation.BtcPk, - stakingMsgTx.TxHash().String(), - gomock.Any(), - ). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - covenantConfig.SlashingAddress = slashingAddr.String() - // TODO create covenant emulator - }) -} diff --git a/service/rpcserver.go b/service/rpcserver.go index 9a1fadce..e7b58e18 100644 --- a/service/rpcserver.go +++ b/service/rpcserver.go @@ -9,13 +9,10 @@ import ( "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" - "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" "google.golang.org/grpc" "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" "github.com/babylonchain/btc-validator/version" ) @@ -27,33 +24,21 @@ type rpcServer struct { proto.UnimplementedBtcValidatorsServer - interceptor signal.Interceptor - app *ValidatorApp - logger *logrus.Logger - - cfg *valcfg.Config - quit chan struct{} wg sync.WaitGroup } // newRPCServer creates a new RPC sever from the set of input dependencies. func newRPCServer( - interceptor signal.Interceptor, - l *logrus.Logger, - cfg *valcfg.Config, v *ValidatorApp, -) (*rpcServer, error) { +) *rpcServer { return &rpcServer{ - interceptor: interceptor, - logger: l, - quit: make(chan struct{}), - cfg: cfg, - app: v, - }, nil + quit: make(chan struct{}), + app: v, + } } // Start signals that the RPC server starts accepting requests. @@ -62,8 +47,6 @@ func (r *rpcServer) Start() error { return nil } - r.logger.Infof("Starting RPC Server") - return nil } @@ -74,8 +57,6 @@ func (r *rpcServer) Stop() error { return nil } - r.logger.Infof("Stopping RPC Server") - close(r.quit) r.wg.Wait() diff --git a/service/server.go b/service/server.go index 49b4182e..5e8c0ff9 100644 --- a/service/server.go +++ b/service/server.go @@ -3,17 +3,14 @@ package service import ( "fmt" "net" - "strings" "sync" "sync/atomic" - "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/signal" "github.com/sirupsen/logrus" "google.golang.org/grpc" "github.com/babylonchain/btc-validator/valcfg" - "github.com/babylonchain/btc-validator/version" ) // Server is the main daemon construct for the BTC-Validator server. It handles @@ -25,7 +22,6 @@ type Server struct { cfg *valcfg.Config logger *logrus.Logger - valApp *ValidatorApp rpcServer *rpcServer interceptor signal.Interceptor @@ -37,13 +33,13 @@ func NewValidatorServer(cfg *valcfg.Config, l *logrus.Logger, v *ValidatorApp, s return &Server{ cfg: cfg, logger: l, - valApp: v, + rpcServer: newRPCServer(v), interceptor: sig, quit: make(chan struct{}, 1), } } -// RunUntilShutdown runs the main BTC-Validator server loop until a signal is +// RunUntilShutdown runs the main EOTS manager server loop until a signal is // received to shut down the process. func (s *Server) RunUntilShutdown() error { if atomic.AddInt32(&s.started, 1) != 1 { @@ -54,53 +50,28 @@ func (s *Server) RunUntilShutdown() error { s.logger.Info("Shutdown complete") }() - mkErr := func(format string, args ...interface{}) error { - logFormat := strings.ReplaceAll(format, "%w", "%v") - s.logger.Errorf("Shutting down because error in main "+ - "method: "+logFormat, args...) - return fmt.Errorf(format, args...) - } - + listenAddr := s.cfg.RpcListener // we create listeners from the RPCListeners defined // in the config. - grpcListeners := make([]net.Listener, 0) - for _, grpcEndpoint := range s.cfg.RpcListeners { - // Start a gRPC server listening for HTTP/2 - // connections. - lis, err := net.Listen(parseNetwork(grpcEndpoint), grpcEndpoint.String()) - if err != nil { - return mkErr("unable to listen on %s: %v", - grpcEndpoint, err) - } - defer lis.Close() - - grpcListeners = append(grpcListeners, lis) - } - - err := s.initialize() + lis, err := net.Listen("tcp", listenAddr) if err != nil { - return mkErr("unable to initialize RPC server: %v", err) + return fmt.Errorf("failed to listen on %s: %w", listenAddr, err) } + defer lis.Close() grpcServer := grpc.NewServer() defer grpcServer.Stop() - err = s.rpcServer.RegisterWithGrpcServer(grpcServer) - if err != nil { - return mkErr("error registering gRPC server: %v", err) + if err := s.rpcServer.RegisterWithGrpcServer(grpcServer); err != nil { + return fmt.Errorf("failed to register gRPC server: %w", err) } // All the necessary components have been registered, so we can // actually start listening for requests. - err = s.startGrpcListen(grpcServer, grpcListeners) - if err != nil { - return mkErr("error starting gRPC listener: %v", err) + if err := s.startGrpcListen(grpcServer, []net.Listener{lis}); err != nil { + return fmt.Errorf("failed to start gRPC listener: %v", err) } - defer func() { - _ = s.rpcServer.Stop() - }() - s.logger.Infof("BTC Validator Daemon is fully active!") // Wait for shutdown signal from either a graceful server stop or from @@ -110,58 +81,6 @@ func (s *Server) RunUntilShutdown() error { return nil } -// initialize creates and initializes an instance rpc server based on the server -// configuration. This method ensures that everything is cleaned up in case there -// is an error while initializing any of the components. -// -// NOTE: the rpc server is not registered with any grpc server in this function. -func (s *Server) initialize() error { - // Show version at startup. - s.logger.Infof("Version: %s, build=%s, logging=%s, "+ - "debuglevel=%s", version.Version(), build.Deployment, - build.LoggingType, s.cfg.DebugLevel) - - // Depending on how far we got in initializing the server, we might need - // to clean up certain services that were already started. Keep track of - // them with this map of service name to shut down function. - shutdownFuncs := make(map[string]func() error) - defer func() { - for serviceName, shutdownFn := range shutdownFuncs { - if err := shutdownFn(); err != nil { - s.logger.Errorf("Error shutting down %s service: %s", serviceName, err.Error()) - } - } - }() - - // Initialize, and register our implementation of the gRPC interface - // exported by the rpcServer. - var err error - s.rpcServer, err = newRPCServer( - s.interceptor, s.logger, s.cfg, s.valApp, - ) - if err != nil { - return fmt.Errorf("failed to create rpc server: %v", err) - } - - // Now we have created all dependencies necessary to populate and - // start the RPC server. - if err := s.rpcServer.Start(); err != nil { - return fmt.Errorf("failed to start RPC server: %v", err) - } - - // This does have no effect if starting the rpc server is the last step - // in this function, but its better to have it here in case we add more - // steps in the future. - // - // NOTE: if this is not the last step in the function, feel free to - // delete this comment. - shutdownFuncs["rpcServer"] = s.rpcServer.Stop - - shutdownFuncs = nil - - return nil -} - // startGrpcListen starts the GRPC server on the passed listeners. func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listener) error { @@ -187,21 +106,3 @@ func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listen return nil } - -// parseNetwork parses the network type of the given address. -func parseNetwork(addr net.Addr) string { - switch addr := addr.(type) { - // TCP addresses resolved through net.ResolveTCPAddr give a default - // network of "tcp", so we'll map back the correct network for the given - // address. This ensures that we can listen on the correct interface - // (IPv4 vs IPv6). - case *net.TCPAddr: - if addr.IP.To4() != nil { - return "tcp4" - } - return "tcp6" - - default: - return addr.Network() - } -} diff --git a/service/validator_manager.go b/service/validator_manager.go index 8bacc030..e3a3e41d 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -192,14 +192,12 @@ func (vm *ValidatorManager) setValidatorSlashed(vi *ValidatorInstance) { } } -func (vm *ValidatorManager) Start() error { +func (vm *ValidatorManager) StartValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { + // currently we expect that only a single validator started at a time + // we can remove the constraint when we want to run multiple validators + // in the same daemon if vm.isStarted.Swap(true) { - return fmt.Errorf("the validator manager is already started") - } - - storedValidators, err := vm.vs.ListRegisteredValidators() - if err != nil { - return err + return fmt.Errorf("a validator instance is already started") } vm.wg.Add(1) @@ -208,10 +206,8 @@ func (vm *ValidatorManager) Start() error { vm.wg.Add(1) go vm.monitorStatusUpdate() - for _, v := range storedValidators { - if err := vm.addValidatorInstance(v.MustGetBIP340BTCPK(), ""); err != nil { - return err - } + if err := vm.addValidatorInstance(valPk, passphrase); err != nil { + return err } return nil diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index ffdb99a6..df0f5a66 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -36,7 +36,7 @@ func FuzzStatusUpdate(f *testing.F) { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) - vm, cleanUp := newValidatorManagerWithRegisteredValidator(t, r, mockClientController) + vm, valPk, cleanUp := newValidatorManagerWithRegisteredValidator(t, r, mockClientController) defer cleanUp() // setup mocks @@ -59,7 +59,7 @@ func FuzzStatusUpdate(f *testing.F) { mockClientController.EXPECT().QueryValidatorSlashed(gomock.Any()).Return(true, nil).AnyTimes() } - err := vm.Start() + err := vm.StartValidator(valPk, passphrase) require.NoError(t, err) valIns := vm.ListValidatorInstances()[0] // stop the validator as we are testing static functionalities @@ -85,7 +85,7 @@ func waitForStatus(t *testing.T, valIns *service.ValidatorInstance, s proto.Vali }, eventuallyWaitTimeOut, eventuallyPollTime) } -func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.ValidatorManager, func()) { +func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.ValidatorManager, *bbntypes.BIP340PubKey, func()) { // create validator app with config cfg := valcfg.DefaultConfig() cfg.StatusUpdateInterval = 10 * time.Millisecond @@ -145,5 +145,5 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) } - return vm, cleanUp + return vm, btcPk, cleanUp } diff --git a/valcfg/config.go b/valcfg/config.go index 3e82cd13..aa87d922 100644 --- a/valcfg/config.go +++ b/valcfg/config.go @@ -14,7 +14,6 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/lightningnetwork/lnd/lncfg" "github.com/sirupsen/logrus" eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" @@ -54,6 +53,7 @@ var ( defaultLogDir = filepath.Join(DefaultValdDir, defaultLogDirname) defaultActiveNetParams = chaincfg.SimNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) + defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) ) // Config is the main config for the vald cli command @@ -93,9 +93,7 @@ type Config struct { ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - GRpcServerConfig *GRpcServerConfig - - RpcListeners []net.Addr + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` } func DefaultConfig() Config { @@ -104,7 +102,7 @@ func DefaultConfig() Config { pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() eotsMngrCfg := DefaultEOTSManagerConfig() - return Config{ + cfg := Config{ ValdDir: DefaultValdDir, ChainName: defaultChainName, ConfigFile: DefaultConfigFile, @@ -130,19 +128,12 @@ func DefaultConfig() Config { BitcoinNetwork: defaultBitcoinNetwork, ActiveNetParams: defaultActiveNetParams, EOTSManagerAddress: defaultEOTSManagerAddress, + RpcListener: defaultRpcListener, } -} -// usageError is an error type that signals a problem with the supplied flags. -type usageError struct { - err error -} + _ = cfg.Validate() -// Error returns the error string. -// -// NOTE: This is part of the error interface. -func (u *usageError) Error() string { - return u.err.Error() + return cfg } func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) { @@ -172,7 +163,7 @@ func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig() (*Config, *logrus.Logger, error) { +func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { // Pre-parse the command line options to pick up an alternative config // file. preCfg := DefaultConfig() @@ -180,39 +171,16 @@ func LoadConfig() (*Config, *logrus.Logger, error) { return nil, nil, err } - // Show the version and exit if the version flag was specified. - appName := filepath.Base(os.Args[0]) - appName = strings.TrimSuffix(appName, filepath.Ext(appName)) - usageMessage := fmt.Sprintf("Use %s -h to show usage", appName) - - // If the config file path has not been modified by the user, then - // we'll use the default config file path. However, if the user has - // modified their default dir, then we should assume they intend to use - // the config file within it. - configFileDir := CleanAndExpandPath(preCfg.ValdDir) - configFilePath := CleanAndExpandPath(preCfg.ConfigFile) - switch { - case configFileDir != DefaultValdDir && - configFilePath == DefaultConfigFile: - - configFilePath = filepath.Join( - configFileDir, defaultConfigFileName, - ) - - // User did specify an explicit --configfile, so we check that it does - // exist under that path to avoid surprises. - case configFilePath != DefaultConfigFile: - if !FileExists(configFilePath) { - return nil, nil, fmt.Errorf("specified config file does "+ - "not exist in %s", configFilePath) - } + if !FileExists(filePath) { + return nil, nil, fmt.Errorf("specified config file does "+ + "not exist in %s", filePath) } // Next, load any additional configuration options from the file. var configFileError error cfg := preCfg fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(configFilePath) + err := flags.NewIniParser(fileParser).ParseFile(filePath) if err != nil { // If it's a parsing related error, then we'll return // immediately, otherwise we can proceed as possibly the config @@ -224,33 +192,18 @@ func LoadConfig() (*Config, *logrus.Logger, error) { configFileError = err } - // Finally, parse the remaining command line options again to ensure - // they take precedence. - flagParser := flags.NewParser(&cfg, flags.Default) - if _, err := flagParser.Parse(); err != nil { - return nil, nil, err - } - cfgLogger := logrus.New() cfgLogger.Out = os.Stdout // Make sure everything we just loaded makes sense. - cleanCfg, err := ValidateConfig(cfg) - if err != nil { - // Log help message in case of usage error. - if _, ok := err.(*usageError); ok { - cfgLogger.Warnf("Incorrect usage: %v", usageMessage) - } - - cfgLogger.Warnf("Error validating config: %v", err) + if err := cfg.Validate(); err != nil { return nil, nil, err } // ignore error here as we already validated the value - logRuslLevel, _ := logrus.ParseLevel(cleanCfg.DebugLevel) + logRuslLevel, _ := logrus.ParseLevel(cfg.DebugLevel) - // TODO: Add log rotation // At this point we know config is valid, create logger which also log to file - logFilePath := filepath.Join(cleanCfg.LogDir, defaultLogFilename) + logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return nil, nil, err @@ -265,10 +218,10 @@ func LoadConfig() (*Config, *logrus.Logger, error) { // options. Note this should go directly before the return. if configFileError != nil { cfgLogger.Warnf("%v", configFileError) - if cleanCfg.DumpCfg { - cfgLogger.Infof("Writing configuration file to %s", configFilePath) + if cfg.DumpCfg { + cfgLogger.Infof("Writing configuration file to %s", filePath) fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).WriteFile(configFilePath, flags.IniIncludeComments|flags.IniIncludeDefaults) + err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) if err != nil { cfgLogger.Warnf("Error writing configuration file: %v", err) return nil, nil, err @@ -276,13 +229,13 @@ func LoadConfig() (*Config, *logrus.Logger, error) { } } - return cleanCfg, cfgLogger, nil + return &cfg, cfgLogger, nil } -// ValidateConfig check the given configuration to be sane. This makes sure no +// Validate checks the given configuration to be sane. This makes sure no // illegal values or combination of values are set. All file system paths are // normalized. The cleaned up config is returned on success. -func ValidateConfig(cfg Config) (*Config, error) { +func (cfg *Config) Validate() error { // If the provided stakerd directory is not the default, we'll modify the // path to all the files and directories that will live within it. valdDir := CleanAndExpandPath(cfg.ValdDir) @@ -291,10 +244,6 @@ func ValidateConfig(cfg Config) (*Config, error) { cfg.LogDir = filepath.Join(valdDir, defaultLogDirname) } - funcName := "ValidateConfig" - mkErr := func(format string, args ...interface{}) error { - return fmt.Errorf(funcName+": "+format, args...) - } makeDirectory := func(dir string) error { err := os.MkdirAll(dir, 0700) if err != nil { @@ -309,8 +258,7 @@ func ValidateConfig(cfg Config) (*Config, error) { } } - str := "Failed to create vald directory '%s': %v" - return mkErr(str, dir, err) + return fmt.Errorf("failed to create dir %s: %w", dir, err) } return nil @@ -336,8 +284,7 @@ func ValidateConfig(cfg Config) (*Config, error) { case "signet": cfg.ActiveNetParams = chaincfg.SigNetParams default: - return nil, mkErr(fmt.Sprintf("invalid network: %v", - cfg.BitcoinNetwork)) + return fmt.Errorf("invalid network: %v", cfg.BitcoinNetwork) } // Create the vald directory and all other subdirectories if they @@ -348,38 +295,22 @@ func ValidateConfig(cfg Config) (*Config, error) { } for _, dir := range dirs { if err := makeDirectory(dir); err != nil { - return nil, err + return err } } - // At least one RPCListener is required. So listen on localhost per - // default. - if len(cfg.GRpcServerConfig.RawRPCListeners) == 0 { - addr := fmt.Sprintf("localhost:%d", DefaultRPCPort) - cfg.GRpcServerConfig.RawRPCListeners = append( - cfg.GRpcServerConfig.RawRPCListeners, addr, - ) - } - _, err := logrus.ParseLevel(cfg.DebugLevel) - if err != nil { - return nil, mkErr("error parsing debuglevel: %v", err) + return err } - // Add default port to all RPC listener addresses if needed and remove - // duplicate addresses. - cfg.RpcListeners, err = lncfg.NormalizeAddresses( - cfg.GRpcServerConfig.RawRPCListeners, strconv.Itoa(DefaultRPCPort), - net.ResolveTCPAddr, - ) - + _, err = net.ResolveTCPAddr("tcp", cfg.RpcListener) if err != nil { - return nil, mkErr("error normalizing RPC listen addrs: %v", err) + return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) } // All good, return the sanitized result. - return &cfg, nil + return nil } // FileExists reports whether the named file or directory exists. @@ -418,7 +349,3 @@ func CleanAndExpandPath(path string) string { // but the variables can still be expanded via POSIX-style $VARIABLE. return filepath.Clean(os.ExpandEnv(path)) } - -type GRpcServerConfig struct { - RawRPCListeners []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"` -} From c5857d0c86966be1c6dfad2949cef2804036a02d Mon Sep 17 00:00:00 2001 From: Gurjot Singh <111540954+gusin13@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:41:23 -0500 Subject: [PATCH 22/66] docs: Add documentation for EOTS and Validator daemons (#147) * add docs * fix string * fix string * fix string * dn vi cmd * fix ordering * more info * more changes * more changes * fix string * bash code listings * empty space * ls bash cmd * separate docs folder and installation guide * fix cmds * configuration.md setup * fix strings * more info * config related info * dump eots config * config related attrs for eotsd * fix strings * fix strings * remove redundant info * operations.md * fix bash listings * proper numbering * add notes * more commands * more notes * more details * fix links * fix readme * fix * fix * more info * fix comments * fix headings * fix links * add more info * change to level 4 heading * Update README.md Co-authored-by: Vitalis Salis * Update README.md Co-authored-by: Vitalis Salis * Update README.md Co-authored-by: Vitalis Salis * Update README.md Co-authored-by: Vitalis Salis * Update docs/configuration.md Co-authored-by: Vitalis Salis * merge installation md in root readme * remove install.md as the contents are merged * remove sed cmds * fix hyperlinks * fix hyperlink --------- Co-authored-by: Vitalis Salis --- README.md | 86 ++++++++++++++++- docs/configuration.md | 99 +++++++++++++++++++ docs/operation.md | 214 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 docs/configuration.md create mode 100644 docs/operation.md diff --git a/README.md b/README.md index 2017bb71..e41f75ae 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,87 @@ # BTC-Validator -BTC-Validator is a stand-alone program that creates and manages all BTC validators' keys and act on behalf of them. +## 1. Overview + +BTC-Validator is a standalone program crafted for the creation and management of BTC validators. +The program includes a CLI functionality for the creation, management, and storage of validator keys, as well as the creation and registration of validators on the consumer chain. + +Once a validator is registered on the chain, BTC-Validator consistently polls for new blocks. It actively engages +with the blockchain by sending finality signatures and committing public randomness at regular intervals. + +The program consists of two essential components: the **EOTS manager Daemon** and the **Validator Daemon**. + +#### 1. EOTS Manager Daemon +The EOTS Daemon is responsible for managing EOTS keys, producing EOTS randomness +and 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). + +1. **EOTS Key Management:** + - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs for the validator using the + [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) standard. + - Persists generated key pairs in the internal [bolt db](https://github.com/etcd-io/bbolt) storage. + +2. **Randomness Generation:** + - Generates lists of [Schnorr randomness pairs](https://www.researchgate.net/publication/222835548_Schnorr_Randomness) 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 validator and corresponding secret randomness for a given chain at a specified height. + - Signs Schnorr signatures using the private key of the validator. + +#### 2. Validator Daemon + +The Validator Daemon is responsible for finality signatures and randomness commitment. + +1. **Finality Signatures:** + - Sends the finality signature to the consumer chain (Babylon) for each registered validator and for each block there's an EOTS randomness commitment. + +2. **EOTS Randomness Commitment:** + - Ensures the generation of EOTS randomness commitment on the Babylon ledger for each block the BTC validator intends to vote for. + +## 2. Installation + +#### Prerequisites + +This project requires Go version 1.20 or later. + +Install Go by following the instructions on the [official Go installation guide](https://golang.org/doc/install). + +#### Downloading the code + +To get started, clone the repository to your local machine from Github: + +```bash +$ git clone git@github.com:babylonchain/btc-validator.git +``` + +You can choose a specific version from the [official releases page](https://github.com/babylonchain/btc-validator/releases) + +```bash +$ cd btc-validator # cd into the project directory +$ git checkout +``` + +#### Building and installing the binary + +```bash +$ cd btc-validator # cd into the project directory +$ make build # build the binaries in the build directory +$ make install # installs the compiled binaries to your $GOPATH/bin directory allowing access from anywhere on your system +``` + +The build directory has the following structure +```bash +$ ls build + ├── eotcli + ├── eotsd + ├── valcli + └── vald +``` + +## 3. Configuration +Follow the [configuration guide](docs/configuration.md). + +## 4. Running the BTC Validator Program +Follow the [operations guide](docs/operation.md). diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 00000000..dfbd714b --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,99 @@ +# Configuration + +### Using `valcli` and `eotscli` for Daemon Configuration + +The `valcli` and `eotscli` tools serve as control planes for the Validator Daemon (`vald`) and EOTS Daemon (`eotsd`) +respectively. These tools allow you to configure various settings and parameters. Let's explore how to configure the +daemons. + +### Dumping Default Configuration + +The `dump-config` command dumps the default configuration for the daemon. + +```bash +$ valcli admin dump-config --help +NAME: + valcli admin dump-config - Dump default configuration file. + +USAGE: + valcli admin dump-config [command options] [arguments...] + +OPTIONS: + --config-file-dir value Path to where the default config file will be dumped (default: "~/Library/Application Support/Vald/vald.conf") +``` + +### 1. Validator daemon (`vald`) config: + +```bash +$ valcli admin dump-config +``` + +This will create a ```vald.conf``` file in the default config directory. The default config directories are: + +```bash +MacOS ~/Library/Application Support/Vald +Linux ~/.Vald +Windows C:\Users\\AppData\Local\Vald +``` + +You can also specify a custom path to store the config + +```bash +$ valcli admin dump-config --config-file-dir /path/to/your/config/dir/ +``` + +After dump the config directory has the following structure + +```bash +$ ls /path/to/your/config/dir/Vald + ├── data # Contains Vald-specific data. + ├── logs # Contains logs generated by Vald. + └── vald.conf # Vald-specific configuration file. +``` + +Lets explore some of the important parameters in the `vald.conf` file. + +```bash +# Address of the EOTS Daemon: +EOTSManagerAddress = 127.0.0.1:15813 + +# Babylon specific parameters + +# Name of the key in the keyring to use for signing transactions: +Key = node0 + +# Address of the RPC server: +RPCAddr = http://localhost:26657 +``` + +**Note:** The `Key` parameter is the name of the key in the keyring to use for signing transactions. +You can create a key and request funds from the faucet by following the instructions in the [Babylon +documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds) + +```bash +# to change the babylon rpc address you can set +RPCAddr = https://rpc.devnet.babylonchain.io:443 +``` + +### 2. EOTS daemon (`eotsd`) config : + +```bash +$ eotscli admin dump-config +``` + +After dump the config directory has following structure + +```bash +$ ls /path/to/your/config/dir/Eotsd + ├── eotsd.conf # Eotsd-specific configuration file. +``` + +Lets explore some of the important parameters in the `eotsd.conf` file. + +```bash +# Path to EOTSD configuration file +ConfigFile = /Users/John/Library/Application Support/Eotsd/eotsd.conf + +# Default address to listen for RPC connections: +RpcListener = localhost:15813 +``` diff --git a/docs/operation.md b/docs/operation.md new file mode 100644 index 00000000..b635fc77 --- /dev/null +++ b/docs/operation.md @@ -0,0 +1,214 @@ +# Operations + +Before you proceed, ensure that you have installed the necessary binaries and configured the daemons. If you haven't done so yet, please follow these steps: + +- [Installation](../README.md#2-installation) +- [Configuration](configuration.md) + +## 1. Starting the EOTS Daemon +You can start the EOTS daemon using the following command: + +```bash +$ eotsd +``` +This will start the rpc server at the default address i.e. `localhost:15813`. You can also specify a custom address using the `--rpclistener` flag. + +```bash +$ eotsd --rpclistener 'localhost:8081' + +time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" +time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager 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. + +```bash +$ eotsd --help + +Usage: + eotsd [OPTIONS] + +Application Options: + --loglevel=[trace|debug|info|warn|error|fatal] Logging level for all subsystems (default: debug) + --workdir= The base directory that contains the EOTS manager's data, logs, configuration file, etc. (default: + /Users/gurjotsingh/Library/Application Support/Eotsd) + --configfile= Path to configuration file (default: /Users/gurjotsingh/Library/Application + Support/Eotsd/eotsd.conf) + --datadir= The directory to store validator's data within (default: /Users/gurjotsingh/Library/Application + Support/Eotsd/data) + --logdir= Directory to log output. (default: /Users/gurjotsingh/Library/Application Support/Eotsd/logs) + --dumpcfg If config file does not exist, create it with current settings + --key-dir= Directory to store keys in (default: /Users/gurjotsingh/Library/Application Support/Eotsd/data) + --keyring-type= Type of keyring to use (default: file) + --backend= Possible database to choose as backend (default: bbolt) + --path= The path that stores the database file (default: bbolt-eots.db) + --name= The name of the database (default: default) + --rpclistener= the listener for RPC connections, e.g., localhost:1234 (default: localhost:15813) + +Help Options: + -h, --help Show this help message +``` + +## 2. Starting the Validator Daemon + +You can start the validator daemon using the following command: + +```bash +$ vald +``` +This will start the rpc server at the default port i.e. `15812`. You can also specify a custom port using +the `--rpclisten` flag. + +```bash +$ vald --rpclisten '8082' + +time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" +time="2023-11-26T16:37:00-05:00" level=info msg="Starting ValidatorApp" +time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" +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 on 127.0.0.1:8082" +time="2023-11-26T16:37:00-05:00" level=info msg="BTC Validator 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. + +```bash +$ vald --help + +Usage: + vald [OPTIONS] + +Application Options: + --debuglevel=[trace|debug|info|warn|error|fatal] Logging level for all subsystems (default: info) + --chainname=[babylon] the name of the consumer chain (default: babylon) + --validatorddir= The base directory that contains validator's data, logs, configuration file, etc. (default: + /Users/gurjotsingh/Library/Application Support/Vald) + --configfile= Path to configuration file (default: /Users/gurjotsingh/Library/Application + Support/Vald/vald.conf) + --datadir= The directory to store validator's data within (default: /Users/gurjotsingh/Library/Application + Support/Vald/data) + --logdir= Directory to log output. (default: /Users/gurjotsingh/Library/Application Support/Vald/logs) + --dumpcfg If config file does not exist, create it with current settings + --numPubRand= The number of Schnorr public randomness for each commitment (default: 100) + --numpubrandmax= The upper bound of the number of Schnorr public randomness for each commitment (default: 100) + --minrandheightgap= The minimum gap between the last committed rand height and the current Babylon block height + (default: 10) + --statusupdateinterval= The interval between each update of validator status (default: 5s) + --randomnesscommitinterval= The interval between each attempt to commit public randomness (default: 5s) + --submissionretryinterval= The interval between each attempt to submit finality signature or public randomness after a + failure (default: 1s) + --unbondingsigsubmissioninterval= The interval between each attempt to check and submit unbonding signature (default: 20s) + --maxsubmissionretries= The maximum number of retries to submit finality signature or public randomness (default: 20) + --fastsyncinterval= The interval between each try of fast sync, which is disabled if the value is 0 (default: 20s) + --fastsynclimit= The maximum number of blocks to catch up for each fast sync (default: 10) + --fastsyncgap= The block gap that will trigger the fast sync (default: 6) + --eotsmanageraddress= The address of the remote EOTS manager; Empty if the EOTS manager is running locally (default: + 127.0.0.1:15813) + --bitcoinnetwork=[regtest|testnet|simnet|signet] Bitcoin network to run on (default: simnet) + --covenantmode If the program is running in Covenant mode + --rpclisten= Add an interface/port/socket to listen for RPC connections + +chainpollerconfig: + --chainpollerconfig.buffersize= The maximum number of Babylon blocks that can be stored in the buffer (default: 1000) + --chainpollerconfig.pollinterval= The interval between each polling of Babylon blocks (default: 5s) + +databaseconfig: + --databaseconfig.backend= Possible database to choose as backend (default: bbolt) + --databaseconfig.path= The path that stores the database file (default: bbolt.db) + --databaseconfig.name= The name of the database (default: default) + +eotsmanagerconfig: + --eotsmanagerconfig.dbbackend= Possible database to choose as backend (default: bbolt) + --eotsmanagerconfig.dbpath= The path that stores the database file (default: bbolt-eots.db) + --eotsmanagerconfig.dbname= The name of the database (default: eots-default) + +babylon: + --babylon.key= name of the key to sign transactions with (default: node0) + --babylon.chain-id= chain id of the chain to connect to (default: chain-test) + --babylon.rpc-address= address of the rpc server to connect to (default: http://localhost:26657) + --babylon.grpc-address= address of the grpc server to connect to (default: https://localhost:9090) + --babylon.acc-prefix= account prefix to use for addresses (default: bbn) + --babylon.keyring-type= type of keyring to use (default: test) + --babylon.gas-adjustment= adjustment factor when using gas estimation (default: 1.2) + --babylon.gas-prices= comma separated minimum gas prices to accept for transactions (default: 0.01ubbn) + --babylon.key-dir= directory to store keys in (default: /Users/gurjotsingh/Library/Application Support/Vald/data) + --babylon.debug flag to print debug output + --babylon.timeout= client timeout when doing queries (default: 20s) + --babylon.block-timeout= block timeout when waiting for block events (default: 1m0s) + --babylon.output-format= default output when printint responses (default: json) + --babylon.sign-mode= sign mode to use (default: direct) + +validator: + --validator.staticchainscanningstartheight= The static height from which we start polling the chain (default: 1) + --validator.autochainscanningmode Automatically discover the height from which to start polling the chain + +covenant: + --covenant.covenantkeyname= The key name of the Covenant if the program is running in Covenant mode (default: covenant-key) + --covenant.queryinterval= The interval between each query for pending BTC delegations (default: 15s) + --covenant.delegationlimit= The maximum number of delegations that the Covenant processes each time (default: 100) + --covenant.slashingaddress= The slashing address that the slashed fund is sent to + +Help Options: + -h, --help Show this help message +``` + +**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 `vald.conf` to reference the address of the machine where `eotsd` is running. + +## 3. Interacting with daemons + +### Creating a validator + +Create a BTC Validator named `my_validator` in the internal storage ([bolt db](https://github.com/etcd-io/bbolt)) +This Validator holds a BTC public key (where the staked tokens will be sent to) and a Babylon account +(where the Babylon reward tokens will be sent to). + +```bash +$ valcli daemon create-validator --key-name my-validator --chain-id chain-test + +{ + "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" +} +``` + + +### Registering a validator to Babylon + +Register the Validator with Babylon. Now, the Validator is ready to receive +delegations. The output contains the hash of the validator registration +Babylon transaction. + +```bash +$ valcli daemon register-validator --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba + +{ + "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" +} +``` + +### Querying the validators managed by the daemon + +List all the BTC Validators managed by the BTC Validator daemon. The `status` +field can receive the following values: +- `1`: The Validator is active and has received no delegations yet +- `2`: The Validator is active and has staked BTC tokens +- `3`: The Validator is inactive (i.e. had staked BTC tokens in the past but +not anymore OR has been slashed) +The `last_committed_height` field is the Babylon height up to which the +Validator has committed sufficient EOTS randomness + +```bash +$ valcli daemon list-validators +{ + "validators": [ + ... + { + "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", + "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", + "last_committed_height": 265, + "status": 1 + } + ] +} +``` From 3abf073fd58a2b0bad92a69bbcca6010fd3b9e2f Mon Sep 17 00:00:00 2001 From: Gurjot Singh <111540954+gusin13@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:19:59 -0500 Subject: [PATCH 23/66] docs: Improvements (#152) --- README.md | 103 ++++++++++---- docs/configuration.md | 99 -------------- docs/eotsd/eotsd-config.md | 55 ++++++++ docs/eotsd/eotsd-startup-guide.md | 38 ++++++ docs/interacting-with-daemons.md | 67 ++++++++++ docs/operation.md | 214 ------------------------------ docs/vald/vald-config.md | 79 +++++++++++ docs/vald/vald-startup-guide.md | 36 +++++ 8 files changed, 351 insertions(+), 340 deletions(-) delete mode 100644 docs/configuration.md create mode 100644 docs/eotsd/eotsd-config.md create mode 100644 docs/eotsd/eotsd-startup-guide.md create mode 100644 docs/interacting-with-daemons.md delete mode 100644 docs/operation.md create mode 100644 docs/vald/vald-config.md create mode 100644 docs/vald/vald-startup-guide.md diff --git a/README.md b/README.md index e41f75ae..94ed8f77 100644 --- a/README.md +++ b/README.md @@ -2,51 +2,70 @@ ## 1. Overview -BTC-Validator is a standalone program crafted for the creation and management of BTC validators. -The program includes a CLI functionality for the creation, management, and storage of validator keys, as well as the creation and registration of validators on the consumer chain. +BTC-Validator is a standalone program crafted for the creation and management of BTC +validators. The program includes a CLI functionality for the creation, management, +and storage of validator keys, as well as the creation and registration of validators +on the consumer chain. -Once a validator is registered on the chain, BTC-Validator consistently polls for new blocks. It actively engages -with the blockchain by sending finality signatures and committing public randomness at regular intervals. +Once a validator is registered on the chain, BTC-Validator consistently polls for new +blocks. It actively engages with the blockchain by sending finality signatures and +committing public randomness at regular intervals. -The program consists of two essential components: the **EOTS manager Daemon** and the **Validator Daemon**. +The program consists of two essential components: the **EOTS manager Daemon** and the +**Validator Daemon**. #### 1. EOTS Manager Daemon -The EOTS Daemon is responsible for managing EOTS keys, producing EOTS randomness -and 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). +The EOTS Daemon is responsible for managing EOTS keys, producing EOTS randomness and +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). +The BTC validator will commit a unique EOTS randomness at each future height it needs +to vote. If the BTC validator votes for two blocks using the same committed EOTS +randomness, then its secret key will be extracted and all of its BTC delegations will +be slashed on Bitcoin, ensuring slashable safety. 1. **EOTS Key Management:** - - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs for the validator using the - [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) standard. - - Persists generated key pairs in the internal [bolt db](https://github.com/etcd-io/bbolt) storage. + - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs + for the validator using the + [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) + standard. + - Persists generated key pairs in the + internal [bolt db](https://github.com/etcd-io/bbolt) storage. 2. **Randomness Generation:** - - Generates lists of [Schnorr randomness pairs](https://www.researchgate.net/publication/222835548_Schnorr_Randomness) based on the EOTS key, chainID, and block height. + - 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 validator and corresponding secret randomness for a given chain at a specified height. + - Signs EOTS using the private key of the validator and corresponding secret + randomness for a given chain at a specified height. - Signs Schnorr signatures using the private key of the validator. #### 2. Validator Daemon -The Validator Daemon is responsible for finality signatures and randomness commitment. +The Validator Daemon is responsible for committing public randomness and submitting +finality signatures. 1. **Finality Signatures:** - - Sends the finality signature to the consumer chain (Babylon) for each registered validator and for each block there's an EOTS randomness commitment. + - Sends the finality signature to the consumer chain (Babylon) for each + registered validator and for each block there's an EOTS randomness commitment. 2. **EOTS Randomness Commitment:** - - Ensures the generation of EOTS randomness commitment on the Babylon ledger for each block the BTC validator intends to vote for. + - Ensures the generation of EOTS randomness commitment on the Babylon ledger for + each block the BTC validator intends to vote for. ## 2. Installation #### Prerequisites -This project requires Go version 1.20 or later. +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). +Install Go by following the instructions on +the [official Go installation guide](https://golang.org/doc/install). #### Downloading the code @@ -56,7 +75,8 @@ To get started, clone the repository to your local machine from Github: $ git clone git@github.com:babylonchain/btc-validator.git ``` -You can choose a specific version from the [official releases page](https://github.com/babylonchain/btc-validator/releases) +You can choose a specific version from +the [official releases page](https://github.com/babylonchain/btc-validator/releases) ```bash $ cd btc-validator # cd into the project directory @@ -65,13 +85,32 @@ $ git checkout #### Building and installing the binary +```bash +# cd into the project directory +$ cd btc-validator + +# installs the compiled binaries to your +# $GOPATH/bin directory allowing access +# from anywhere on your system +$ make install +``` + +The above will produce the following binaries: + +- `eotsd`: The daemon program for the EOTS manager. +- `eotcli`: The CLI tool for interacting with the EOTS daemon. +- `vald`: The daemon program for the btc-validator. +- `valcli`: The CLI tool for interacting with the btc-validator daemon. + +To build locally, + ```bash $ cd btc-validator # cd into the project directory -$ make build # build the binaries in the build directory -$ make install # installs the compiled binaries to your $GOPATH/bin directory allowing access from anywhere on your system +$ make build ``` -The build directory has the following structure +The above will lead to a build directory having the following structure: + ```bash $ ls build ├── eotcli @@ -80,8 +119,18 @@ $ ls build └── vald ``` -## 3. Configuration -Follow the [configuration guide](docs/configuration.md). +## 3. EOTS Daemon Configuration + +Follow the [eots configuration guide](docs/eotsd/eotsd-config.md). + +## 4. Starting the EOTS Daemon + +Follow the [eots startup guide](docs/eotsd/eotsd-startup-guide.md). + +## 5. Validator Daemon Configuration + +Follow the [vald configuration guide](docs/vald/vald-config.md). + +## 6. Starting the Validator Daemon -## 4. Running the BTC Validator Program -Follow the [operations guide](docs/operation.md). +Follow the [vald startup guide](docs/vald/vald-startup-guide.md). diff --git a/docs/configuration.md b/docs/configuration.md deleted file mode 100644 index dfbd714b..00000000 --- a/docs/configuration.md +++ /dev/null @@ -1,99 +0,0 @@ -# Configuration - -### Using `valcli` and `eotscli` for Daemon Configuration - -The `valcli` and `eotscli` tools serve as control planes for the Validator Daemon (`vald`) and EOTS Daemon (`eotsd`) -respectively. These tools allow you to configure various settings and parameters. Let's explore how to configure the -daemons. - -### Dumping Default Configuration - -The `dump-config` command dumps the default configuration for the daemon. - -```bash -$ valcli admin dump-config --help -NAME: - valcli admin dump-config - Dump default configuration file. - -USAGE: - valcli admin dump-config [command options] [arguments...] - -OPTIONS: - --config-file-dir value Path to where the default config file will be dumped (default: "~/Library/Application Support/Vald/vald.conf") -``` - -### 1. Validator daemon (`vald`) config: - -```bash -$ valcli admin dump-config -``` - -This will create a ```vald.conf``` file in the default config directory. The default config directories are: - -```bash -MacOS ~/Library/Application Support/Vald -Linux ~/.Vald -Windows C:\Users\\AppData\Local\Vald -``` - -You can also specify a custom path to store the config - -```bash -$ valcli admin dump-config --config-file-dir /path/to/your/config/dir/ -``` - -After dump the config directory has the following structure - -```bash -$ ls /path/to/your/config/dir/Vald - ├── data # Contains Vald-specific data. - ├── logs # Contains logs generated by Vald. - └── vald.conf # Vald-specific configuration file. -``` - -Lets explore some of the important parameters in the `vald.conf` file. - -```bash -# Address of the EOTS Daemon: -EOTSManagerAddress = 127.0.0.1:15813 - -# Babylon specific parameters - -# Name of the key in the keyring to use for signing transactions: -Key = node0 - -# Address of the RPC server: -RPCAddr = http://localhost:26657 -``` - -**Note:** The `Key` parameter is the name of the key in the keyring to use for signing transactions. -You can create a key and request funds from the faucet by following the instructions in the [Babylon -documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds) - -```bash -# to change the babylon rpc address you can set -RPCAddr = https://rpc.devnet.babylonchain.io:443 -``` - -### 2. EOTS daemon (`eotsd`) config : - -```bash -$ eotscli admin dump-config -``` - -After dump the config directory has following structure - -```bash -$ ls /path/to/your/config/dir/Eotsd - ├── eotsd.conf # Eotsd-specific configuration file. -``` - -Lets explore some of the important parameters in the `eotsd.conf` file. - -```bash -# Path to EOTSD configuration file -ConfigFile = /Users/John/Library/Application Support/Eotsd/eotsd.conf - -# Default address to listen for RPC connections: -RpcListener = localhost:15813 -``` diff --git a/docs/eotsd/eotsd-config.md b/docs/eotsd/eotsd-config.md new file mode 100644 index 00000000..35895132 --- /dev/null +++ b/docs/eotsd/eotsd-config.md @@ -0,0 +1,55 @@ +## EOTS daemon (`eotsd`) configuration: + +The `eotscli` tool serves as a control plane for the EOTS Daemon (`eotsd`). Below, +instructions are provided for configuring the `eotsd` daemon. + +The `eotscli admin dump-config` 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 `--config-file-dir` flag. + +```bash +$ eotscli admin dump-config --config-file-dir /path/to/eotsd-home/ +``` + +After initialization, the home directory will have the following structure + +```bash +$ ls /path/to/eotsd-home/ + ├── eotsd.conf # Eotsd-specific configuration file. +``` + +If the `--config-file-dir` flag is not specified, then the default home location will +be used. For different operating systems, those are: + +- **MacOS** `~/Library/Application Support/Eotsd` +- **Linux** `~/.Eotsd` +- **Windows** `C:\Users\\AppData\Local\Eotsd` + +Below are some of the important parameters in the `eotsd.conf` file. + +```bash +# Path to EOTSD configuration file +ConfigFile = /Users//Library/Application Support/Eotsd/eotsd.conf + +# Default address to listen for RPC connections +RpcListener = localhost:15813 + +# Directory to store EOTS manager keys +KeyDirectory = /Users//Library/Application Support/Eotsd/data + +# Type of keyring to use, +# supported backends - (os|file|kwallet|pass|test|memory) +# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring +KeyringBackend = file + +# Possible database to choose as backend +Backend = bbolt + +# Path to the database +Path = bbolt-eots.db + +# Name of the database +Name = default +``` + +To see the complete list of configuration options, check the `eotsd.conf` file. diff --git a/docs/eotsd/eotsd-startup-guide.md b/docs/eotsd/eotsd-startup-guide.md new file mode 100644 index 00000000..343d4ac3 --- /dev/null +++ b/docs/eotsd/eotsd-startup-guide.md @@ -0,0 +1,38 @@ +## Prerequisites + +1. **Install Binaries:** + Follow the instructions in + the [installation section](../../README.md#2-installation) to install the required + binaries. + +2. **EOTS Daemon Configuration:** + Follow the instructions in the [EOTS Daemon Configuration](eotsd-config.md) guide + to configure the EOTS daemon. + +## Starting the EOTS Daemon + +You can start the EOTS daemon using the following command: + +```bash +$ eotsd +``` + +This will start the rpc server at the address specified in the configuration under +the `RpcListener` field. It can also be overridden with custom address using +the `--rpclistener` flag. + +```bash +$ eotsd --rpclistener 'localhost:8081' + +time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" +time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager 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. + +**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 `vald.conf` to reference the address of the machine +where `eotsd` is running. diff --git a/docs/interacting-with-daemons.md b/docs/interacting-with-daemons.md new file mode 100644 index 00000000..923612a6 --- /dev/null +++ b/docs/interacting-with-daemons.md @@ -0,0 +1,67 @@ +# Interacting with daemons + +Before proceeding, make sure you have installed the required binaries, configured and +started both EOTS and the BTC validator daemon. + +- [Starting the EOTS daemon](./eotsd/startup-guide.md) +- [Starting the BTC validator daemon](./vald/startup-guide.md) + +The following guide will show how to interact with the daemons to create a BTC +validator and register it to Babylon. + +### 1. Creating a BTC validator + +A BTC Validator named `my_validator` can be created in the internal +storage ([bolt db](https://github.com/etcd-io/bbolt)) +through the `valcli daemon create-validator` command. This validator is associated +with a BTC public key, serving as its unique identifier, and a Babylon account to +which staking rewards will be directed. + +```bash +$ valcli daemon create-validator --key-name my-validator --chain-id chain-test +--passphrase mypassphrase +{ + "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" +} +``` + +### 2. Registering a validator to Babylon + +The BTC validator can be registered with Babylon through the `register-validator` +command. The output contains the hash of the validator registration Babylon +transaction. + +```bash +$ valcli daemon register-validator --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba +{ + "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" +} +``` + +### 3. Querying the validators managed by the daemon + +The BTC validators that are managed by the daemon can be listed through the +`valcli daemon list-validators` command. The `status` field can receive the following +values: + +- `1`: The Validator is active and has received no delegations yet +- `2`: The Validator is active and has staked BTC tokens +- `3`: The Validator is inactive (i.e. had staked BTC tokens in the past but not + anymore OR has been slashed) + The `last_committed_height` field is the Babylon height up to which the Validator + has committed sufficient EOTS randomness + +```bash +$ valcli daemon list-validators +{ + "validators": [ + ... + { + "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", + "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", + "last_committed_height": 265, + "status": 1 + } + ] +} +``` diff --git a/docs/operation.md b/docs/operation.md deleted file mode 100644 index b635fc77..00000000 --- a/docs/operation.md +++ /dev/null @@ -1,214 +0,0 @@ -# Operations - -Before you proceed, ensure that you have installed the necessary binaries and configured the daemons. If you haven't done so yet, please follow these steps: - -- [Installation](../README.md#2-installation) -- [Configuration](configuration.md) - -## 1. Starting the EOTS Daemon -You can start the EOTS daemon using the following command: - -```bash -$ eotsd -``` -This will start the rpc server at the default address i.e. `localhost:15813`. You can also specify a custom address using the `--rpclistener` flag. - -```bash -$ eotsd --rpclistener 'localhost:8081' - -time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" -time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager 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. - -```bash -$ eotsd --help - -Usage: - eotsd [OPTIONS] - -Application Options: - --loglevel=[trace|debug|info|warn|error|fatal] Logging level for all subsystems (default: debug) - --workdir= The base directory that contains the EOTS manager's data, logs, configuration file, etc. (default: - /Users/gurjotsingh/Library/Application Support/Eotsd) - --configfile= Path to configuration file (default: /Users/gurjotsingh/Library/Application - Support/Eotsd/eotsd.conf) - --datadir= The directory to store validator's data within (default: /Users/gurjotsingh/Library/Application - Support/Eotsd/data) - --logdir= Directory to log output. (default: /Users/gurjotsingh/Library/Application Support/Eotsd/logs) - --dumpcfg If config file does not exist, create it with current settings - --key-dir= Directory to store keys in (default: /Users/gurjotsingh/Library/Application Support/Eotsd/data) - --keyring-type= Type of keyring to use (default: file) - --backend= Possible database to choose as backend (default: bbolt) - --path= The path that stores the database file (default: bbolt-eots.db) - --name= The name of the database (default: default) - --rpclistener= the listener for RPC connections, e.g., localhost:1234 (default: localhost:15813) - -Help Options: - -h, --help Show this help message -``` - -## 2. Starting the Validator Daemon - -You can start the validator daemon using the following command: - -```bash -$ vald -``` -This will start the rpc server at the default port i.e. `15812`. You can also specify a custom port using -the `--rpclisten` flag. - -```bash -$ vald --rpclisten '8082' - -time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" -time="2023-11-26T16:37:00-05:00" level=info msg="Starting ValidatorApp" -time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" -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 on 127.0.0.1:8082" -time="2023-11-26T16:37:00-05:00" level=info msg="BTC Validator 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. - -```bash -$ vald --help - -Usage: - vald [OPTIONS] - -Application Options: - --debuglevel=[trace|debug|info|warn|error|fatal] Logging level for all subsystems (default: info) - --chainname=[babylon] the name of the consumer chain (default: babylon) - --validatorddir= The base directory that contains validator's data, logs, configuration file, etc. (default: - /Users/gurjotsingh/Library/Application Support/Vald) - --configfile= Path to configuration file (default: /Users/gurjotsingh/Library/Application - Support/Vald/vald.conf) - --datadir= The directory to store validator's data within (default: /Users/gurjotsingh/Library/Application - Support/Vald/data) - --logdir= Directory to log output. (default: /Users/gurjotsingh/Library/Application Support/Vald/logs) - --dumpcfg If config file does not exist, create it with current settings - --numPubRand= The number of Schnorr public randomness for each commitment (default: 100) - --numpubrandmax= The upper bound of the number of Schnorr public randomness for each commitment (default: 100) - --minrandheightgap= The minimum gap between the last committed rand height and the current Babylon block height - (default: 10) - --statusupdateinterval= The interval between each update of validator status (default: 5s) - --randomnesscommitinterval= The interval between each attempt to commit public randomness (default: 5s) - --submissionretryinterval= The interval between each attempt to submit finality signature or public randomness after a - failure (default: 1s) - --unbondingsigsubmissioninterval= The interval between each attempt to check and submit unbonding signature (default: 20s) - --maxsubmissionretries= The maximum number of retries to submit finality signature or public randomness (default: 20) - --fastsyncinterval= The interval between each try of fast sync, which is disabled if the value is 0 (default: 20s) - --fastsynclimit= The maximum number of blocks to catch up for each fast sync (default: 10) - --fastsyncgap= The block gap that will trigger the fast sync (default: 6) - --eotsmanageraddress= The address of the remote EOTS manager; Empty if the EOTS manager is running locally (default: - 127.0.0.1:15813) - --bitcoinnetwork=[regtest|testnet|simnet|signet] Bitcoin network to run on (default: simnet) - --covenantmode If the program is running in Covenant mode - --rpclisten= Add an interface/port/socket to listen for RPC connections - -chainpollerconfig: - --chainpollerconfig.buffersize= The maximum number of Babylon blocks that can be stored in the buffer (default: 1000) - --chainpollerconfig.pollinterval= The interval between each polling of Babylon blocks (default: 5s) - -databaseconfig: - --databaseconfig.backend= Possible database to choose as backend (default: bbolt) - --databaseconfig.path= The path that stores the database file (default: bbolt.db) - --databaseconfig.name= The name of the database (default: default) - -eotsmanagerconfig: - --eotsmanagerconfig.dbbackend= Possible database to choose as backend (default: bbolt) - --eotsmanagerconfig.dbpath= The path that stores the database file (default: bbolt-eots.db) - --eotsmanagerconfig.dbname= The name of the database (default: eots-default) - -babylon: - --babylon.key= name of the key to sign transactions with (default: node0) - --babylon.chain-id= chain id of the chain to connect to (default: chain-test) - --babylon.rpc-address= address of the rpc server to connect to (default: http://localhost:26657) - --babylon.grpc-address= address of the grpc server to connect to (default: https://localhost:9090) - --babylon.acc-prefix= account prefix to use for addresses (default: bbn) - --babylon.keyring-type= type of keyring to use (default: test) - --babylon.gas-adjustment= adjustment factor when using gas estimation (default: 1.2) - --babylon.gas-prices= comma separated minimum gas prices to accept for transactions (default: 0.01ubbn) - --babylon.key-dir= directory to store keys in (default: /Users/gurjotsingh/Library/Application Support/Vald/data) - --babylon.debug flag to print debug output - --babylon.timeout= client timeout when doing queries (default: 20s) - --babylon.block-timeout= block timeout when waiting for block events (default: 1m0s) - --babylon.output-format= default output when printint responses (default: json) - --babylon.sign-mode= sign mode to use (default: direct) - -validator: - --validator.staticchainscanningstartheight= The static height from which we start polling the chain (default: 1) - --validator.autochainscanningmode Automatically discover the height from which to start polling the chain - -covenant: - --covenant.covenantkeyname= The key name of the Covenant if the program is running in Covenant mode (default: covenant-key) - --covenant.queryinterval= The interval between each query for pending BTC delegations (default: 15s) - --covenant.delegationlimit= The maximum number of delegations that the Covenant processes each time (default: 100) - --covenant.slashingaddress= The slashing address that the slashed fund is sent to - -Help Options: - -h, --help Show this help message -``` - -**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 `vald.conf` to reference the address of the machine where `eotsd` is running. - -## 3. Interacting with daemons - -### Creating a validator - -Create a BTC Validator named `my_validator` in the internal storage ([bolt db](https://github.com/etcd-io/bbolt)) -This Validator holds a BTC public key (where the staked tokens will be sent to) and a Babylon account -(where the Babylon reward tokens will be sent to). - -```bash -$ valcli daemon create-validator --key-name my-validator --chain-id chain-test - -{ - "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" -} -``` - - -### Registering a validator to Babylon - -Register the Validator with Babylon. Now, the Validator is ready to receive -delegations. The output contains the hash of the validator registration -Babylon transaction. - -```bash -$ valcli daemon register-validator --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba - -{ - "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" -} -``` - -### Querying the validators managed by the daemon - -List all the BTC Validators managed by the BTC Validator daemon. The `status` -field can receive the following values: -- `1`: The Validator is active and has received no delegations yet -- `2`: The Validator is active and has staked BTC tokens -- `3`: The Validator is inactive (i.e. had staked BTC tokens in the past but -not anymore OR has been slashed) -The `last_committed_height` field is the Babylon height up to which the -Validator has committed sufficient EOTS randomness - -```bash -$ valcli daemon list-validators -{ - "validators": [ - ... - { - "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", - "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", - "last_committed_height": 265, - "status": 1 - } - ] -} -``` diff --git a/docs/vald/vald-config.md b/docs/vald/vald-config.md new file mode 100644 index 00000000..9e9d1711 --- /dev/null +++ b/docs/vald/vald-config.md @@ -0,0 +1,79 @@ +## Prerequisites + +#### Create a Babylon keyring with funds + +The `vald` daemon requires a keyring with loaded funds to pay for the transactions. +These transactions include randomness commits and vote submissions. Follow this +guide [Getting Testnet Tokens](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds) +to create a keyring and request funds. + +## Validator daemon (`vald`) configuration + +The `valcli` tools serves as a control plane for the Validator Daemon (`vald`). +Below, instructions are provided for configuring the daemons. + +The `valcli admin dump-config` command initializes a home directory for the BTC +validator daemon. This directory is created in the default home location or in a +location specified by the `--config-file-dir` flag. + +```bash +$ valcli admin dump-config --config-file-dir /path/to/vald-home/ +``` + +After initialization, the home directory will have the following structure + +```bash +$ ls /path/to/vald-home/ + ├── vald.conf # Vald-specific configuration file. +``` + +If the `--config-file-dir` flag is not specified, then the default home directory +will be used. For different operating systems, those are: + +- **MacOS** `~/Library/Application Support/Vald` +- **Linux** `~/.Vald` +- **Windows** `C:\Users\\AppData\Local\Vald` + +Below are some important parameters of the `vald.conf` file. + +**Note:** + +The `Key` parameter in the config below is the name of the key in the keyring to use +for signing transactions. Use the key name you created +in [Create a Babylon keyring with funds](#create-a-babylon-keyring-with-funds) + +```bash +# Address of the EOTS Daemon +EOTSManagerAddress = 127.0.0.1:15813 + +# Babylon specific parameters + +# Chain id of the chain (Babylon) +ChainID = chain-test + +# Address of the chain's RPC server (Babylon) +RPCAddr = http://localhost:26657 + +# Address of the chain's GRPC server (Babylon) +GRPCAddr = https://localhost:9090 + +# Name of the key in the keyring to use for signing transactions +Key = node0 + +# Type of keyring to use, +# supported backends - (os|file|kwallet|pass|test|memory) +# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring +KeyringBackend = test + +# Directory to store validator keys in +KeyDirectory = /Users//Library/Application Support/Vald/data +``` + +To change the babylon rpc/grpc address, you can set + +```bash +RPCAddr = https://rpc.devnet.babylonchain.io:443 +GRPCAddr = https://grpc.devnet.babylonchain.io:443 +``` + +To see the complete list of configuration options, check the `vald.conf` file. diff --git a/docs/vald/vald-startup-guide.md b/docs/vald/vald-startup-guide.md new file mode 100644 index 00000000..ad059595 --- /dev/null +++ b/docs/vald/vald-startup-guide.md @@ -0,0 +1,36 @@ +## Prerequisites + +1. **Install Binaries:** + Follow the instructions in + the [installation section](../../README.md#2-installation) to install the required + binaries. + +2. **Validator Daemon Configuration:** + Follow the instructions in the [Validator Daemon Configuration](vald-config.md) + guide to configure the validator daemon. + +## Starting the Validator Daemon + +You can start the validator daemon using the following command: + +```bash +$ vald +``` + +This will start the RPC server at the address specified in the configuration under +the `RawRPCListeners` field. A custom address can also be specified using +the `--rpclisten` flag. + +```bash +$ vald --rpclisten 'localhost:8082' + +time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" +time="2023-11-26T16:37:00-05:00" level=info msg="Starting ValidatorApp" +time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" +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 on 127.0.0.1:8082" +time="2023-11-26T16:37:00-05:00" level=info msg="BTC Validator 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. From fdc9cb3424f18fa44aead860127434d5446be5c4 Mon Sep 17 00:00:00 2001 From: Filippos Malandrakis <35352222+filippos47@users.noreply.github.com> Date: Fri, 1 Dec 2023 13:23:39 +0200 Subject: [PATCH 24/66] CI: Push images for covenant (#156) --- .circleci/config.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 19b24a59..7bf0b6b2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,14 @@ jobs: tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "eotsmanager" extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" + - aws-ecr/build-image: + push-image: false + dockerfile: Dockerfile + path: ./covenant + build-path: ./ + tag: "$CIRCLE_SHA1,$CIRCLE_TAG" + repo: "covenant" + extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - run: name: Save Docker image to export it to workspace command: | @@ -97,6 +105,11 @@ jobs: region: "$AWS_REGION" repo: "eotsmanager" tag: "$CIRCLE_SHA1,$CIRCLE_TAG" + - aws-ecr/push-image: + registry-id: AWS_ECR_REGISTRY_ID + region: "$AWS_REGION" + repo: "covenant" + tag: "$CIRCLE_SHA1,$CIRCLE_TAG" workflows: CI: From 3b55f4cb7106816f6c0527e7dc18b33d7625490a Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 4 Dec 2023 12:02:18 +0800 Subject: [PATCH 25/66] Chore: Bump Babylon version and use rpc-client to replace cosmos provider (#149) --- .circleci/config.yml | 6 +- Dockerfile | 4 +- Makefile | 6 +- clientcontroller/babylon.go | 616 ++++++--------------- clientcontroller/interface.go | 29 +- clientcontroller/retry_utils.go | 37 +- cmd/valcli/daemoncmd.go | 13 +- covenant/Dockerfile | 4 +- covenant/cmd/covcli/new.go | 4 +- covenant/cmd/covd/start.go | 2 +- covenant/covenant.go | 295 ++++++---- covenant/covenant_test.go | 162 +++++- eotsmanager/Dockerfile | 4 +- go.mod | 326 +++++------ go.sum | 850 ++++++++++++----------------- itest/babylon_node_handler.go | 4 - itest/e2e_test.go | 78 ++- itest/test_manager.go | 200 ++++--- proto/validators.pb.go | 393 +++++++------ proto/validators.proto | 31 +- service/app.go | 16 +- service/app_test.go | 4 +- service/client/rpcclient.go | 21 +- service/event_loop.go | 2 +- service/fastsync_test.go | 2 +- service/rpcserver.go | 2 +- service/types.go | 22 +- service/validator_instance.go | 188 +------ service/validator_instance_test.go | 4 +- service/validator_manager.go | 3 +- service/validator_manager_test.go | 4 +- testutil/datagen.go | 42 +- testutil/mocks/babylon.go | 104 +--- testutil/utils.go | 14 +- tools/go.mod | 135 ++--- tools/go.sum | 79 +++ types/delegation.go | 96 +++- types/errors.go | 17 - types/key.go | 8 + types/params.go | 16 +- val/keyringcontroller.go | 22 +- val/keyringcontroller_test.go | 4 +- val/valstore.go | 5 +- valcfg/babylon.go | 61 ++- 44 files changed, 1736 insertions(+), 2199 deletions(-) delete mode 100644 types/errors.go create mode 100644 types/key.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 7bf0b6b2..0fe66ad8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,7 @@ jobs: resource_class: large steps: - go/install: - version: "1.20" + version: "1.21.4" - checkout - run: name: Print Go environment @@ -29,8 +29,8 @@ jobs: - run: name: Lint command: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.52.2 - ./bin/golangci-lint run + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.55.2 + ./bin/golangci-lint run --timeout 5m0s - run: name: Run tests command: | diff --git a/Dockerfile b/Dockerfile index 1d5fceb8..4a0d4d85 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.5-alpine as builder +FROM golang:1.21.4-alpine as builder # Version to build. Default is the Git HEAD. ARG VERSION="HEAD" @@ -14,7 +14,7 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/babylon-private +ENV GOPRIVATE=github.com/babylonchain/* # Build WORKDIR /go/src/github.com/babylonchain/btc-validator diff --git a/Makefile b/Makefile index 7ffbe17c..78ef8490 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ BUILDDIR ?= $(CURDIR)/build TOOLS_DIR := tools -BTCD_PKG := github.com/btcsuite/btcd BABYLON_PKG := github.com/babylonchain/babylon/cmd/babylond GO_BIN := ${GOPATH}/bin @@ -35,9 +34,6 @@ all: build install build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) -clean: - rm -rf $(BUILDDIR) - $(BUILD_TARGETS): go.sum $(BUILDDIR)/ go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... @@ -48,7 +44,7 @@ build-docker: $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ $(shell git rev-parse --show-toplevel) -.PHONY: build build-docker clean +.PHONY: build build-docker test: go test ./... diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 3d48cdc8..e0823dfc 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,40 +2,29 @@ package clientcontroller import ( "context" + "encoding/hex" "fmt" "math/big" - "os" - "path" - "strings" - "sync" "time" "cosmossdk.io/math" - "github.com/avast/retry-go/v4" - bbnapp "github.com/babylonchain/babylon/app" 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" finalitytypes "github.com/babylonchain/babylon/x/finality/types" + bbnclient "github.com/babylonchain/rpc-client/client" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" sdkquery "github.com/cosmos/cosmos-sdk/types/query" sttypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/provider" - pv "github.com/cosmos/relayer/v2/relayer/provider" - zaplogfmt "github.com/jsternberg/zap-logfmt" - "github.com/juju/fslock" "github.com/sirupsen/logrus" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "sigs.k8s.io/yaml" "github.com/babylonchain/btc-validator/types" "github.com/babylonchain/btc-validator/valcfg" @@ -44,121 +33,89 @@ import ( var _ ClientController = &BabylonController{} type BabylonController struct { - provider *cosmos.CosmosProvider - logger *logrus.Logger - timeout time.Duration -} - -func newRootLogger(format string, debug bool) (*zap.Logger, error) { - config := zap.NewProductionEncoderConfig() - config.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { - encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00")) - } - config.LevelKey = "lvl" - - var enc zapcore.Encoder - switch format { - case "json": - enc = zapcore.NewJSONEncoder(config) - case "auto", "console": - enc = zapcore.NewConsoleEncoder(config) - case "logfmt": - enc = zaplogfmt.NewEncoder(config) - default: - return nil, fmt.Errorf("unrecognized log format %q", format) - } - - level := zap.InfoLevel - if debug { - level = zap.DebugLevel - } - return zap.New(zapcore.NewCore( - enc, - os.Stderr, - level, - )), nil + bbnClient *bbnclient.Client + cfg *valcfg.BBNConfig + btcParams *chaincfg.Params + logger *logrus.Logger } func NewBabylonController( - homedir string, cfg *valcfg.BBNConfig, + btcParams *chaincfg.Params, logger *logrus.Logger, ) (*BabylonController, error) { - zapLogger, err := newRootLogger("console", true) - if err != nil { - return nil, err - } + bbnConfig := valcfg.BBNConfigToBabylonConfig(cfg) - // HACK: replace the modules in public rpc-client to add BTC staking / finality modules - // so that it recognises their message formats - // TODO: fix this either by fixing rpc-client side - var moduleBasics []module.AppModuleBasic - for _, mbasic := range bbnapp.ModuleBasics { - moduleBasics = append(moduleBasics, mbasic) + if err := bbnConfig.Validate(); err != nil { + return nil, fmt.Errorf("invalid config for Babylon client: %w", err) } - cosmosConfig := valcfg.BBNConfigToCosmosProviderConfig(cfg) - - cosmosConfig.Modules = moduleBasics - - provider, err := cosmosConfig.NewProvider( - zapLogger, - homedir, - true, - "babylon", + bc, err := bbnclient.New( + &bbnConfig, + logger, ) - if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create Babylon client: %w", err) } - cp := provider.(*cosmos.CosmosProvider) + return &BabylonController{ + bc, + cfg, + btcParams, + logger, + }, nil +} + +func (bc *BabylonController) mustGetTxSigner() string { + signer := bc.GetKeyAddress() + prefix := bc.cfg.AccountPrefix + return sdk.MustBech32ifyAddressBytes(prefix, signer) +} - cp.PCfg.KeyDirectory = cfg.KeyDirectory - // Need to override this manually as otherwise oprion from config is ignored - cp.Cdc = cosmos.MakeCodec(moduleBasics, []string{}) +func (bc *BabylonController) GetKeyAddress() sdk.AccAddress { + // get key address, retrieves address based on key name which is configured in + // cfg *stakercfg.BBNConfig. If this fails, it means we have misconfiguration problem + // and we should panic. + // This is checked at the start of BabylonController, so if it fails something is really wrong - err = cp.Init(context.Background()) + keyRec, err := bc.bbnClient.GetKeyring().Key(bc.cfg.Key) if err != nil { - return nil, err + panic(fmt.Sprintf("Failed to get key address: %s", err)) } - return &BabylonController{ - cp, - logger, - cfg.Timeout, - }, nil -} + addr, err := keyRec.GetAddress() -func (bc *BabylonController) MustGetTxSigner() string { - address, err := bc.provider.Address() if err != nil { - panic(err) + panic(fmt.Sprintf("Failed to get key address: %s", err)) } - return address + + return addr } func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - queryCkptClient := btcctypes.NewQueryClient(bc.provider) - - ckptQueryRequest := &btcctypes.QueryParamsRequest{} - ckptParamRes, err := queryCkptClient.Params(ctx, ckptQueryRequest) + // query btc checkpoint params + ckptParamRes, err := bc.bbnClient.QueryClient.BTCCheckpointParams() if err != nil { return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err) } - queryStakingClient := btcstakingtypes.NewQueryClient(bc.provider) - stakingQueryRequest := &btcstakingtypes.QueryParamsRequest{} - stakingParamRes, err := queryStakingClient.Params(ctx, stakingQueryRequest) + // query btc staking params + stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParams() if err != nil { return nil, fmt.Errorf("failed to query staking params: %v", err) } - covenantPk, err := stakingParamRes.Params.CovenantPk.ToBTCPK() + + covenantPks := make([]*btcec.PublicKey, 0, len(stakingParamRes.Params.CovenantPks)) + for _, pk := range stakingParamRes.Params.CovenantPks { + covPk, err := pk.ToBTCPK() + if err != nil { + return nil, fmt.Errorf("invalida covenant public key") + } + covenantPks = append(covenantPks, covPk) + } + slashingAddress, err := btcutil.DecodeAddress(stakingParamRes.Params.SlashingAddress, bc.btcParams) if err != nil { return nil, err } @@ -167,9 +124,10 @@ func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), - CovenantPk: covenantPk, - SlashingAddress: stakingParamRes.Params.SlashingAddress, - MinCommissionRate: stakingParamRes.Params.MinCommissionRate.String(), + CovenantPks: covenantPks, + SlashingAddress: slashingAddress, + CovenantQuorum: stakingParamRes.Params.CovenantQuorum, + SlashingRate: stakingParamRes.Params.SlashingRate, }, nil } @@ -178,90 +136,12 @@ func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxRe } func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { - var ( - rlyResp *provider.RelayerTxResponse - callbackErr error - wg sync.WaitGroup + return bc.bbnClient.ReliablySendMsgs( + context.Background(), + msgs, + expectedErrors, + unrecoverableErrors, ) - - callback := func(rtr *provider.RelayerTxResponse, err error) { - rlyResp = rtr - callbackErr = err - wg.Done() - } - - wg.Add(1) - - // convert message type - relayerMsgs := []pv.RelayerMessage{} - for _, m := range msgs { - relayerMsg := cosmos.NewCosmosMessage(m, func(signer string) {}) - relayerMsgs = append(relayerMsgs, relayerMsg) - } - - ctx := context.Background() - if err := retry.Do(func() error { - var sendMsgErr error - krErr := bc.accessKeyWithLock(func() { - sendMsgErr = bc.provider.SendMessagesToMempool(ctx, relayerMsgs, "", ctx, []func(*provider.RelayerTxResponse, error){callback}) - }) - if krErr != nil { - bc.logger.WithFields(logrus.Fields{ - "error": krErr, - }).Error("unrecoverable err when submitting the tx, skip retrying") - return retry.Unrecoverable(krErr) - } - if sendMsgErr != nil { - sendMsgErr = ConvertErrType(sendMsgErr) - if IsUnrecoverable(sendMsgErr) { - bc.logger.WithFields(logrus.Fields{ - "error": sendMsgErr, - }).Error("unrecoverable err when submitting the tx, skip retrying") - return retry.Unrecoverable(sendMsgErr) - } - if IsExpected(sendMsgErr) { - // this is necessary because if err is returned - // the callback function will not be executed so - // that the inside wg.Done will not be executed - wg.Done() - bc.logger.WithFields(logrus.Fields{ - "error": sendMsgErr, - }).Error("expected err when submitting the tx, skip retrying") - return nil - } - return sendMsgErr - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - bc.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": rtyAttNum, - "error": err, - }).Error() - })); err != nil { - return nil, err - } - - wg.Wait() - - if callbackErr != nil { - callbackErr = ConvertErrType(callbackErr) - if IsExpected(callbackErr) { - return nil, nil - } - return nil, callbackErr - } - - if rlyResp == nil { - // this case could happen if the error within the retry is an expected error - return nil, nil - } - - if rlyResp.Code != 0 { - return rlyResp, fmt.Errorf("transaction failed with code: %d", rlyResp.Code) - } - - return rlyResp, nil } // RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon @@ -271,7 +151,7 @@ func (bc *BabylonController) RegisterValidator( valPk *btcec.PublicKey, pop []byte, commission *big.Int, - description string, + description []byte, ) (*types.TxResponse, error) { var bbnPop btcstakingtypes.ProofOfPossession if err := bbnPop.Unmarshal(pop); err != nil { @@ -281,12 +161,12 @@ func (bc *BabylonController) RegisterValidator( sdkCommission := math.LegacyNewDecFromBigInt(commission) var sdkDescription sttypes.Description - if err := yaml.Unmarshal([]byte(description), &sdkDescription); err != nil { - return nil, fmt.Errorf("invalid descirption: %w", err) + if err := sdkDescription.Unmarshal(description); err != nil { + return nil, fmt.Errorf("invalid description: %w", err) } msg := &btcstakingtypes.MsgCreateBTCValidator{ - Signer: bc.MustGetTxSigner(), + Signer: bc.mustGetTxSigner(), BabylonPk: &secp256k1.PubKey{Key: chainPk}, BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), Pop: &bbnPop, @@ -319,7 +199,7 @@ func (bc *BabylonController) CommitPubRandList( bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) msg := &finalitytypes.MsgCommitPubRandList{ - Signer: bc.MustGetTxSigner(), + Signer: bc.mustGetTxSigner(), ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), StartHeight: startHeight, PubRandList: schnorrPubRandList, @@ -334,22 +214,19 @@ func (bc *BabylonController) CommitPubRandList( return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -// SubmitCovenantSig submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode +// SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode // it returns tx hash and error -func (bc *BabylonController) SubmitCovenantSig( - valPk *btcec.PublicKey, - delPk *btcec.PublicKey, +func (bc *BabylonController) SubmitCovenantSigs( + covPk *btcec.PublicKey, stakingTxHash string, - sig *schnorr.Signature, + sigs [][]byte, ) (*types.TxResponse, error) { - bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) msg := &btcstakingtypes.MsgAddCovenantSig{ - Signer: bc.MustGetTxSigner(), - ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), - DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), + Signer: bc.mustGetTxSigner(), + Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), StakingTxHash: stakingTxHash, - Sig: &bip340Sig, + Sigs: sigs, } res, err := bc.reliablySendMsg(msg) @@ -363,23 +240,19 @@ func (bc *BabylonController) SubmitCovenantSig( // SubmitCovenantUnbondingSigs submits the Covenant signatures via a MsgAddCovenantUnbondingSigs to Babylon if the daemon runs in Covenant mode // it returns tx hash and error func (bc *BabylonController) SubmitCovenantUnbondingSigs( - valPk *btcec.PublicKey, - delPk *btcec.PublicKey, + covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, - slashUnbondingSig *schnorr.Signature, + slashUnbondingSigs [][]byte, ) (*types.TxResponse, error) { bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) - bip340SlashUnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(slashUnbondingSig) - msg := &btcstakingtypes.MsgAddCovenantUnbondingSigs{ - Signer: bc.MustGetTxSigner(), - ValPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), - DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), - StakingTxHash: stakingTxHash, - UnbondingTxSig: &bip340UnbondingSig, - SlashingUnbondingTxSig: &bip340SlashUnbondingSig, + Signer: bc.mustGetTxSigner(), + Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), + StakingTxHash: stakingTxHash, + UnbondingTxSig: &bip340UnbondingSig, + SlashingUnbondingTxSigs: slashUnbondingSigs, } res, err := bc.reliablySendMsg(msg) @@ -393,11 +266,11 @@ func (bc *BabylonController) SubmitCovenantUnbondingSigs( // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon func (bc *BabylonController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { msg := &finalitytypes.MsgAddFinalitySig{ - Signer: bc.MustGetTxSigner(), - ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), - BlockHeight: blockHeight, - BlockLastCommitHash: blockHash, - FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), + Signer: bc.mustGetTxSigner(), + ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + BlockHeight: blockHeight, + BlockAppHash: blockHash, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), } res, err := bc.reliablySendMsg(msg) @@ -417,11 +290,11 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blo msgs := make([]sdk.Msg, 0, len(blocks)) for i, b := range blocks { msg := &finalitytypes.MsgAddFinalitySig{ - Signer: bc.MustGetTxSigner(), - ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), - BlockHeight: b.Height, - BlockLastCommitHash: b.Hash, - FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]), + Signer: bc.mustGetTxSigner(), + ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + BlockHeight: b.Height, + BlockAppHash: b.Hash, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]), } msgs = append(msgs, msg) } @@ -434,40 +307,6 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blo return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -func (bc *BabylonController) SubmitValidatorUnbondingSig( - valPk *btcec.PublicKey, - delPk *btcec.PublicKey, - stakingTxHash string, - sig *schnorr.Signature, -) (*types.TxResponse, error) { - valBtcPk := bbntypes.NewBIP340PubKeyFromBTCPK(valPk) - - bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) - - msg := &btcstakingtypes.MsgAddValidatorUnbondingSig{ - Signer: bc.MustGetTxSigner(), - ValPk: valBtcPk, - DelPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPk), - StakingTxHash: stakingTxHash, - UnbondingTxSig: &bip340Sig, - } - - res, err := bc.reliablySendMsg(msg) - - if err != nil { - return nil, err - } - - bc.logger.WithFields(logrus.Fields{ - "validator": valBtcPk.MarshalHex(), - "code": res.Code, - "height": res.Height, - "tx_hash": res.TxHash, - }).Debug("Succesfuly submitted validator signature for unbonding tx") - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil -} - func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } @@ -480,22 +319,11 @@ func (bc *BabylonController) QueryUnbondingDelegations(limit uint64) ([]*types.D // 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) ([]*types.Delegation, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() pagination := &sdkquery.PageRequest{ Limit: limit, } - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryBTCDelegationsRequest{ - Status: btcstakingtypes.BTCDelegationStatus(status), - Pagination: pagination, - } - res, err := queryClient.BTCDelegations(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.BTCDelegations(status, pagination) if err != nil { return nil, fmt.Errorf("failed to query BTC delegations: %v", err) } @@ -509,11 +337,10 @@ func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.B } func (bc *BabylonController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} valPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(valPk) queryRequest := &btcstakingtypes.QueryBTCValidatorRequest{ValBtcPkHex: valPubKey.MarshalHex()} @@ -539,18 +366,7 @@ func (bc *BabylonController) getNDelegations( Limit: n, } - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - queryRequest := &btcstakingtypes.QueryBTCValidatorDelegationsRequest{ - ValBtcPkHex: valBtcPk.MarshalHex(), - Pagination: pagination, - } - res, err := queryClient.BTCValidatorDelegations(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.BTCValidatorDelegations(valBtcPk.MarshalHex(), pagination) if err != nil { return nil, nil, fmt.Errorf("failed to query BTC delegations: %v", err) @@ -609,34 +425,12 @@ func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( } } -func (bc *BabylonController) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { - // TODO Check what is the order of returned delegations. Ideally we would return - // delegation here from the first one which received undelegation - - return bc.getNValidatorDelegationsMatchingCriteria( - bbntypes.NewBIP340PubKeyFromBTCPK(valPk), - max, - func(del *types.Delegation) bool { - return del.BtcUndelegation != nil && del.BtcUndelegation.ValidatorUnbondingSig == nil - }, - ) -} - // QueryValidatorVotingPower queries the voting power of the validator at a given height func (bc *BabylonController) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryBTCValidatorPowerAtHeightRequest{ - ValBtcPkHex: bbntypes.NewBIP340PubKeyFromBTCPK(valPk).MarshalHex(), - Height: blockHeight, - } - res, err := queryClient.BTCValidatorPowerAtHeight(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.BTCValidatorPowerAtHeight( + bbntypes.NewBIP340PubKeyFromBTCPK(valPk).MarshalHex(), + blockHeight, + ) if err != nil { return 0, fmt.Errorf("failed to query BTC delegations: %w", err) } @@ -667,18 +461,7 @@ func (bc *BabylonController) queryLatestBlocks(startKey []byte, count uint64, st Key: startKey, } - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - queryRequest := &finalitytypes.QueryListBlocksRequest{ - Status: status, - Pagination: pagination, - } - res, err := queryClient.ListBlocks(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.ListBlocks(status, pagination) if err != nil { return nil, fmt.Errorf("failed to query finalized blocks: %v", err) } @@ -686,7 +469,7 @@ func (bc *BabylonController) queryLatestBlocks(startKey []byte, count uint64, st for _, b := range res.Blocks { ib := &types.BlockInfo{ Height: b.Height, - Hash: b.LastCommitHash, + Hash: b.AppHash, } blocks = append(blocks, ib) } @@ -700,10 +483,10 @@ func getContextWithCancel(timeout time.Duration) (context.Context, context.Cance } func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} queryClient := finalitytypes.NewQueryClient(clientCtx) @@ -718,16 +501,16 @@ func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) return &types.BlockInfo{ Height: height, - Hash: res.Block.LastCommitHash, + Hash: res.Block.AppHash, Finalized: res.Block.Finalized, }, nil } func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} queryClient := btcstakingtypes.NewQueryClient(clientCtx) @@ -742,9 +525,9 @@ func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { } func (bc *BabylonController) QueryBestBlock() (*types.BlockInfo, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) // this will return 20 items at max in the descending order (highest first) - chainInfo, err := bc.provider.RPCClient.BlockchainInfo(ctx, 0, 0) + chainInfo, err := bc.bbnClient.RPCClient.BlockchainInfo(ctx, 0, 0) defer cancel() if err != nil { @@ -755,77 +538,24 @@ func (bc *BabylonController) QueryBestBlock() (*types.BlockInfo, error) { // at request will contain nil header return &types.BlockInfo{ Height: uint64(chainInfo.BlockMetas[0].Header.Height), - Hash: chainInfo.BlockMetas[0].Header.LastCommitHash, + Hash: chainInfo.BlockMetas[0].Header.AppHash, }, nil } -// accessKeyWithLock triggers a function that access key ring while acquiring -// the file system lock, in order to remain thread-safe when multiple concurrent -// relayers are running on the same machine and accessing the same keyring -// adapted from -// https://github.com/babylonchain/babylon-relayer/blob/f962d0940832a8f84f747c5d9cbc67bc1b156386/bbnrelayer/utils.go#L212 -func (bc *BabylonController) accessKeyWithLock(accessFunc func()) error { - // use lock file to guard concurrent access to the keyring - lockFilePath := path.Join(bc.provider.PCfg.KeyDirectory, "keys.lock") - lock := fslock.New(lockFilePath) - if err := lock.Lock(); err != nil { - return fmt.Errorf("failed to acquire file system lock (%s): %w", lockFilePath, err) - } - - // trigger function that access keyring - accessFunc() - - // unlock and release access - if err := lock.Unlock(); err != nil { - return fmt.Errorf("error unlocking file system lock (%s), please manually delete", lockFilePath) - } - - return nil -} - func (bc *BabylonController) Close() error { - if !bc.provider.RPCClient.IsRunning() { + if !bc.bbnClient.IsRunning() { return nil } - return bc.provider.RPCClient.Stop() -} - -func ConvertErrType(err error) error { - if err == nil { - return nil - } - switch { - case strings.Contains(err.Error(), btcstakingtypes.ErrBTCValAlreadySlashed.Error()): - return types.ErrValidatorSlashed - case strings.Contains(err.Error(), finalitytypes.ErrBlockNotFound.Error()): - return types.ErrBlockNotFound - case strings.Contains(err.Error(), finalitytypes.ErrInvalidFinalitySig.Error()): - return types.ErrInvalidFinalitySig - case strings.Contains(err.Error(), finalitytypes.ErrHeightTooHigh.Error()): - return types.ErrHeightTooHigh - case strings.Contains(err.Error(), finalitytypes.ErrNoPubRandYet.Error()): - return types.ErrNoPubRandYet - case strings.Contains(err.Error(), finalitytypes.ErrPubRandNotFound.Error()): - return types.ErrPubRandNotFound - case strings.Contains(err.Error(), finalitytypes.ErrTooFewPubRand.Error()): - return types.ErrTooFewPubRand - case strings.Contains(err.Error(), finalitytypes.ErrInvalidPubRand.Error()): - return types.ErrInvalidPubRand - case strings.Contains(err.Error(), finalitytypes.ErrDuplicatedFinalitySig.Error()): - return types.ErrDuplicatedFinalitySig - default: - return err - } + return bc.bbnClient.Stop() } func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation { var ( - stakingTxHex string - slashingTxHex string - covenantSchnorrSig *schnorr.Signature - undelegation *types.Undelegation - err error + stakingTxHex string + slashingTxHex string + covenantSigs []*types.CovenantAdaptorSigInfo + undelegation *types.Undelegation ) if del.StakingTx == nil { @@ -836,44 +566,46 @@ func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation panic(fmt.Errorf("slashing tx should not be empty in delegation")) } - stakingTxHex, err = del.StakingTx.ToHexStr() - if err != nil { - panic(err) - } + stakingTxHex = hex.EncodeToString(del.StakingTx) slashingTxHex = del.SlashingTx.ToHexStr() - if del.CovenantSig != nil { - covenantSchnorrSig, err = del.CovenantSig.ToBTCSig() - if err != nil { - panic(err) + for _, s := range del.CovenantSigs { + covSigInfo := &types.CovenantAdaptorSigInfo{ + Pk: s.CovPk.MustToBTCPK(), + Sigs: s.AdaptorSigs, } + covenantSigs = append(covenantSigs, covSigInfo) } if del.BtcUndelegation != nil { undelegation = ConvertUndelegationType(del.BtcUndelegation) } + valBtcPks := make([]*btcec.PublicKey, 0, len(del.ValBtcPkList)) + for _, val := range del.ValBtcPkList { + valBtcPks = append(valBtcPks, val.MustToBTCPK()) + } + return &types.Delegation{ BtcPk: del.BtcPk.MustToBTCPK(), - ValBtcPk: del.ValBtcPk.MustToBTCPK(), + ValBtcPks: valBtcPks, + TotalSat: del.TotalSat, StartHeight: del.StartHeight, EndHeight: del.EndHeight, StakingTxHex: stakingTxHex, SlashingTxHex: slashingTxHex, - CovenantSig: covenantSchnorrSig, + CovenantSigs: covenantSigs, BtcUndelegation: undelegation, } } func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Undelegation { var ( - unbondingTxHex string - slashingTxHex string - covenantSlashingSchnorrSig *schnorr.Signature - covenantUnbondingSchnorrSig *schnorr.Signature - valUnbondingSchnorrSig *schnorr.Signature - err error + unbondingTxHex string + slashingTxHex string + covenantSlashingSigs []*types.CovenantAdaptorSigInfo + covenantUnbondingSigs []*types.CovenantSchnorrSigInfo ) if undel.UnbondingTx == nil { @@ -884,60 +616,66 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde panic(fmt.Errorf("slashing tx should not be empty in undelegation")) } - unbondingTxHex, err = undel.UnbondingTx.ToHexStr() - if err != nil { - panic(err) - } + unbondingTxHex = hex.EncodeToString(undel.UnbondingTx) slashingTxHex = undel.SlashingTx.ToHexStr() - if undel.CovenantSlashingSig != nil { - covenantSlashingSchnorrSig, err = undel.CovenantSlashingSig.ToBTCSig() + for _, unbondingSig := range undel.CovenantUnbondingSigList { + sig, err := unbondingSig.Sig.ToBTCSig() if err != nil { panic(err) } - } - - if undel.CovenantUnbondingSig != nil { - covenantUnbondingSchnorrSig, err = undel.CovenantUnbondingSig.ToBTCSig() - if err != nil { - panic(err) + sigInfo := &types.CovenantSchnorrSigInfo{ + Pk: unbondingSig.Pk.MustToBTCPK(), + Sig: sig, } + covenantUnbondingSigs = append(covenantUnbondingSigs, sigInfo) } - if undel.ValidatorUnbondingSig != nil { - valUnbondingSchnorrSig, err = undel.ValidatorUnbondingSig.ToBTCSig() - if err != nil { - panic(err) + for _, s := range undel.CovenantSlashingSigs { + covSigInfo := &types.CovenantAdaptorSigInfo{ + Pk: s.CovPk.MustToBTCPK(), + Sigs: s.AdaptorSigs, } + covenantSlashingSigs = append(covenantSlashingSigs, covSigInfo) } return &types.Undelegation{ UnbondingTxHex: unbondingTxHex, SlashingTxHex: slashingTxHex, - CovenantSlashingSig: covenantSlashingSchnorrSig, - CovenantUnbondingSig: covenantUnbondingSchnorrSig, - ValidatorUnbondingSig: valUnbondingSchnorrSig, + CovenantSlashingSigs: covenantSlashingSigs, + CovenantUnbondingSigs: covenantUnbondingSigs, + UnbondingTime: undel.UnbondingTime, } } // Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) CreateBTCDelegation( delBabylonPk *secp256k1.PubKey, + delBtcPk *bbntypes.BIP340PubKey, + valPks []*btcec.PublicKey, pop *btcstakingtypes.ProofOfPossession, - stakingTx *btcstakingtypes.BabylonBTCTaprootTx, + stakingTime uint32, + stakingValue int64, stakingTxInfo *btcctypes.TransactionInfo, slashingTx *btcstakingtypes.BTCSlashingTx, delSig *bbntypes.BIP340Signature, ) (*types.TxResponse, error) { + valBtcPks := make([]bbntypes.BIP340PubKey, 0, len(valPks)) + for _, v := range valPks { + valBtcPks = append(valBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) + } msg := &btcstakingtypes.MsgCreateBTCDelegation{ - Signer: bc.MustGetTxSigner(), - BabylonPk: delBabylonPk, - Pop: pop, - StakingTx: stakingTx, - StakingTxInfo: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delSig, + Signer: bc.mustGetTxSigner(), + BabylonPk: delBabylonPk, + BtcPk: delBtcPk, + ValBtcPkList: valBtcPks, + Pop: pop, + StakingTime: stakingTime, + StakingValue: stakingValue, + StakingTx: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSig: delSig, } res, err := bc.reliablySendMsg(msg) @@ -951,13 +689,17 @@ func (bc *BabylonController) CreateBTCDelegation( // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) CreateBTCUndelegation( - unbondingTx *btcstakingtypes.BabylonBTCTaprootTx, + unbondingTx []byte, + unbondingTime uint32, + unbondingValue int64, slashingTx *btcstakingtypes.BTCSlashingTx, delSig *bbntypes.BIP340Signature, ) (*provider.RelayerTxResponse, error) { msg := &btcstakingtypes.MsgBTCUndelegate{ - Signer: bc.MustGetTxSigner(), + Signer: bc.mustGetTxSigner(), UnbondingTx: unbondingTx, + UnbondingTime: unbondingTime, + UnbondingValue: unbondingValue, SlashingTx: slashingTx, DelegatorSlashingSig: delSig, } @@ -975,7 +717,7 @@ func (bc *BabylonController) CreateBTCUndelegation( // Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { msg := &btclctypes.MsgInsertHeaders{ - Signer: bc.MustGetTxSigner(), + Signer: bc.mustGetTxSigner(), Headers: headers, } @@ -995,10 +737,10 @@ func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, Limit: 100, } - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} queryClient := btcstakingtypes.NewQueryClient(clientCtx) @@ -1023,10 +765,10 @@ func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} queryClient := btclctypes.NewQueryClient(clientCtx) @@ -1051,10 +793,10 @@ func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { - ctx, cancel := getContextWithCancel(bc.timeout) + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} queryClient := finalitytypes.NewQueryClient(clientCtx) diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 568286df..3860b114 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -35,7 +35,7 @@ type ValidatorAPIs interface { valPk *btcec.PublicKey, pop []byte, commission *big.Int, - description string, + description []byte, ) (*types.TxResponse, error) // CommitPubRandList commits a list of EOTS public randomness the consumer chain @@ -48,14 +48,6 @@ type ValidatorAPIs interface { // SubmitBatchFinalitySigs submits a batch of finality signatures to the consumer chain SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) - // SubmitValidatorUnbondingSig submits the validator signature for unbonding transaction to the consumer chain - SubmitValidatorUnbondingSig( - valPk *btcec.PublicKey, - delPk *btcec.PublicKey, - stakingTxHash string, - sig *schnorr.Signature, - ) (*types.TxResponse, error) - // Note: the following queries are only for PoC // QueryValidatorVotingPower queries the voting power of the validator at a given height @@ -79,27 +71,22 @@ type ValidatorAPIs interface { // QueryActivatedHeight returns the activated height of the consumer chain // error will be returned if the consumer chain has not been activated QueryActivatedHeight() (uint64, error) - - // QueryBTCValidatorUnbondingDelegations queries the unbonding delegations. UnbondingDelegations: - // - already received unbodning transaction on babylon chain - // - not received validator signature yet - QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) } // CovenantAPIs contains interfaces needed when the program is running in the covenant mode type CovenantAPIs interface { - // SubmitCovenantSig submits the Covenant signature to the consumer chain + // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to + // a validator that the delegation is (re-)staked to // it returns tx hash and error - SubmitCovenantSig(valPk *btcec.PublicKey, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) + SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) - // SubmitCovenantUnbondingSigs submits the Covenant signatures to the consumer chain + // SubmitCovenantUnbondingSigs submits the Covenant signatures for undelegation to the consumer chain // it returns tx hash and error SubmitCovenantUnbondingSigs( - valPk *btcec.PublicKey, - delPk *btcec.PublicKey, + covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, - slashUnbondingSig *schnorr.Signature, + slashUnbondingSigs [][]byte, ) (*types.TxResponse, error) // QueryPendingDelegations queries BTC delegations that are in status of pending @@ -116,7 +103,7 @@ func NewClientController(cfg *valcfg.Config, logger *logrus.Logger) (ClientContr ) switch cfg.ChainName { case babylonConsumerChainName: - cc, err = NewBabylonController(cfg.DataDir, cfg.BabylonConfig, logger) + cc, err = NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, logger) if err != nil { return nil, fmt.Errorf("failed to create Babylon rpc client: %w", err) } diff --git a/clientcontroller/retry_utils.go b/clientcontroller/retry_utils.go index 159e91f3..d84721b8 100644 --- a/clientcontroller/retry_utils.go +++ b/clientcontroller/retry_utils.go @@ -2,32 +2,23 @@ package clientcontroller import ( "errors" - "time" - "github.com/avast/retry-go/v4" - - "github.com/babylonchain/btc-validator/types" -) - -// Variables used for retries -var ( - rtyAttNum = uint(5) - rtyAtt = retry.Attempts(rtyAttNum) - rtyDel = retry.Delay(time.Millisecond * 400) - rtyErr = retry.LastErrorOnly(true) + sdkErr "cosmossdk.io/errors" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + finalitytypes "github.com/babylonchain/babylon/x/finality/types" ) // these errors are considered unrecoverable because these indicate // something critical in the validator program or the consumer chain -var unrecoverableErrors = []error{ - types.ErrBlockNotFound, - types.ErrInvalidFinalitySig, - types.ErrHeightTooHigh, - types.ErrInvalidPubRand, - types.ErrNoPubRandYet, - types.ErrPubRandNotFound, - types.ErrTooFewPubRand, - types.ErrValidatorSlashed, +var unrecoverableErrors = []*sdkErr.Error{ + finalitytypes.ErrBlockNotFound, + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrHeightTooHigh, + finalitytypes.ErrInvalidPubRand, + finalitytypes.ErrNoPubRandYet, + finalitytypes.ErrPubRandNotFound, + finalitytypes.ErrTooFewPubRand, + btcstakingtypes.ErrBTCValAlreadySlashed, } // IsUnrecoverable returns true when the error is in the unrecoverableErrors list @@ -41,10 +32,10 @@ func IsUnrecoverable(err error) bool { return false } -var expectedErrors = []error{ +var expectedErrors = []*sdkErr.Error{ // if due to some low-level reason (e.g., network), we submit duplicated finality sig, // we should just ignore the error - types.ErrDuplicatedFinalitySig, + finalitytypes.ErrDuplicatedFinalitySig, } // IsExpected returns true when the error is in the expectedErrors list diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go index c2c2de51..9d73595a 100644 --- a/cmd/valcli/daemoncmd.go +++ b/cmd/valcli/daemoncmd.go @@ -37,7 +37,7 @@ const ( keyNameFlag = "key-name" valBTCPkFlag = "btc-pk" blockHeightFlag = "height" - lastCommitHashFlag = "last-commit-hash" + appHashFlag = "app-hash" passphraseFlag = "passphrase" hdPathFlag = "hd-path" chainIdFlag = "chain-id" @@ -56,7 +56,7 @@ const ( var ( defaultValdDaemonAddress = "127.0.0.1:" + strconv.Itoa(valcfg.DefaultRPCPort) - defaultLastCommitHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" + defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" ) var getDaemonInfoCmd = cli.Command{ @@ -181,7 +181,7 @@ func createValDaemon(ctx *cli.Context) error { ctx.String(chainIdFlag), ctx.String(passphraseFlag), ctx.String(hdPathFlag), - &description, + description, &commissionRate, ) @@ -203,6 +203,7 @@ func getDescriptionFromContext(ctx *cli.Context) (stakingtypes.Description, erro detailsStr := ctx.String(detailsFlag) description := stakingtypes.NewDescription(monikerStr, identityStr, websiteStr, securityContractStr, detailsStr) + return description.EnsureLength() } @@ -353,9 +354,9 @@ var addFinalitySigDaemonCmd = cli.Command{ Required: true, }, cli.StringFlag{ - Name: lastCommitHashFlag, + Name: appHashFlag, Usage: "The last commit hash of the chain block", - Value: defaultLastCommitHashStr, + Value: defaultAppHashStr, }, }, Action: addFinalitySig, @@ -374,7 +375,7 @@ func addFinalitySig(ctx *cli.Context) error { return err } - lch, err := types.NewLastCommitHashFromHex(ctx.String(lastCommitHashFlag)) + lch, err := types.NewAppHashFromHex(ctx.String(appHashFlag)) if err != nil { return err } diff --git a/covenant/Dockerfile b/covenant/Dockerfile index dc9cd19a..8ada7868 100644 --- a/covenant/Dockerfile +++ b/covenant/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.5-alpine as builder +FROM golang:1.21.4-alpine as builder # Version to build. Default is the Git HEAD. ARG VERSION="HEAD" @@ -14,7 +14,7 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/babylon-private +ENV GOPRIVATE=github.com/babylonchain/* # Build WORKDIR /go/src/github.com/babylonchain/covenant diff --git a/covenant/cmd/covcli/new.go b/covenant/cmd/covcli/new.go index d0621aa1..bb603127 100644 --- a/covenant/cmd/covcli/new.go +++ b/covenant/cmd/covcli/new.go @@ -77,7 +77,7 @@ func createCovenantKey(ctx *cli.Context) error { passphrase := ctx.String(passphraseFlag) hdPath := ctx.String(hdPathFlag) - covenantPk, err := covenant.CreateCovenantKey( + keyPair, err := covenant.CreateCovenantKey( keyringDir, chainID, keyName, @@ -90,7 +90,7 @@ func createCovenantKey(ctx *cli.Context) error { return fmt.Errorf("failed to create covenant key: %w", err) } - bip340Key := types.NewBIP340PubKeyFromBTCPK(covenantPk) + bip340Key := types.NewBIP340PubKeyFromBTCPK(keyPair.PublicKey) printRespJSON( &covenantKey{ Name: ctx.String(keyNameFlag), diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go index e86e0c88..31fb288e 100644 --- a/covenant/cmd/covd/start.go +++ b/covenant/cmd/covd/start.go @@ -45,7 +45,7 @@ func startCovenantFn(ctx *cli.Context) error { return fmt.Errorf("failed to load config at %s: %w", configFilePath, err) } - bbnClient, err := clientcontroller.NewBabylonController(cfg.CovenantDir, cfg.BabylonConfig, cfgLogger) + bbnClient, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, cfgLogger) if err != nil { return fmt.Errorf("failed to create rpc client for the consumer chain: %w", err) } diff --git a/covenant/covenant.go b/covenant/covenant.go index 801a70ad..2e5aa025 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -6,11 +6,13 @@ import ( "sync" "time" + "github.com/avast/retry-go/v4" + "github.com/babylonchain/babylon/btcstaking" + asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" @@ -20,6 +22,14 @@ import ( "github.com/babylonchain/btc-validator/val" ) +var ( + // TODO: Maybe configurable? + RtyAttNum = uint(5) + RtyAtt = retry.Attempts(RtyAttNum) + RtyDel = retry.Delay(time.Millisecond * 400) + RtyErr = retry.LastErrorOnly(true) +) + type CovenantEmulator struct { startOnce sync.Once stopOnce sync.Once @@ -27,10 +37,13 @@ type CovenantEmulator struct { wg sync.WaitGroup quit chan struct{} + pk *btcec.PublicKey + cc clientcontroller.ClientController kc *val.ChainKeyringController config *covcfg.Config + params *types.StakingParams logger *logrus.Logger // input is used to pass passphrase to the keyring @@ -60,10 +73,16 @@ func NewCovenantEmulator( return nil, err } - if _, err := kc.GetChainPrivKey(passphrase); err != nil { + sk, err := kc.GetChainPrivKey(passphrase) + if err != nil { return nil, fmt.Errorf("covenant key %s is not found: %w", config.BabylonConfig.Key, err) } + pk, err := btcec.ParsePubKey(sk.PubKey().Bytes()) + if err != nil { + return nil, err + } + return &CovenantEmulator{ cc: cc, kc: kc, @@ -71,66 +90,108 @@ func NewCovenantEmulator( logger: logger, input: input, passphrase: passphrase, + pk: pk, quit: make(chan struct{}), }, nil } +func (ce *CovenantEmulator) UpdateParams() error { + params, err := ce.getParamsWithRetry() + if err != nil { + return err + } + ce.params = params + + return nil +} + // AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// TODO the logic will be largely replaced when new staking utilities are introduced func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*service.AddCovenantSigResponse, error) { - if btcDel.CovenantSig != nil { - return nil, fmt.Errorf("the Covenant sig already existed in the Bitcoin delection") + // 1. the quorum is already achieved, skip sending more sigs + if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) { + return nil, nil } - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) + // 2. check staking tx and slashing tx are valid + stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.StakingTxHex) if err != nil { return nil, err } - err = slashingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) - if err != nil { - return nil, fmt.Errorf("invalid delegation: %w", err) - } - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(btcDel.StakingTxHex) + slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) if err != nil { return nil, err } - stakingMsgTx, err := stakingTx.ToMsgTx() + + slashingMsgTx, err := slashingTx.ToMsgTx() if err != nil { return nil, err } - // get Covenant private key from the keyring + if err := btcstaking.CheckTransactions( + slashingMsgTx, + stakingMsgTx, + btcDel.StakingOutputIdx, + int64(ce.params.MinSlashingTxFeeSat), + ce.params.SlashingRate, + ce.params.SlashingAddress, + &ce.config.ActiveNetParams, + ); err != nil { + return nil, fmt.Errorf("invalid txs in the delegation: %w", err) + } + + // 3. sign covenant sigs covenantPrivKey, err := ce.getPrivKey() if err != nil { return nil, fmt.Errorf("failed to get Covenant private key: %w", err) } - covenantSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, + stakingInfo, err := btcstaking.BuildStakingInfo( + btcDel.BtcPk, + btcDel.ValBtcPks, + ce.params.CovenantPks, + ce.params.CovenantQuorum, + btcDel.GetStakingTime(), + btcutil.Amount(btcDel.TotalSat), &ce.config.ActiveNetParams, ) if err != nil { return nil, err } - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantSchnorrSig, err := covenantSig.ToBTCSig() + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() if err != nil { return nil, err } - res, err := ce.cc.SubmitCovenantSig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, covenantSchnorrSig) - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.ValBtcPk).MarshalHex() + covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) + for _, valPk := range btcDel.ValBtcPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + if err != nil { + return nil, err + } + covenantSig, err := slashingTx.EncSign( + stakingMsgTx, + btcDel.StakingOutputIdx, + slashingPathInfo.GetPkScriptPath(), + covenantPrivKey, + encKey, + ) + if err != nil { + return nil, err + } + covSigs = append(covSigs, covenantSig.MustMarshal()) + } + + // 4. submit covenant sigs + res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs) + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() if err != nil { ce.logger.WithFields(logrus.Fields{ - "err": err, - "validator_pk": valPkHex, - "delegator_pk": delPkHex, + "err": err, + "validator_pks": btcDel.ValBtcPks, + "delegator_pk": delPkHex, }).Error("failed to submit Covenant signature") return nil, err } @@ -139,7 +200,6 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*ser } // AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon -// TODO the logic will be largely replaced when new staking utilities are introduced func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*service.AddCovenantSigResponse, error) { if del == nil { return nil, fmt.Errorf("btc delegation is nil") @@ -149,114 +209,134 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, fmt.Errorf("delegation does not have an unbonding transaction") } - if del.BtcUndelegation.ValidatorUnbondingSig == nil { - return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") - } - - // In normal operation it is not possible to have one of this signatures and not have the other - // as only way to update this fields in delegation is by processing the MsgAddCovenantUnbondingSigs msg - // which should update both fields at atomically in case of successfull transaction. - if del.BtcUndelegation.CovenantSlashingSig != nil || del.BtcUndelegation.CovenantUnbondingSig != nil { - return nil, fmt.Errorf("delegation already has required covenant signatures") + // 1. skip sending sigs if the quorum has already been reached + if del.BtcUndelegation.HasAllSignatures(ce.params.CovenantQuorum) { + return nil, fmt.Errorf("undelegation of the delegation already has required signature from covenant") } - // get Covenant private key from the keyring - covenantPrivKey, err := ce.getPrivKey() + // 2. ensure that the unbonding tx and the slashing tx are valid + slashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.SlashingTxHex) if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + return nil, err } - // 1. Sign unbonding transaction - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) + unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.UnbondingTxHex) if err != nil { return nil, err } - stakingMsgTx, err := stakingTx.ToMsgTx() + unbondingInfo, err := btcstaking.BuildUnbondingInfo( + del.BtcPk, + del.ValBtcPks, + ce.params.CovenantPks, + ce.params.CovenantQuorum, + uint16(del.BtcUndelegation.UnbondingTime), + btcutil.Amount(unbondingMsgTx.TxOut[0].Value), + &ce.config.ActiveNetParams, + ) if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) + return nil, err } - unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) + err = btcstaking.CheckTransactions( + slashingMsgTx, + unbondingMsgTx, + 0, + int64(ce.params.MinSlashingTxFeeSat), + ce.params.SlashingRate, + ce.params.SlashingAddress, + &ce.config.ActiveNetParams, + ) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) } - covenantUnbondingSig, err := unbondingTx.Sign( - stakingMsgTx, - stakingTx.Script, - covenantPrivKey, + + // 3. Sign unbonding transaction + stakingInfo, err := btcstaking.BuildStakingInfo( + del.BtcPk, + del.ValBtcPks, + ce.params.CovenantPks, + ce.params.CovenantQuorum, + del.GetStakingTime(), + btcutil.Amount(del.TotalSat), &ce.config.ActiveNetParams, ) - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) + return nil, err } - // 2. Sign slash unbonding transaction - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() if err != nil { return nil, err } - err = slashUnbondingTx.Validate(&ce.config.ActiveNetParams, ce.config.SlashingAddress) + covenantPrivKey, err := ce.getPrivKey() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) } - - unbondingMsgTx, err := unbondingTx.ToMsgTx() - + stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.StakingTxHex) if err != nil { - return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) + return nil, err } - covenantSlashingUnbondingSig, err := slashUnbondingTx.Sign( + covenantUnbondingSignature, err := btcstaking.SignTxWithOneScriptSpendInputStrict( unbondingMsgTx, - unbondingTx.Script, + stakingMsgTx, + del.StakingOutputIdx, + stakingTxUnbondingPathInfo.GetPkScriptPath(), covenantPrivKey, - &ce.config.ActiveNetParams, ) if err != nil { - return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) + return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) } - stakingTxHash := stakingMsgTx.TxHash().String() - - covenantUnbondingSchnorrSig, err := covenantUnbondingSig.ToBTCSig() + // 4. Sign slash unbonding transaction + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err } - covenantSlashingUnbondingShcnorrSig, err := covenantSlashingUnbondingSig.ToBTCSig() + + unbondingTxSlashingPath, err := unbondingInfo.SlashingPathSpendInfo() if err != nil { return nil, err } + + covSlashingSigs := make([][]byte, 0, len(del.ValBtcPks)) + for _, valPk := range del.ValBtcPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + if err != nil { + return nil, err + } + covenantSig, err := slashUnbondingTx.EncSign( + unbondingMsgTx, + 0, // 0th output is always the unbonding script output + unbondingTxSlashingPath.GetPkScriptPath(), + covenantPrivKey, + encKey, + ) + if err != nil { + return nil, err + } + covSlashingSigs = append(covSlashingSigs, covenantSig.MustMarshal()) + } + + // 5. submit covenant sigs res, err := ce.cc.SubmitCovenantUnbondingSigs( - del.ValBtcPk, - del.BtcPk, - stakingTxHash, - covenantUnbondingSchnorrSig, - covenantSlashingUnbondingShcnorrSig, + ce.pk, + stakingMsgTx.TxHash().String(), + covenantUnbondingSignature, + covSlashingSigs, ) - valPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.ValBtcPk).MarshalHex() delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() if err != nil { ce.logger.WithFields(logrus.Fields{ "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") + "delegator_pk": delPkHex, + }).Error("failed to submit covenant signatures") return nil, err } - if res == nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": valPkHex, - "delBtcPubKey": delPkHex, - }).Error("failed to submit Covenant signature") - return nil, fmt.Errorf("failed to submit Covenant signature due to known error") - } - return &service.AddCovenantSigResponse{ TxHash: res.TxHash, }, nil @@ -285,22 +365,12 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { select { case <-covenantSigTicker.C: // 0. Update slashing address in case it is changed upon governance proposal - params, err := ce.cc.QueryStakingParams() - if err != nil { + if err := ce.UpdateParams(); err != nil { ce.logger.WithFields(logrus.Fields{ "err": err, - }).Error("failed to get slashing address") + }).Error("failed to get staking params") continue } - slashingAddress := params.SlashingAddress - _, err = btcutil.DecodeAddress(slashingAddress, &ce.config.ActiveNetParams) - if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("invalid slashing address") - continue - } - ce.config.SlashingAddress = slashingAddress // 1. Get all pending delegations first, these are more important than the unbonding ones dels, err := ce.cc.QueryPendingDelegations(limit) @@ -344,7 +414,7 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { ce.logger.WithFields(logrus.Fields{ "err": err, "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") + }).Error("failed to submit Covenant sig to the Bitcoin undelegation") } } @@ -356,7 +426,7 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } -func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*btcec.PublicKey, error) { +func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.KeyPair, error) { sdkCtx, err := service.CreateClientCtx( keyringDir, chainID, ) @@ -373,17 +443,32 @@ func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath return nil, err } - sdkCovenantPk, err := krController.CreateChainKey(passphrase, hdPath) - if err != nil { - return nil, err - } + return krController.CreateChainKey(passphrase, hdPath) +} - covenantPk, err := secp256k1.ParsePubKey(sdkCovenantPk.Key) - if err != nil { +func (ce *CovenantEmulator) getParamsWithRetry() (*types.StakingParams, error) { + var ( + params *types.StakingParams + err error + ) + + if err := retry.Do(func() error { + params, err = ce.cc.QueryStakingParams() + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + ce.logger.WithFields(logrus.Fields{ + "attempt": n + 1, + "max_attempts": RtyAttNum, + "error": err, + }).Debug("failed to query the consumer chain for the staking params") + })); err != nil { return nil, err } - return covenantPk, nil + return params, nil } func (ce *CovenantEmulator) Start() error { diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index e912c716..f0b3f0f2 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -1,11 +1,16 @@ package covenant_test import ( + "encoding/hex" "math/rand" "testing" + "github.com/babylonchain/babylon/btcstaking" + asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" "github.com/babylonchain/babylon/testutil/datagen" + bbntypes "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -21,23 +26,22 @@ const ( hdPath = "" ) +var net = &chaincfg.SimNetParams + func FuzzAddCovenantSig(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - // prepare mocked babylon client + params := testutil.GenRandomParams(r, t) randomStartingHeight := uint64(r.Int63n(100) + 1) finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) + mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight, params) // create a Covenant key pair in the keyring - slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) covenantConfig := covcfg.DefaultConfig() - covenantConfig.SlashingAddress = slashingAddr.String() - covenantPk, err := covenant.CreateCovenantKey( + covKeyPair, err := covenant.CreateCovenantKey( covenantConfig.BabylonConfig.KeyDirectory, covenantConfig.BabylonConfig.ChainID, covenantConfig.BabylonConfig.Key, @@ -46,43 +50,151 @@ func FuzzAddCovenantSig(f *testing.F) { hdPath, ) require.NoError(t, err) + + // create and start covenant emulator ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logrus.New()) require.NoError(t, err) - btcPk, err := datagen.GenRandomBIP340PubKey(r) + err = ce.UpdateParams() require.NoError(t, err) // generate BTC delegation + changeAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) + require.NoError(t, err) delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) stakingTimeBlocks := uint16(5) stakingValue := int64(2 * 10e8) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk.MustToBTCPK(), covenantPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) - require.NoError(t, err) - require.NoError(t, err) - stakingTxHex, err := stakingTx.ToHexStr() + valNum := datagen.RandomInt(r, 5) + 1 + valPks := testutil.GenBtcPublicKeys(r, t, int(valNum)) + testInfo := datagen.GenBTCStakingSlashingInfo( + r, + t, + net, + delSK, + valPks, + params.CovenantPks, + params.CovenantQuorum, + stakingTimeBlocks, + stakingValue, + params.SlashingAddress.String(), + changeAddr.String(), + params.SlashingRate, + ) + stakingTxBytes, err := bbntypes.SerializeBTCTx(testInfo.StakingTx) require.NoError(t, err) - delegation := &types.Delegation{ - ValBtcPk: btcPk.MustToBTCPK(), - BtcPk: delPK, - StakingTxHex: stakingTxHex, - SlashingTxHex: slashingTx.ToHexStr(), + startHeight := datagen.RandomInt(r, 1000) + 100 + btcDel := &types.Delegation{ + BtcPk: delPK, + ValBtcPks: valPks, + StartHeight: startHeight, // not relevant here + EndHeight: startHeight + uint64(stakingTimeBlocks), + TotalSat: uint64(stakingValue), + StakingTxHex: hex.EncodeToString(stakingTxBytes), + StakingOutputIdx: 0, + SlashingTxHex: testInfo.SlashingTx.ToHexStr(), } - stakingMsgTx, err := stakingTx.ToMsgTx() + // generate covenant sigs + slashingSpendInfo, err := testInfo.StakingInfo.SlashingPathSpendInfo() require.NoError(t, err) + covSigs := make([][]byte, 0, len(valPks)) + for _, valPk := range valPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + require.NoError(t, err) + covenantSig, err := testInfo.SlashingTx.EncSign( + testInfo.StakingTx, + 0, + slashingSpendInfo.GetPkScriptPath(), + covKeyPair.PrivateKey, encKey, + ) + require.NoError(t, err) + covSigs = append(covSigs, covenantSig.MustMarshal()) + } + + // check the sigs are expected expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryPendingDelegations(gomock.Any()). - Return([]*types.Delegation{delegation}, nil).AnyTimes() - mockClientController.EXPECT().SubmitCovenantSig( - delegation.ValBtcPk, - delegation.BtcPk, - stakingMsgTx.TxHash().String(), - gomock.Any(), + mockClientController.EXPECT().SubmitCovenantSigs( + covKeyPair.PublicKey, + testInfo.StakingTx.TxHash().String(), + covSigs, ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + res, err := ce.AddCovenantSignature(btcDel) + require.NoError(t, err) + require.Equal(t, expectedTxHash, res.TxHash) + + // generate undelegation + unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 + unbondingValue := int64(btcDel.TotalSat) - 1000 + + stakingTxHash := testInfo.StakingTx.TxHash() + testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( + r, + t, + net, + delSK, + btcDel.ValBtcPks, + params.CovenantPks, + params.CovenantQuorum, + wire.NewOutPoint(&stakingTxHash, 0), + unbondingTime, + unbondingValue, + params.SlashingAddress.String(), changeAddr.String(), + params.SlashingRate, + ) + require.NoError(t, err) + // random signer + unbondingTxMsg := testUnbondingInfo.UnbondingTx + + unbondingSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() + require.NoError(t, err) - res, err := ce.AddCovenantSignature(delegation) + serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) + require.NoError(t, err) + undel := &types.Undelegation{ + UnbondingTxHex: hex.EncodeToString(serializedUnbondingTx), + UnbondingTime: uint32(unbondingTime), + SlashingTxHex: testUnbondingInfo.SlashingTx.ToHexStr(), + } + btcDel.BtcUndelegation = undel + stakingTxUnbondingPathInfo, err := testInfo.StakingInfo.UnbondingPathSpendInfo() + require.NoError(t, err) + unbondingCovSig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( + unbondingTxMsg, + testInfo.StakingTx, + btcDel.StakingOutputIdx, + stakingTxUnbondingPathInfo.GetPkScriptPath(), + covKeyPair.PrivateKey, + ) + require.NoError(t, err) + unbondingCovSlashingSigs := make([][]byte, 0, len(valPks)) + for _, valPk := range valPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + require.NoError(t, err) + covenantSig, err := testUnbondingInfo.SlashingTx.EncSign( + testUnbondingInfo.UnbondingTx, + 0, + unbondingSlashingPathInfo.GetPkScriptPath(), + covKeyPair.PrivateKey, + encKey, + ) + require.NoError(t, err) + unbondingCovSlashingSigs = append(unbondingCovSlashingSigs, covenantSig.MustMarshal()) + } + + // check the sigs are expected + expectedTxHash = testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT().QueryUnbondingDelegations(gomock.Any()). + Return([]*types.Delegation{btcDel}, nil).AnyTimes() + mockClientController.EXPECT().SubmitCovenantUnbondingSigs( + covKeyPair.PublicKey, + testInfo.StakingTx.TxHash().String(), + unbondingCovSig, + unbondingCovSlashingSigs, + ). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + res, err = ce.AddCovenantUnbondingSignatures(btcDel) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) }) diff --git a/eotsmanager/Dockerfile b/eotsmanager/Dockerfile index d9374b19..e6cb5688 100644 --- a/eotsmanager/Dockerfile +++ b/eotsmanager/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.5-alpine as builder +FROM golang:1.21.4-alpine as builder # Version to build. Default is the Git HEAD. ARG VERSION="HEAD" @@ -14,7 +14,7 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/babylon-private +ENV GOPRIVATE=github.com/babylonchain/* # Build WORKDIR /go/src/github.com/babylonchain/eots-manager diff --git a/go.mod b/go.mod index c3727d04..847cc41c 100644 --- a/go.mod +++ b/go.mod @@ -1,310 +1,248 @@ module github.com/babylonchain/btc-validator -go 1.20 +go 1.21 + +toolchain go1.21.4 require ( - cosmossdk.io/math v1.0.1 - github.com/avast/retry-go/v4 v4.3.3 - github.com/babylonchain/babylon v0.7.1 + cosmossdk.io/errors v1.0.0 + cosmossdk.io/math v1.2.0 + github.com/avast/retry-go/v4 v4.5.1 + github.com/babylonchain/babylon v0.7.2 + github.com/babylonchain/rpc-client v0.7.0 github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 - github.com/cosmos/cosmos-proto v1.0.0-beta.2 - github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/cosmos-proto v1.0.0-beta.3 + github.com/cosmos/cosmos-sdk v0.50.1 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/gogoproto v1.4.10 - github.com/cosmos/relayer/v2 v2.4.1 + github.com/cosmos/gogoproto v1.4.11 + github.com/cosmos/relayer/v2 v2.4.3-0.20231121194223-be8ebe0a83db github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 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/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b github.com/lightningnetwork/lnd v0.16.4-beta.rc1 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.14 go.etcd.io/bbolt v1.3.7 go.uber.org/atomic v1.10.0 - go.uber.org/zap v1.24.0 - golang.org/x/sync v0.1.0 - google.golang.org/grpc v1.56.1 + google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 - sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go v0.110.8 // indirect + cloud.google.com/go/compute v1.23.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.29.0 // indirect - cosmossdk.io/api v0.3.1 // indirect - cosmossdk.io/core v0.5.1 // indirect - cosmossdk.io/depinject v1.0.0-alpha.3 // indirect - cosmossdk.io/errors v1.0.0-beta.7 // indirect - cosmossdk.io/log v1.1.0 // indirect - cosmossdk.io/tools/rosetta v0.2.1 // indirect + cloud.google.com/go/iam v1.1.3 // indirect + cloud.google.com/go/storage v1.31.0 // indirect + cosmossdk.io/api v0.7.2 // 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.2.1 // indirect + cosmossdk.io/store v1.0.0 // indirect + cosmossdk.io/tools/confix v0.1.0 // 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.12.0 // 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 github.com/99designs/keyring v1.2.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/CosmWasm/wasmd v0.40.0 // indirect - github.com/CosmWasm/wasmvm v1.2.3 // indirect - github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/CosmWasm/wasmd v0.50.0-rc.2 // indirect + github.com/CosmWasm/wasmvm v1.5.0 // indirect + github.com/DataDog/zstd v1.5.5 // indirect github.com/aead/siphash v1.0.1 // indirect - github.com/andybalholm/brotli v1.0.3 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.44.203 // 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/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd/btcutil/psbt v1.1.8 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13 // indirect - github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect - github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect - github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 // indirect - github.com/btcsuite/btcwallet/walletdb v1.4.0 // indirect - github.com/btcsuite/btcwallet/wtxmgr v1.5.0 // indirect - github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect - github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect - github.com/btcsuite/winsvc v1.0.0 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect - github.com/cometbft/cometbft v0.37.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/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v0.38.1 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect - github.com/confio/ics23/go v0.9.0 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // 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/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.2.0 // indirect + github.com/cosmos/iavl v1.0.0 // 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 - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect - github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/creachadair/atomicfile v0.3.1 // indirect + github.com/creachadair/tomledit v0.0.24 // indirect github.com/danieljoos/wincred v1.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // 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/lru v1.0.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/docker/distribution v2.8.2+incompatible // indirect - github.com/dsnet/compress v0.0.1 // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/ethereum/go-ethereum v1.11.3 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect - github.com/fergusstrange/embedded-postgres v1.10.0 // indirect + github.com/emicklei/dot v1.6.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/go-ethereum v1.13.5 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-errors/errors v1.0.1 // indirect + github.com/getsentry/sentry-go v0.25.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-logr/logr v1.2.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // 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.4.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 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.5.9 // 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.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.8.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // 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/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // 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.2 // 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 + github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect 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/big v0.0.0-20221017200358-a027dc42d04e // indirect - github.com/holiman/uint256 v1.2.0 // indirect + github.com/holiman/uint256 v1.2.3 // 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.10.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.1.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.8.1 // indirect - github.com/jackc/pgx/v4 v4.13.0 // 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/jrick/logrotate v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/juju/clock v1.0.3 // indirect - github.com/juju/errors v1.0.0 // indirect - github.com/juju/loggo v1.0.0 // indirect - github.com/juju/testing v1.0.2 // indirect - github.com/juju/utils/v3 v3.0.2 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/jsternberg/zap-logfmt v1.3.0 // indirect + github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect + github.com/klauspost/compress v1.17.2 // 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/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect - github.com/lightninglabs/neutrino v0.15.0 // indirect - github.com/lightninglabs/neutrino/cache v1.1.1 // indirect - github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 // indirect - github.com/lightningnetwork/lnd/clock v1.1.0 // indirect - github.com/lightningnetwork/lnd/healthcheck v1.2.2 // indirect - github.com/lightningnetwork/lnd/kvdb v1.4.1 // indirect - github.com/lightningnetwork/lnd/queue v1.1.0 // indirect - github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect - github.com/lightningnetwork/lnd/tlv v1.1.0 // indirect - github.com/lightningnetwork/lnd/tor v1.1.0 // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect - github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect + github.com/linxGnu/grocksdb v1.8.4 // 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.18 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mholt/archiver/v3 v3.5.0 // indirect - github.com/miekg/dns v1.1.43 // 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/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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // 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.0.8 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect - github.com/pierrec/lz4/v4 v4.1.8 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + 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.0 // indirect - github.com/prometheus/client_golang v1.15.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect - github.com/rakyll/statik v0.1.7 // 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/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/rogpeppe/fastuuid v1.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.29.1 // indirect + github.com/rs/zerolog v1.31.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/soheilhy/cmux v0.1.5 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.16.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - github.com/supranational/blst v0.3.8 // indirect + github.com/spf13/viper v1.17.0 // indirect + github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 // 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.6.0 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect + github.com/tidwall/btree v1.7.0 // 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.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect - go.etcd.io/etcd/api/v3 v3.5.9 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect - go.etcd.io/etcd/client/v2 v2.305.7 // indirect - go.etcd.io/etcd/client/v3 v3.5.9 // 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 + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3 // indirect - go.opentelemetry.io/otel v1.11.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/sdk v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.11.0 // indirect - go.opentelemetry.io/proto/otlp v0.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/time v0.1.0 // indirect - golang.org/x/tools v0.6.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.15.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.18.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.122.0 // indirect + google.golang.org/api v0.143.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - gopkg.in/errgo.v1 v1.0.1 // indirect + google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/macaroon-bakery.v2 v2.0.1 // indirect - gopkg.in/macaroon.v2 v2.0.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 - 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 + gotest.tools/v3 v3.5.1 // indirect nhooyr.io/websocket v1.8.6 // indirect - pgregory.net/rapid v0.5.5 // indirect + pgregory.net/rapid v1.1.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f - github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 + github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 07d9955a..27f14bd9 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,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.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= 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= @@ -70,8 +70,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.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= 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= @@ -111,13 +111,12 @@ 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 v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= 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= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -175,8 +174,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f 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.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI= +cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0= 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= @@ -188,20 +187,38 @@ 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.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= -cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= -cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= -cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= -cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= -cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= -cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= -cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= +cosmossdk.io/api v0.7.2/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= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= +cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= +cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= +cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= +cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= +cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= +cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= +cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= +cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= +cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= +cosmossdk.io/x/evidence v0.1.0/go.mod h1:hTaiiXsoiJ3InMz1uptgF0BnGqROllAN8mwisOMMsfw= +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.12.0 h1:Ry2btjQdrfrje9qZ3iZeZSmDArjgxUJMMcLMrX4wj5U= +cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +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= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= @@ -209,71 +226,66 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +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 v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.40.0 h1:3Vvq1m8dPQdvZR+QJc86VIx6QoWAEVnuHxqBPshJvyo= -github.com/CosmWasm/wasmd v0.40.0/go.mod h1:SuxskRBB7+bpwXGhUXaEfdpjg5WKpdxBy7Tm36VRMUU= -github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= -github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +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-rc.2 h1:CK7bRrAxYo8xooGhAwCRWyJqog+/M/7G1/p1BQVDNNU= +github.com/CosmWasm/wasmd v0.50.0-rc.2/go.mod h1:KtrZmXmh/V1ZmQ2/3dU6VRuZ09moRDpRqTL3L/mnPIE= +github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= +github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +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/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +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= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 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.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= -github.com/andybalholm/brotli v1.0.3/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= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/avast/retry-go/v4 v4.3.3 h1:G56Bp6mU0b5HE1SkaoVjscZjlQb0oy4mezwY/cGH19w= -github.com/avast/retry-go/v4 v4.3.3/go.mod h1:rg6XFaiuFYII0Xu3RDbZQkxCofFwruZKW8oEF1jpWiU= +github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh7o= +github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc= 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.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= -github.com/aws/aws-sdk-go v1.44.203/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-private v0.0.0-20231109083355-a680fcc5261f h1:J8wNXIRlc7+vFpWj2LiUNhHng8o37+a1RpbbrkvXr8Q= -github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f/go.mod h1:Omv/7j7d/KioUlGhffrA1uajzYwx959cLElstveJwKc= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= +github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af h1:qzjmuFWgiamSvTXUQT/uDJEn4PA2ndV2Srq0qZauL1c= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af/go.mod h1:2Dwjgml0C7vO/JSFs2ZJtgGrnP1oa5G21+DDQ6IqQTk= +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= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -283,29 +295,23 @@ 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/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.20220204213055-eaf0459ff879/go.mod h1:osu7EoKiL36UThEgzYPqdRaxeo0NU8VoXqgcnwpey0g= -github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 h1:FZR6mILlSI/GDx8ydNVBZAlXlRXsoRBWX2Un64mpfsI= github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34= github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/btcutil/psbt v1.1.8 h1:4voqtT8UppT7nmKQkXV+T9K8UyQjKOn2z/ycpmJK8wg= -github.com/btcsuite/btcd/btcutil/psbt v1.1.8/go.mod h1:kA6FLH/JfUx++j9pYU0pyu+Z8XGBQuuTmuKYUf6q7/U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= @@ -313,32 +319,15 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/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 v0.16.10-0.20230621165747-9c21f464ce13 h1:7i0CzK+PP4+Dth9ia/eIBFRw8+K6MT8MfoFqBH43Xts= -github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13/go.mod h1:Hl4PP/tSNcgN6himfx/020mYSa19a1qkqTuqQBUU97w= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 h1:etuLgGEojecsDOYTII8rYiGHjGyV5xTqsXi+ZQ715UU= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2/go.mod h1:Zpk/LOb2sKqwP2lmHjaZT9AdaKsHPSbNLm2Uql5IQ/0= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 h1:BtEN5Empw62/RVnZ0VcJaVtVlBijnLlJY+dwjAye2Bg= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.2/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 h1:PszOub7iXVYbtGybym5TGCp9Dv1h1iX4rIC3HICZGLg= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= -github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -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/btcwallet/wtxmgr v1.5.0 h1:WO0KyN4l6H3JWnlFxfGR7r3gDnlGT7W2cL8vl6av4SU= -github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= 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= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= +github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -374,86 +363,95 @@ 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-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -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/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +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/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +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/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= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= -github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= +github.com/cometbft/cometbft v0.38.1 h1:hflfGk/VrPapfHco3rgCqn2YpOglAqJshSdyrM2zSLk= +github.com/cometbft/cometbft v0.38.1/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= -github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= -github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= 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-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.3 h1:r0hGmZoAzP2D+MaPaFGHwAaTdFQq3pNpHaUp1BsffbM= -github.com/cosmos/cosmos-sdk v0.47.3/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +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.1 h1:2SYwAYqd7ZwtrWxu/J8PwbQV/cDcu90bCr/a78g3lVw= +github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= 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= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= -github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +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/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= +github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= -github.com/cosmos/relayer/v2 v2.4.1 h1:oQpx5S1f2qCtWIevgmM7tczEvuSurBF37yOXokwwqMg= -github.com/cosmos/relayer/v2 v2.4.1/go.mod h1:g74emrKs5e55PDjBJj9sG+Es5EtUFN5S9jMpDH9gHJU= -github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= -github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +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.20231121194223-be8ebe0a83db h1:F5dlvwH3zQpTDnZySmH9OoMKKdx2OUKrP8CEQTWsAuY= +github.com/cosmos/relayer/v2 v2.4.3-0.20231121194223-be8ebe0a83db/go.mod h1:z5EtRGgbdFhqiemIu09cwwNbNu+UNH/qkhk696JFv48= 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 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 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-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/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= +github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= @@ -466,13 +464,12 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +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/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/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/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 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= @@ -483,6 +480,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/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= @@ -494,32 +493,36 @@ 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 v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/ethereum/go-ethereum v1.11.3 h1:uuBkYUJW9aY5JYi3+sqLHz+XWyo5fmn/ab9XcbtVDTU= -github.com/ethereum/go-ethereum v1.11.3/go.mod h1:rBUvAl5cdVrAei9q5lgOU7RSEuPJk1nlBDnS/YSoKQE= +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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.2/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/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/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= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +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/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= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -536,46 +539,44 @@ 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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -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.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +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 h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 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.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -613,16 +614,15 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu 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.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 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= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -636,8 +636,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -648,6 +649,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -665,19 +667,20 @@ 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-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/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= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -687,36 +690,32 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +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/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.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +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/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/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= 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-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= 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= @@ -728,13 +727,19 @@ 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.2 h1:uJDtyXwEfalmp1PqdxuhZqrNkUyClZAhVeZYTArbqkg= +github.com/hashicorp/go-getter v1.7.2/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= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y= +github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -751,27 +756,30 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +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/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= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -780,56 +788,12 @@ 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.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -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 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -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.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= -github.com/jackc/pgtype v1.8.1/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.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= -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= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -840,10 +804,7 @@ 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 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= 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= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -857,133 +818,76 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y= github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/juju/clock v1.0.3 h1:yJHIsWXeU8j3QcBdiess09SzfiXRRrsjKPn2whnMeds= -github.com/juju/clock v1.0.3/go.mod h1:HIBvJ8kiV/n7UHwKuCkdYL4l/MDECztHR2sAvWDxxf0= -github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM= -github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8= github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8= github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= -github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0= -github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= -github.com/juju/testing v1.0.2 h1:OR90RqCd9CJONxXamZAjLknpZdtqDyxqW8IwCbgw3i4= -github.com/juju/testing v1.0.2/go.mod h1:h3Vd2rzB57KrdsBEy6R7bmSKPzP76BnNavt7i8PerwQ= -github.com/juju/utils/v3 v3.0.2 h1:6Hel0EXKSM4SOQFHfRel74ZvRp4O0QuxSSf3p3W2FNA= -github.com/juju/utils/v3 v3.0.2/go.mod h1:8csUcj1VRkfjNIRzBFWzLFCMLwLqsRWvkmhfVAUwbC4= 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.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -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/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= 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/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/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 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/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/neutrino v0.15.0 h1:yr3uz36fLAq8hyM0TRUVlef1TRNoWAqpmmNlVtKUDtI= -github.com/lightninglabs/neutrino v0.15.0/go.mod h1:pmjwElN/091TErtSE9Vd5W4hpxoG2/+xlb+HoPm9Gug= -github.com/lightninglabs/neutrino/cache v1.1.1 h1:TllWOSlkABhpgbWJfzsrdUaDH2fBy/54VSIB4vVqV8M= -github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 h1:Wm0g70gkcAu2pGpNZwfWPSVOY21j8IyYsNewwK4OkT4= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1/go.mod h1:7dDx73ApjEZA0kcknI799m2O5kkpfg4/gr7N092ojNo= 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/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ= -github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -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/queue v1.1.0 h1:YpCJjlIvVxN/R7ww2aNiY8ex7U2fucZDLJ67tI3HFx8= -github.com/lightningnetwork/lnd/queue v1.1.0/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= -github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= -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/tlv v1.1.0 h1:gsyte75HVuA/X59O+BhaISHM6OobZ0YesPbdu+xG1h0= -github.com/lightningnetwork/lnd/tlv v1.1.0/go.mod h1:0+JKp4un47MG1lnj6jKa8woNeB1X7w3yF4MZB1NHiiE= -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.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= -github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= -github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= -github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= -github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= -github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= +github.com/linxGnu/grocksdb v1.8.4/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= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= 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.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 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.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -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/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/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/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= @@ -1002,6 +906,9 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1023,30 +930,37 @@ 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= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1056,31 +970,33 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6nYUPxQEP+ReTsceJTKizeuwjWOPUA= +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= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -1088,74 +1004,68 @@ 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.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +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_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.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +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/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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 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= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= -github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= 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/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.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= 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 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +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/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.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -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.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +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/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= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 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/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/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 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= @@ -1164,38 +1074,37 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs 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= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +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/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= @@ -1206,28 +1115,26 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/supranational/blst v0.3.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= -github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +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= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= -github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= -github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +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= @@ -1235,9 +1142,8 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -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/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.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= @@ -1246,9 +1152,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX 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/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/vulpine-io/io-test v1.0.0/go.mod h1:X1I+p5GCxVX9m4nFd1HBtr2bVX9v1ZE6x8w+Obt36AU= 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= @@ -1257,30 +1161,14 @@ 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.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/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.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= -go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= -go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= -go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= -go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= -go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= -go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= -go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= -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= @@ -1292,65 +1180,43 @@ 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.36.3 h1:syAz40OyelLZo42+3U68Phisvrx4qh+4wpdZw7eUUdY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3/go.mod h1:Dts42MGkzZne2yCru741+bFiTMWkIj/LLRizad7b9tw= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk= -go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= -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/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= -go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI= -go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= 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= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +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.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +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.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -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.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= 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= @@ -1362,8 +1228,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-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +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/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= @@ -1390,8 +1256,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.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +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/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= @@ -1433,7 +1299,6 @@ 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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1442,7 +1307,6 @@ 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-20211112202133-69e39bad7dc2/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= @@ -1456,8 +1320,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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= 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= @@ -1470,7 +1334,6 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1484,8 +1347,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.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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= @@ -1500,8 +1363,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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/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/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= @@ -1513,9 +1376,7 @@ 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= @@ -1524,10 +1385,8 @@ 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1563,7 +1422,6 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210225134936-a50acf3fe073/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= @@ -1582,6 +1440,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1606,14 +1465,14 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.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.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= 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= @@ -1623,16 +1482,13 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1642,18 +1498,17 @@ 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= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1695,10 +1550,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.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -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/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= 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= @@ -1757,8 +1610,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.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA= +google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= 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= @@ -1820,7 +1673,6 @@ google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= @@ -1878,12 +1730,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-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= 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= @@ -1916,7 +1768,6 @@ 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= @@ -1926,8 +1777,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.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= @@ -1948,27 +1799,18 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= -gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= 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/macaroon-bakery.v2 v2.0.1 h1:0N1TlEdfLP4HXNCg7MQUMp5XwvOoxk+oe9Owr2cpvsc= -gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= -gopkg.in/macaroon.v2 v2.0.0 h1:LVWycAfeJBUjCIqfR9gqlo7I8vmiXRr51YEOZ1suop8= -gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= -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= @@ -1987,8 +1829,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1997,38 +1839,16 @@ 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/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -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/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= 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 v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 07c88b98..52d21905 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -182,10 +182,6 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { return dir } -func (w *BabylonNodeHandler) GetSlashingAddress() string { - return w.babylonNode.slashingAddr -} - func (w *BabylonNodeHandler) GetCovenantPk() *types.BIP340PubKey { return w.babylonNode.covenantPk } diff --git a/itest/e2e_test.go b/itest/e2e_test.go index eaec847e..b0d5849d 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/babylonchain/babylon/testutil/datagen" + "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/types" @@ -27,11 +28,13 @@ func TestValidatorLifeCycle(t *testing.T) { tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) + params := tm.GetParams(t) + // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) @@ -52,11 +55,13 @@ func TestDoubleSigning(t *testing.T) { tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) + params := tm.GetParams(t) + // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) @@ -76,7 +81,7 @@ func TestDoubleSigning(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) b := &types.BlockInfo{ Height: finalizedBlocks[0].Height, - Hash: datagen.GenRandomLastCommitHash(r), + Hash: datagen.GenRandomAppHash(r), } _, extractedKey, err := valIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) @@ -92,11 +97,13 @@ func TestFastSync(t *testing.T) { tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) + params := tm.GetParams(t) + // check the public randomness is committed tm.WaitForValPubRandCommitted(t, valIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) @@ -106,9 +113,11 @@ func TestFastSync(t *testing.T) { // check the last voted block is finalized lastVotedHeight := tm.WaitForValVoteCast(t, valIns) tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) - finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) + var finalizedBlocks []*types.BlockInfo + finalizedBlocks = tm.WaitForNFinalizedBlocks(t, 1) n := 3 // stop the validator for a few blocks then restart to trigger the fast sync @@ -128,63 +137,42 @@ func TestFastSync(t *testing.T) { require.True(t, currentHeight < finalizedHeight+uint64(n)) } -func TestValidatorUnbondingSigSubmission(t *testing.T) { - tm, valIns := StartManagerWithValidator(t) - defer tm.Stop(t) - - // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) - - // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) - - // check the BTC delegation is pending - _ = tm.WaitForNPendingDels(t, 1) - - _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - - tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) - - _ = tm.WaitForValNUnbondingDels(t, valIns.GetBtcPkBIP340(), 1) -} - func TestCovenantLifeCycle(t *testing.T) { tm, valIns := StartManagerWithValidator(t) defer tm.Stop(t) - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + params := tm.GetParams(t) + valPk := valIns.MustGetBtcPk() + valBtcPk := valIns.GetBtcPkBIP340() + // send BTC delegation and make sure it's deep enough in btclightclient module + delData := tm.InsertBTCDelegation(t, []*btcec.PublicKey{valPk}, stakingTime, stakingAmount, params) dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - err := valIns.Stop() + del := dels[0] + err := tm.Va.Stop() require.NoError(t, err) - tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) + tm.InsertBTCUnbonding( + t, + del, + delData.DelegatorPrivKey, + delData.ChangeAddr, + params, + ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) + dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) if err != nil { return false } return len(dels) == 1 && dels[0].BtcUndelegation != nil }, eventuallyWaitTimeOut, eventuallyPollTime) - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) - require.NoError(t, err) - delegationWithUndelegation := dels[0] - - validatorPrivKey, err := valIns.BtcPrivKey() - require.NoError(t, err) - - tm.AddValidatorUnbondingSignature( - t, - delegationWithUndelegation, - validatorPrivKey, - ) + t.Log("undelegation is found, waiting for covenant sigs") - // after providing validator unbodning signature, we should wait for covenant to provide both valid signatures + // after providing validator unbonding signature, we should wait for covenant to provide both valid signatures require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) + dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) if err != nil { return false } @@ -199,6 +187,6 @@ func TestCovenantLifeCycle(t *testing.T) { return false } - return del.BtcUndelegation.CovenantSlashingSig != nil && del.BtcUndelegation.CovenantUnbondingSig != nil + return len(del.BtcUndelegation.CovenantSlashingSigs) != 0 && len(del.BtcUndelegation.CovenantUnbondingSigs) != 0 }, 1*time.Minute, eventuallyPollTime) } diff --git a/itest/test_manager.go b/itest/test_manager.go index b2856ecb..24aa5a0f 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/babylonchain/babylon/btcstaking" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" @@ -21,7 +21,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -67,12 +66,14 @@ type TestDelegationData struct { DelegatorKey *btcec.PublicKey DelegatorBabylonPrivKey *secp256k1.PrivKey DelegatorBabylonKey *secp256k1.PubKey - StakingTx *bstypes.BabylonBTCTaprootTx SlashingTx *bstypes.BTCSlashingTx + StakingTx *wire.MsgTx StakingTxInfo *btcctypes.TransactionInfo DelegatorSig *bbntypes.BIP340Signature + ValidatorPks []*btcec.PublicKey SlashingAddr string + ChangeAddr string StakingTime uint16 StakingAmount int64 } @@ -89,15 +90,15 @@ func StartManager(t *testing.T) *TestManager { covenantConfig := defaultCovenantConfig(testDir) err = covenantConfig.Validate() require.NoError(t, err) - covenantPk, err := covenant.CreateCovenantKey(testDir, chainID, covenantKeyName, keyring.BackendTest, passphrase, hdPath) + covKeyPair, err := covenant.CreateCovenantKey(testDir, chainID, covenantKeyName, keyring.BackendTest, passphrase, hdPath) require.NoError(t, err) // 2. prepare Babylon node - bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covenantPk)) + bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covKeyPair.PublicKey)) err = bh.Start() require.NoError(t, err) cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir) - bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) + bc, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, logger) require.NoError(t, err) // 3. prepare EOTS manager @@ -153,8 +154,10 @@ func StartManagerWithValidator(t *testing.T) (*TestManager, *service.ValidatorIn valName := valNamePrefix + strconv.Itoa(0) moniker := monikerPrefix + strconv.Itoa(0) - commission := sdktypes.ZeroDec() - res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, newDescription(moniker), &commission) + commission := sdkmath.LegacyZeroDec() + desc, err := newDescription(moniker).Marshal() + require.NoError(t, err) + res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, desc, &commission) require.NoError(t, err) _, err = app.RegisterValidator(res.ValPk.MarshalHex()) require.NoError(t, err) @@ -181,7 +184,7 @@ func StartManagerWithValidator(t *testing.T) (*TestManager, *service.ValidatorIn if !strings.Contains(v.Description.Moniker, monikerPrefix) { return false } - if !v.Commission.Equal(sdktypes.ZeroDec()) { + if !v.Commission.Equal(sdkmath.LegacyZeroDec()) { return false } } @@ -285,7 +288,7 @@ func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BI return false } - return len(dels) == 1 && dels[0].BtcUndelegation != nil && dels[0].BtcUndelegation.ValidatorUnbondingSig != nil + return len(dels) == 1 && dels[0].BtcUndelegation != nil }, 1*time.Minute, eventuallyPollTime) @@ -306,9 +309,8 @@ func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, statu func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTCDelegationStatus { if del.BtcUndelegation != nil { - if del.BtcUndelegation.CovenantSlashingSig != nil && - del.BtcUndelegation.CovenantUnbondingSig != nil && - del.BtcUndelegation.ValidatorUnbondingSig != nil { + if del.BtcUndelegation.CovenantSlashingSigs != nil && + del.BtcUndelegation.CovenantUnbondingSigs != nil { return bstypes.BTCDelegationStatus_UNBONDED } // If we received an undelegation but is still does not have all required signature, @@ -322,7 +324,7 @@ func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTC } if del.StartHeight <= btcHeight && btcHeight+w <= del.EndHeight { - if del.CovenantSig != nil { + if del.CovenantSigs != nil { return bstypes.BTCDelegationStatus_ACTIVE } else { return bstypes.BTCDelegationStatus_PENDING @@ -415,71 +417,36 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, require.NoError(t, err) } -// delegation must containt undelgation object -func (tm *TestManager) AddValidatorUnbondingSignature( - t *testing.T, - del *types.Delegation, - validatorSk *btcec.PrivateKey, -) { - stakingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.StakingTxHex) - require.NoError(t, err) - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - - unbondingTx, err := bstypes.NewBabylonTaprootTxFromHex(del.BtcUndelegation.UnbondingTxHex) - require.NoError(t, err) - - valSig, err := unbondingTx.Sign( - stakingMsgTx, - stakingTx.Script, - validatorSk, - btcNetworkParams, - ) - require.NoError(t, err) - - stakingTxHash := stakingMsgTx.TxHash().String() - - valSchnorrSig, err := valSig.ToBTCSig() - require.NoError(t, err) - _, err = tm.BabylonClient.SubmitValidatorUnbondingSig( - del.ValBtcPk, - del.BtcPk, - stakingTxHash, - valSchnorrSig, - ) - require.NoError(t, err) -} - func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { record, err := tm.EOTSClient.KeyRecord(valPk, passphrase) require.NoError(t, err) return record.PrivKey } -func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData { +func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *types.StakingParams) *TestDelegationData { r := rand.New(rand.NewSource(time.Now().UnixNano())) - // examine staking params - params, err := tm.BabylonClient.QueryStakingParams() - slashingAddr := params.SlashingAddress - require.NoError(t, err) - require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) - require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - covenantPk := tm.BabylonHandler.GetCovenantPk().MustToBTCPK() - require.NoError(t, err) - require.Equal(t, params.CovenantPk.SerializeCompressed()[1:], covenantPk.SerializeCompressed()[1:]) - // delegator BTC key pairs, staking tx and slashing tx delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx( - r, btcNetworkParams, delBtcPrivKey, valBtcPk, covenantPk, stakingTime, stakingAmount, slashingAddr) - require.NoError(t, err) - // get msgTx - stakingMsgTx, err := stakingTx.ToMsgTx() + changeAddress, err := datagen.GenRandomBTCAddress(r, btcNetworkParams) require.NoError(t, err) + testStakingInfo := datagen.GenBTCStakingSlashingInfo( + r, + t, + btcNetworkParams, + delBtcPrivKey, + validatorPks, + params.CovenantPks, + params.CovenantQuorum, + stakingTime, + stakingAmount, + params.SlashingAddress.String(), changeAddress.String(), + params.SlashingRate, + ) + // delegator Babylon key pairs delBabylonPrivKey, delBabylonPubKey, err := datagen.GenRandomSecp256k1KeyPair(r) require.NoError(t, err) @@ -491,7 +458,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK // create and insert BTC headers which include the staking tx to get staking tx info currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() require.NoError(t, err) - blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), stakingMsgTx) + blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), testStakingInfo.StakingTx) accumulatedWork := btclctypes.CalcWork(&blockWithStakingTx.HeaderBytes) accumulatedWork = btclctypes.CumulativeWork(accumulatedWork, *currentBtcTip.Work) parentBlockHeaderInfo := &btclctypes.BTCHeaderInfo{ @@ -510,20 +477,33 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK _, err = tm.BabylonClient.InsertBtcBlockHeaders(headers) require.NoError(t, err) btcHeader := blockWithStakingTx.HeaderBytes - txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, stakingTx.Tx, blockWithStakingTx.SpvProof.MerkleNodes) + serializedStakingTx, err := bbntypes.SerializeBTCTx(testStakingInfo.StakingTx) + require.NoError(t, err) + txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, serializedStakingTx, blockWithStakingTx.SpvProof.MerkleNodes) + + slashignSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo() + require.NoError(t, err) // delegator sig - delegatorSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, + delegatorSig, err := testStakingInfo.SlashingTx.Sign( + testStakingInfo.StakingTx, + 0, + slashignSpendInfo.GetPkScriptPath(), delBtcPrivKey, - btcNetworkParams, ) require.NoError(t, err) // submit the BTC delegation to Babylon _, err = tm.BabylonClient.CreateBTCDelegation( - delBabylonPubKey.(*secp256k1.PubKey), pop, stakingTx, txInfo, slashingTx, delegatorSig) + delBabylonPubKey.(*secp256k1.PubKey), + bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), + validatorPks, + pop, + uint32(stakingTime), + stakingAmount, + txInfo, + testStakingInfo.SlashingTx, + delegatorSig) require.NoError(t, err) return &TestDelegationData{ @@ -531,11 +511,13 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK DelegatorKey: delBtcPubKey, DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), - StakingTx: stakingTx, - SlashingTx: slashingTx, + ValidatorPks: validatorPks, + StakingTx: testStakingInfo.StakingTx, + SlashingTx: testStakingInfo.SlashingTx, StakingTxInfo: txInfo, DelegatorSig: delegatorSig, - SlashingAddr: tm.BabylonHandler.GetSlashingAddress(), + SlashingAddr: params.SlashingAddress.String(), + ChangeAddr: changeAddress.String(), StakingTime: stakingTime, StakingAmount: stakingAmount, } @@ -543,57 +525,63 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK func (tm *TestManager) InsertBTCUnbonding( t *testing.T, - stakingTx *bstypes.BabylonBTCTaprootTx, - stakerPrivKey *btcec.PrivateKey, - validatorPk *btcec.PublicKey, + actualDel *types.Delegation, + delSK *btcec.PrivateKey, + changeAddress string, + params *types.StakingParams, ) { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - params, err := tm.BabylonClient.QueryStakingParams() - require.NoError(t, err) - slashingAddr := params.SlashingAddress - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - stakingTxChainHash := stakingTx.MustGetTxHash() + stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(actualDel.StakingTxHex) require.NoError(t, err) + stakingTxHash := stakingMsgTx.TxHash() - stakingOutputIdx, err := btcstaking.GetIdxOutputCommitingToScript( - stakingMsgTx, stakingTx.Script, btcNetworkParams, - ) - require.NoError(t, err) + unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 + unbondingValue := int64(actualDel.TotalSat - 1000) - stakingValue := stakingMsgTx.TxOut[stakingOutputIdx].Value - fee := int64(1000) + r := rand.New(rand.NewSource(time.Now().UnixNano())) - unbondingTx, slashUnbondingTx, err := datagen.GenBTCUnbondingSlashingTx( + testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( r, + t, btcNetworkParams, - stakerPrivKey, - validatorPk, - params.CovenantPk, - wire.NewOutPoint(&stakingTxChainHash, uint32(stakingOutputIdx)), - uint16(params.FinalizationTimeoutBlocks)+1, - stakingValue-fee, - slashingAddr, + delSK, + actualDel.ValBtcPks, + params.CovenantPks, + params.CovenantQuorum, + wire.NewOutPoint(&stakingTxHash, 0), + unbondingTime, + unbondingValue, + params.SlashingAddress.String(), changeAddress, + params.SlashingRate, ) - require.NoError(t, err) - unbondingTxMsg, err := unbondingTx.ToMsgTx() + unbondingTxMsg := testUnbondingInfo.UnbondingTx + + unbondingSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() require.NoError(t, err) - slashingTxSig, err := slashUnbondingTx.Sign( + unbondingSig, err := testUnbondingInfo.SlashingTx.Sign( unbondingTxMsg, - unbondingTx.Script, - stakerPrivKey, - btcNetworkParams, + 0, + unbondingSlashingPathInfo.GetPkScriptPath(), + delSK, ) require.NoError(t, err) + serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) + require.NoError(t, err) + _, err = tm.BabylonClient.CreateBTCUndelegation( - unbondingTx, slashUnbondingTx, slashingTxSig, + serializedUnbondingTx, uint32(unbondingTime), unbondingValue, testUnbondingInfo.SlashingTx, unbondingSig, ) require.NoError(t, err) } +func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { + p, err := tm.BabylonClient.QueryStakingParams() + require.NoError(t, err) + return p +} + func defaultValidatorConfig(keyringDir, testDir string) *valcfg.Config { cfg := valcfg.DefaultConfig() diff --git a/proto/validators.pb.go b/proto/validators.pb.go index e1928ec0..ae10ec24 100644 --- a/proto/validators.pb.go +++ b/proto/validators.pb.go @@ -8,7 +8,7 @@ package proto import ( _ "github.com/cosmos/cosmos-proto" - types "github.com/cosmos/cosmos-sdk/x/staking/types" + _ "github.com/cosmos/cosmos-sdk/x/staking/types" _ "github.com/cosmos/gogoproto/gogoproto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -198,9 +198,8 @@ type CreateValidatorRequest struct { // chain_id is the identifier of the consumer chain that the validator connected to ChainId string `protobuf:"bytes,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + Description []byte `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec Commission string `protobuf:"bytes,6,opt,name=commission,proto3" json:"commission,omitempty"` } @@ -264,7 +263,7 @@ func (x *CreateValidatorRequest) GetChainId() string { return "" } -func (x *CreateValidatorRequest) GetDescription() *types.Description { +func (x *CreateValidatorRequest) GetDescription() []byte { if x != nil { return x.Description } @@ -440,8 +439,8 @@ type AddFinalitySignatureRequest struct { 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 uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - // last_commit_hash is the last commit hash of the Babylon block - LastCommitHash []byte `protobuf:"bytes,3,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` + // app_hash is the AppHash of the Babylon block + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } func (x *AddFinalitySignatureRequest) Reset() { @@ -490,9 +489,9 @@ func (x *AddFinalitySignatureRequest) GetHeight() uint64 { return 0 } -func (x *AddFinalitySignatureRequest) GetLastCommitHash() []byte { +func (x *AddFinalitySignatureRequest) GetAppHash() []byte { if x != nil { - return x.LastCommitHash + return x.AppHash } return nil } @@ -753,9 +752,8 @@ type StoreValidator struct { // btc_pk is the BTC secp256k1 PK of the validator 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 validator - Description *types.Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec 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 *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,omitempty"` @@ -821,7 +819,7 @@ func (x *StoreValidator) GetBtcPk() []byte { return nil } -func (x *StoreValidator) GetDescription() *types.Description { +func (x *StoreValidator) GetDescription() []byte { if x != nil { return x.Description } @@ -895,9 +893,8 @@ type ValidatorInfo struct { // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator 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 validator - Description *types.Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec 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"` @@ -954,7 +951,7 @@ func (x *ValidatorInfo) GetBtcPkHex() string { return "" } -func (x *ValidatorInfo) GetDescription() *types.Description { +func (x *ValidatorInfo) GetDescription() []byte { if x != nil { return x.Description } @@ -1119,7 +1116,7 @@ var file_validators_proto_rawDesc = []byte{ 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xa8, 0x02, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0xee, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, @@ -1127,172 +1124,160 @@ var file_validators_proto_rawDesc = []byte{ 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, - 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x51, 0x0a, 0x18, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, - 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 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, - 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, - 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, - 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x76, 0x0a, 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, - 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, - 0x0a, 0x1c, 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, 0x17, - 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, - 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, - 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, - 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, - 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, - 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, - 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, - 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, - 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 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, - 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, - 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, - 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 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, - 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x41, 0x64, 0x64, + 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 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, 0x06, 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, + 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, + 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, + 0x50, 0x6b, 0x22, 0x51, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, + 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x62, 0x74, 0x63, 0x50, 0x6b, 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, 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x67, 0x0a, 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, + 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, + 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, + 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, + 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xd3, 0x03, 0x0a, 0x0e, 0x53, 0x74, + 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 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, 0x0a, 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, + 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, + 0xca, 0x02, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 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, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 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, 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, 0x4d, 0x0a, 0x0e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x12, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x4d, 0x0a, + 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x12, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1327,34 +1312,30 @@ var file_validators_proto_goTypes = []interface{}{ (*ValidatorInfo)(nil), // 14: proto.ValidatorInfo (*ProofOfPossession)(nil), // 15: proto.ProofOfPossession (*SchnorrRandPair)(nil), // 16: proto.SchnorrRandPair - (*types.Description)(nil), // 17: cosmos.staking.v1beta1.Description } var file_validators_proto_depIdxs = []int32{ - 17, // 0: proto.CreateValidatorRequest.description:type_name -> cosmos.staking.v1beta1.Description - 14, // 1: proto.QueryValidatorResponse.validator:type_name -> proto.ValidatorInfo - 14, // 2: proto.QueryValidatorListResponse.validators:type_name -> proto.ValidatorInfo - 17, // 3: proto.StoreValidator.description:type_name -> cosmos.staking.v1beta1.Description - 15, // 4: proto.StoreValidator.pop:type_name -> proto.ProofOfPossession - 0, // 5: proto.StoreValidator.status:type_name -> proto.ValidatorStatus - 17, // 6: proto.ValidatorInfo.description:type_name -> cosmos.staking.v1beta1.Description - 0, // 7: proto.ValidatorInfo.status:type_name -> proto.ValidatorStatus - 1, // 8: proto.BtcValidators.GetInfo:input_type -> proto.GetInfoRequest - 3, // 9: proto.BtcValidators.CreateValidator:input_type -> proto.CreateValidatorRequest - 5, // 10: proto.BtcValidators.RegisterValidator:input_type -> proto.RegisterValidatorRequest - 7, // 11: proto.BtcValidators.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest - 9, // 12: proto.BtcValidators.QueryValidator:input_type -> proto.QueryValidatorRequest - 11, // 13: proto.BtcValidators.QueryValidatorList:input_type -> proto.QueryValidatorListRequest - 2, // 14: proto.BtcValidators.GetInfo:output_type -> proto.GetInfoResponse - 4, // 15: proto.BtcValidators.CreateValidator:output_type -> proto.CreateValidatorResponse - 6, // 16: proto.BtcValidators.RegisterValidator:output_type -> proto.RegisterValidatorResponse - 8, // 17: proto.BtcValidators.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse - 10, // 18: proto.BtcValidators.QueryValidator:output_type -> proto.QueryValidatorResponse - 12, // 19: proto.BtcValidators.QueryValidatorList:output_type -> proto.QueryValidatorListResponse - 14, // [14:20] is the sub-list for method output_type - 8, // [8:14] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 14, // 0: proto.QueryValidatorResponse.validator:type_name -> proto.ValidatorInfo + 14, // 1: proto.QueryValidatorListResponse.validators:type_name -> proto.ValidatorInfo + 15, // 2: proto.StoreValidator.pop:type_name -> proto.ProofOfPossession + 0, // 3: proto.StoreValidator.status:type_name -> proto.ValidatorStatus + 0, // 4: proto.ValidatorInfo.status:type_name -> proto.ValidatorStatus + 1, // 5: proto.BtcValidators.GetInfo:input_type -> proto.GetInfoRequest + 3, // 6: proto.BtcValidators.CreateValidator:input_type -> proto.CreateValidatorRequest + 5, // 7: proto.BtcValidators.RegisterValidator:input_type -> proto.RegisterValidatorRequest + 7, // 8: proto.BtcValidators.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest + 9, // 9: proto.BtcValidators.QueryValidator:input_type -> proto.QueryValidatorRequest + 11, // 10: proto.BtcValidators.QueryValidatorList:input_type -> proto.QueryValidatorListRequest + 2, // 11: proto.BtcValidators.GetInfo:output_type -> proto.GetInfoResponse + 4, // 12: proto.BtcValidators.CreateValidator:output_type -> proto.CreateValidatorResponse + 6, // 13: proto.BtcValidators.RegisterValidator:output_type -> proto.RegisterValidatorResponse + 8, // 14: proto.BtcValidators.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse + 10, // 15: proto.BtcValidators.QueryValidator:output_type -> proto.QueryValidatorResponse + 12, // 16: proto.BtcValidators.QueryValidatorList:output_type -> proto.QueryValidatorListResponse + 11, // [11:17] is the sub-list for method output_type + 5, // [5:11] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_validators_proto_init() } diff --git a/proto/validators.proto b/proto/validators.proto index 8e283723..17ba1784 100644 --- a/proto/validators.proto +++ b/proto/validators.proto @@ -50,12 +50,11 @@ message CreateValidatorRequest { // chain_id is the identifier of the consumer chain that the validator connected to string chain_id = 4; // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 5; + bytes description = 5; // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 6 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" + string commission = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false ]; } @@ -81,8 +80,8 @@ message AddFinalitySignatureRequest { string btc_pk = 1; // height is the height of the Babylon block uint64 height = 2; - // last_commit_hash is the last commit hash of the Babylon block - bytes last_commit_hash = 3; + // app_hash is the AppHash of the Babylon block + bytes app_hash = 3; } message AddFinalitySignatureResponse { @@ -118,12 +117,11 @@ message StoreValidator { // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec bytes btc_pk = 2; // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 3; + bytes description = 3; // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 4 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" + string commission = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false ]; // pop is the proof of possession of babylon_pk and btc_pk ProofOfPossession pop = 5; @@ -150,12 +148,11 @@ message ValidatorInfo { // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator encoded in BIP-340 spec string btc_pk_hex = 2; // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 3; + bytes description = 3; // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 4 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" + string commission = 4 [ + (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; diff --git a/service/app.go b/service/app.go index 323cf4ba..362f5ef6 100644 --- a/service/app.go +++ b/service/app.go @@ -5,13 +5,12 @@ import ( "strings" "sync" - "cosmossdk.io/math" + sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" @@ -182,7 +181,7 @@ func (app *ValidatorApp) RegisterValidator(valPkStr string) (*RegisterValidatorR BtcSigType: bstypes.BTCSigType_BIP340, } - commissionRate, err := math.LegacyNewDecFromStr(validator.Commission) + commissionRate, err := sdkmath.LegacyNewDecFromStr(validator.Commission) if err != nil { return nil, err } @@ -286,8 +285,8 @@ func (app *ValidatorApp) Stop() error { func (app *ValidatorApp) CreateValidator( keyName, chainID, passPhrase, hdPath string, - description *stakingtypes.Description, - commission *sdktypes.Dec, + description []byte, + commission *sdkmath.LegacyDec, ) (*CreateValidatorResult, error) { req := &createValidatorRequest{ @@ -331,10 +330,11 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, err } - bbnPk, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + keyPair, err := kr.CreateChainKey(req.passPhrase, req.hdPath) if err != nil { return nil, fmt.Errorf("failed to create chain key for the validator: %w", err) } + pk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} valRecord, err := app.eotsManager.KeyRecord(valPk.MustMarshal(), req.passPhrase) if err != nil { @@ -346,7 +346,7 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) } - validator := val.NewStoreValidator(bbnPk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) + validator := val.NewStoreValidator(pk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) if err := app.vs.SaveValidator(validator); err != nil { return nil, fmt.Errorf("failed to save validator: %w", err) diff --git a/service/app_test.go b/service/app_test.go index ed19ef5d..9237d50f 100644 --- a/service/app_test.go +++ b/service/app_test.go @@ -44,7 +44,7 @@ func FuzzRegisterValidator(f *testing.F) { cfg.ValidatorModeConfig.AutoChainScanningMode = false cfg.ValidatorModeConfig.StaticChainScanningStartHeight = randomStartingHeight currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) @@ -81,7 +81,7 @@ func FuzzRegisterValidator(f *testing.F) { validator.MustGetBIP340BTCPK().MustToBTCPK(), popBytes, testutil.ZeroCommissionRate().BigInt(), - testutil.EmptyDescription().String(), + testutil.EmptyDescription(), ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() res, err := app.RegisterValidator(validator.MustGetBIP340BTCPK().MarshalHex()) diff --git a/service/client/rpcclient.go b/service/client/rpcclient.go index 5cd5bf04..58dba473 100644 --- a/service/client/rpcclient.go +++ b/service/client/rpcclient.go @@ -4,9 +4,9 @@ import ( "context" "fmt" + sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -60,16 +60,21 @@ func (c *ValidatorServiceGRpcClient) RegisterValidator( func (c *ValidatorServiceGRpcClient) CreateValidator( ctx context.Context, keyName, chainID, passphrase, hdPath string, - description *stakingtypes.Description, - commission *sdktypes.Dec, + description types.Description, + commission *sdkmath.LegacyDec, ) (*proto.CreateValidatorResponse, error) { + descBytes, err := description.Marshal() + if err != nil { + return nil, err + } + req := &proto.CreateValidatorRequest{ KeyName: keyName, ChainId: chainID, Passphrase: passphrase, HdPath: hdPath, - Description: description, + Description: descBytes, Commission: commission.String(), } @@ -83,9 +88,9 @@ func (c *ValidatorServiceGRpcClient) CreateValidator( func (c *ValidatorServiceGRpcClient) AddFinalitySignature(ctx context.Context, valPk string, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { req := &proto.AddFinalitySignatureRequest{ - BtcPk: valPk, - Height: height, - LastCommitHash: lch, + BtcPk: valPk, + Height: height, + AppHash: lch, } res, err := c.client.AddFinalitySignature(ctx, req) diff --git a/service/event_loop.go b/service/event_loop.go index 17c3b07d..bad8b163 100644 --- a/service/event_loop.go +++ b/service/event_loop.go @@ -76,7 +76,7 @@ func (app *ValidatorApp) registrationLoop() { req.btcPubKey.MustToBTCPK(), popBytes, req.commission.BigInt(), - req.description.String(), + req.description, ) if err != nil { diff --git a/service/fastsync_test.go b/service/fastsync_test.go index 6fad58ce..74d43bb9 100644 --- a/service/fastsync_test.go +++ b/service/fastsync_test.go @@ -20,7 +20,7 @@ func FuzzFastSync(f *testing.F) { finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) diff --git a/service/rpcserver.go b/service/rpcserver.go index e7b58e18..ef1095cd 100644 --- a/service/rpcserver.go +++ b/service/rpcserver.go @@ -142,7 +142,7 @@ func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFina b := &types.BlockInfo{ Height: req.Height, - Hash: req.LastCommitHash, + Hash: req.AppHash, } txRes, privKey, err := v.TestSubmitFinalitySignatureAndExtractPrivKey(b) diff --git a/service/types.go b/service/types.go index f1505801..0c710b67 100644 --- a/service/types.go +++ b/service/types.go @@ -3,12 +3,11 @@ package service import ( "sync" + sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/proto" @@ -23,8 +22,8 @@ type createValidatorRequest struct { passPhrase string hdPath string chainID string - description *stakingtypes.Description - commission *sdktypes.Dec + description []byte + commission *sdkmath.LegacyDec errResponse chan error successResponse chan *createValidatorResponse } @@ -34,8 +33,8 @@ type registerValidatorRequest struct { btcPubKey *bbntypes.BIP340PubKey // TODO we should have our own representation of PoP pop *btcstakingtypes.ProofOfPossession - description *stakingtypes.Description - commission *sdktypes.Dec + description []byte + commission *sdkmath.LegacyDec errResponse chan error successResponse chan *RegisterValidatorResponse } @@ -61,17 +60,6 @@ type CreateValidatorResult struct { ValPk *bbntypes.BIP340PubKey } -type unbondingTxSigData struct { - stakerPk *bbntypes.BIP340PubKey - stakingTxHash string - signature *bbntypes.BIP340Signature -} - -type unbondingTxSigSendResult struct { - err error - stakingTxHash string -} - type valState struct { mu sync.Mutex v *proto.StoreValidator diff --git a/service/validator_instance.go b/service/validator_instance.go index 14bbb86a..20eca70d 100644 --- a/service/validator_instance.go +++ b/service/validator_instance.go @@ -9,14 +9,13 @@ import ( "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" - types2 "github.com/babylonchain/babylon/x/btcstaking/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" ftypes "github.com/babylonchain/babylon/x/finality/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/gogo/protobuf/jsonpb" "github.com/sirupsen/logrus" "go.uber.org/atomic" - "golang.org/x/sync/errgroup" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" @@ -124,8 +123,6 @@ func (v *ValidatorInstance) Start() error { v.wg.Add(1) go v.randomnessCommitmentLoop() v.wg.Add(1) - go v.unbondindSigSubmissionLoop() - v.wg.Add(1) go v.checkLaggingLoop() return nil @@ -175,181 +172,6 @@ func (v *ValidatorInstance) IsRunning() bool { return v.isStarted.Load() } -func (v *ValidatorInstance) signUnbondingTransactions( - privKey *btcec.PrivateKey, - toSign []*types.Delegation) ([]unbondingTxSigData, error) { - - var dataWithSignatures []unbondingTxSigData - for _, delegation := range toSign { - stakingTx, err := types2.NewBabylonTaprootTxFromHex(delegation.StakingTxHex) - if err != nil { - return nil, err - } - fundingTx, err := stakingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) - } - - fundingTxHash := fundingTx.TxHash().String() - - txToSign, err := types2.NewBabylonTaprootTxFromHex(delegation.BtcUndelegation.UnbondingTxHex) - if err != nil { - return nil, err - } - - sig, err := txToSign.Sign( - fundingTx, - stakingTx.Script, - privKey, - &v.cfg.ActiveNetParams, - ) - - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - utd := unbondingTxSigData{ - stakerPk: bbntypes.NewBIP340PubKeyFromBTCPK(delegation.BtcPk), - stakingTxHash: fundingTxHash, - signature: sig, - } - - dataWithSignatures = append(dataWithSignatures, utd) - } - - return dataWithSignatures, nil -} - -func (v *ValidatorInstance) sendSignaturesForUnbondingTransactions(sigsToSend []unbondingTxSigData) []unbondingTxSigSendResult { - var eg errgroup.Group - var mu sync.Mutex - var res []unbondingTxSigSendResult - - for _, sigData := range sigsToSend { - sd := sigData - eg.Go(func() error { - schnorrSig, err := sd.signature.ToBTCSig() - if err != nil { - res = append(res, unbondingTxSigSendResult{ - err: err, - stakingTxHash: sd.stakingTxHash, - }) - } - _, err = v.cc.SubmitValidatorUnbondingSig( - v.MustGetBtcPk(), - sd.stakerPk.MustToBTCPK(), - sd.stakingTxHash, - schnorrSig, - ) - - mu.Lock() - defer mu.Unlock() - - if err != nil { - res = append(res, unbondingTxSigSendResult{ - err: err, - stakingTxHash: sd.stakingTxHash, - }) - } else { - res = append(res, unbondingTxSigSendResult{ - err: nil, - stakingTxHash: sd.stakingTxHash, - }) - } - - return nil - }) - } - - if err := eg.Wait(); err != nil { - // this should not happen as we do not return errors from our sending - v.logger.Fatalf("Failed to wait for signatures send") - } - - return res -} - -func (v *ValidatorInstance) unbondindSigSubmissionLoop() { - defer v.wg.Done() - - sendUnbondingSigTicker := time.NewTicker(v.cfg.UnbondingSigSubmissionInterval) - defer sendUnbondingSigTicker.Stop() - - for { - select { - case <-sendUnbondingSigTicker.C: - delegationsNeedingSignatures, err := v.cc.QueryBTCValidatorUnbondingDelegations( - v.MustGetBtcPk(), - // TODO: parameterize the max number of delegations to be queried - // it should not be to high to not take too long time to sign them - 10, - ) - - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Error("failed to query Babylon for BTC validator unbonding delegations") - continue - } - - if len(delegationsNeedingSignatures) == 0 { - continue - } - - v.logger.WithFields(logrus.Fields{ - "num_delegations": len(delegationsNeedingSignatures), - "btc_pk_hex": v.GetBtcPkHex(), - }).Debug("Retrieved delegations which need unbonding signatures") - - validatorPrivKey, err := v.getEOTSPrivKey() - - if err != nil { - // Kill the app, if we can't recover our private key, then we have some bug - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Fatalf("failed to get validator private key") - } - - signed, err := v.signUnbondingTransactions(validatorPrivKey, delegationsNeedingSignatures) - - if err != nil { - // We received some malformed data from Babylon either there is some bug in babylon code - // or we are on some malcious fork. Log it as error and continue. - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Errorf("failed to sign unbonding transactions") - continue - } - - sendResult := v.sendSignaturesForUnbondingTransactions(signed) - - for _, res := range sendResult { - if res.err != nil { - // Just log send errors, as if we failed to submit signaute, we will retry in next tick - v.logger.WithFields(logrus.Fields{ - "err": res.err, - "babylon_pk_hex": v.GetBabylonPkHex(), - "staking_tx": res.stakingTxHash, - }).Errorf("failed to send signature for unbonding transaction") - } else { - v.logger.WithFields(logrus.Fields{ - "babylon_pk_hex": v.GetBabylonPkHex(), - "staking_tx": res.stakingTxHash, - }).Infof("successfully sent signature for unbonding transaction") - } - } - - case <-v.quit: - v.logger.Debug("the unbonding sig submission loop is closing") - return - } - } -} - func (v *ValidatorInstance) finalitySigSubmissionLoop() { defer v.wg.Done() @@ -399,7 +221,7 @@ func (v *ValidatorInstance) finalitySigSubmissionLoop() { res, err := v.tryFastSync(targetBlock) v.isLagging.Store(false) if err != nil { - if errors.Is(err, types.ErrValidatorSlashed) { + if errors.Is(err, bstypes.ErrBTCValAlreadySlashed) { v.reportCriticalErr(err) continue } @@ -855,9 +677,9 @@ func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockI func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { // build proper finality signature request msg := &ftypes.MsgAddFinalitySig{ - ValBtcPk: v.btcPk, - BlockHeight: b.Height, - BlockLastCommitHash: b.Hash, + ValBtcPk: v.btcPk, + BlockHeight: b.Height, + BlockAppHash: b.Hash, } msgToSign := msg.MsgToSign() sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height, v.passphrase) diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go index 44279223..04b6f1f9 100644 --- a/service/validator_instance_test.go +++ b/service/validator_instance_test.go @@ -26,7 +26,7 @@ func FuzzCommitPubRandList(f *testing.F) { 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 := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() @@ -57,7 +57,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { 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 := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) defer cleanUp() diff --git a/service/validator_manager.go b/service/validator_manager.go index e3a3e41d..17cdc651 100644 --- a/service/validator_manager.go +++ b/service/validator_manager.go @@ -8,6 +8,7 @@ import ( "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/sirupsen/logrus" "go.uber.org/atomic" @@ -85,7 +86,7 @@ func (vm *ValidatorManager) monitorCriticalErr() { if err != nil { panic(fmt.Errorf("failed to get the validator instance: %w", err)) } - if errors.Is(criticalErr.err, types.ErrValidatorSlashed) { + if errors.Is(criticalErr.err, btcstakingtypes.ErrBTCValAlreadySlashed) { vm.setValidatorSlashed(vi) vm.logger.WithFields(logrus.Fields{ "err": criticalErr, diff --git a/service/validator_manager_test.go b/service/validator_manager_test.go index df0f5a66..6025573e 100644 --- a/service/validator_manager_test.go +++ b/service/validator_manager_test.go @@ -9,6 +9,7 @@ import ( "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/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -122,8 +123,9 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - bbnPk, err := kc.CreateChainKey(passphrase, hdPath) + keyPair, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) + bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) diff --git a/testutil/datagen.go b/testutil/datagen.go index 90485015..941e07e2 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -7,9 +7,11 @@ import ( "testing" "time" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -70,12 +72,50 @@ func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { } } +func GenValidSlashingRate(r *rand.Rand) sdkmath.LegacyDec { + return sdkmath.LegacyNewDecWithPrec(int64(datagen.RandomInt(r, 41)+10), 2) +} + +func GenRandomParams(r *rand.Rand, t *testing.T) *types.StakingParams { + covThreshold := datagen.RandomInt(r, 5) + 1 + covNum := covThreshold * 2 + covenantPks := make([]*btcec.PublicKey, 0, covNum) + for i := 0; i < int(covNum); i++ { + _, covPk, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + covenantPks = append(covenantPks, covPk) + } + + slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) + require.NoError(t, err) + return &types.StakingParams{ + ComfirmationTimeBlocks: 10, + FinalizationTimeoutBlocks: 100, + MinSlashingTxFeeSat: 1, + CovenantPks: covenantPks, + SlashingAddress: slashingAddr, + CovenantQuorum: uint32(covThreshold), + SlashingRate: GenValidSlashingRate(r), + } +} + +func GenBtcPublicKeys(r *rand.Rand, t *testing.T, num int) []*btcec.PublicKey { + pks := make([]*btcec.PublicKey, 0, num) + for i := 0; i < num; i++ { + _, covPk, err := datagen.GenRandomBTCKeyPair(r) + require.NoError(t, err) + pks = append(pks, covPk) + } + + return pks +} + func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { blocks := make([]*types.BlockInfo, 0) for i := startHeight; i <= endHeight; i++ { b := &types.BlockInfo{ Height: i, - Hash: datagen.GenRandomLastCommitHash(r), + Hash: datagen.GenRandomAppHash(r), } blocks = append(blocks, b) } diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 665e6acb..2779f19d 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -81,21 +81,6 @@ func (mr *MockClientControllerMockRecorder) QueryActivatedHeight() *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockClientController)(nil).QueryActivatedHeight)) } -// QueryBTCValidatorUnbondingDelegations mocks base method. -func (m *MockClientController) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valPk, max) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. -func (mr *MockClientControllerMockRecorder) QueryBTCValidatorUnbondingDelegations(valPk, max interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCValidatorUnbondingDelegations), valPk, max) -} - // QueryBestBlock mocks base method. func (m *MockClientController) QueryBestBlock() (*types.BlockInfo, error) { m.ctrl.T.Helper() @@ -232,7 +217,7 @@ func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(valPk, blo } // RegisterValidator mocks base method. -func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description string) (*types.TxResponse, error) { +func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) @@ -261,34 +246,34 @@ func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, block return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) } -// SubmitCovenantSig mocks base method. -func (m *MockClientController) SubmitCovenantSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitCovenantSigs mocks base method. +func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSig", valPk, delPk, stakingTxHash, sig) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitCovenantSig indicates an expected call of SubmitCovenantSig. -func (mr *MockClientControllerMockRecorder) SubmitCovenantSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { +// SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. +func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSig", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSig), valPk, delPk, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) } // SubmitCovenantUnbondingSigs mocks base method. -func (m *MockClientController) SubmitCovenantUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { +func (m *MockClientController) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) } // SubmitFinalitySig mocks base method. @@ -306,21 +291,6 @@ func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(valPk, blockHeight return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) } -// SubmitValidatorUnbondingSig mocks base method. -func (m *MockClientController) SubmitValidatorUnbondingSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPk, delPk, stakingTxHash, sig) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. -func (mr *MockClientControllerMockRecorder) SubmitValidatorUnbondingSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockClientController)(nil).SubmitValidatorUnbondingSig), valPk, delPk, stakingTxHash, sig) -} - // MockValidatorAPIs is a mock of ValidatorAPIs interface. type MockValidatorAPIs struct { ctrl *gomock.Controller @@ -374,21 +344,6 @@ func (mr *MockValidatorAPIsMockRecorder) QueryActivatedHeight() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryActivatedHeight)) } -// QueryBTCValidatorUnbondingDelegations mocks base method. -func (m *MockValidatorAPIs) QueryBTCValidatorUnbondingDelegations(valPk *btcec.PublicKey, max uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valPk, max) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. -func (mr *MockValidatorAPIsMockRecorder) QueryBTCValidatorUnbondingDelegations(valPk, max interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBTCValidatorUnbondingDelegations), valPk, max) -} - // QueryBestBlock mocks base method. func (m *MockValidatorAPIs) QueryBestBlock() (*types.BlockInfo, error) { m.ctrl.T.Helper() @@ -480,7 +435,7 @@ func (mr *MockValidatorAPIsMockRecorder) QueryValidatorVotingPower(valPk, blockH } // RegisterValidator mocks base method. -func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description string) (*types.TxResponse, error) { +func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) @@ -524,21 +479,6 @@ func (mr *MockValidatorAPIsMockRecorder) SubmitFinalitySig(valPk, blockHeight, b return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) } -// SubmitValidatorUnbondingSig mocks base method. -func (m *MockValidatorAPIs) SubmitValidatorUnbondingSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPk, delPk, stakingTxHash, sig) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. -func (mr *MockValidatorAPIsMockRecorder) SubmitValidatorUnbondingSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitValidatorUnbondingSig), valPk, delPk, stakingTxHash, sig) -} - // MockCovenantAPIs is a mock of CovenantAPIs interface. type MockCovenantAPIs struct { ctrl *gomock.Controller @@ -592,32 +532,32 @@ func (mr *MockCovenantAPIsMockRecorder) QueryUnbondingDelegations(limit interfac return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryUnbondingDelegations), limit) } -// SubmitCovenantSig mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantSig(valPk, delPk *btcec.PublicKey, stakingTxHash string, sig *schnorr.Signature) (*types.TxResponse, error) { +// SubmitCovenantSigs mocks base method. +func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSig", valPk, delPk, stakingTxHash, sig) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// SubmitCovenantSig indicates an expected call of SubmitCovenantSig. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSig(valPk, delPk, stakingTxHash, sig interface{}) *gomock.Call { +// SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSig", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSig), valPk, delPk, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) } // SubmitCovenantUnbondingSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantUnbondingSigs(valPk, delPk *btcec.PublicKey, stakingTxHash string, unbondingSig, slashUnbondingSig *schnorr.Signature) (*types.TxResponse, error) { +func (m *MockCovenantAPIs) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantUnbondingSigs(valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantUnbondingSigs), valPk, delPk, stakingTxHash, unbondingSig, slashUnbondingSig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) } diff --git a/testutil/utils.go b/testutil/utils.go index bbca2c49..a9235e6f 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -4,24 +4,23 @@ import ( "math/rand" "testing" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + sdkmath "cosmossdk.io/math" "github.com/golang/mock/gomock" "github.com/babylonchain/btc-validator/testutil/mocks" "github.com/babylonchain/btc-validator/types" ) -func EmptyDescription() *stakingtypes.Description { - return &stakingtypes.Description{} +func EmptyDescription() []byte { + return []byte("empty description") } -func ZeroCommissionRate() *sdktypes.Dec { - zeroCom := sdktypes.ZeroDec() +func ZeroCommissionRate() *sdkmath.LegacyDec { + zeroCom := sdkmath.LegacyZeroDec() return &zeroCom } -func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64) *mocks.MockClientController { +func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64, params *types.StakingParams) *mocks.MockClientController { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) @@ -41,6 +40,7 @@ func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, curr mockClientController.EXPECT().Close().Return(nil).AnyTimes() mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + mockClientController.EXPECT().QueryStakingParams().Return(params, nil).AnyTimes() return mockClientController } diff --git a/tools/go.mod b/tools/go.mod index 17b0b356..a5beb47b 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,30 +1,32 @@ module github.com/babylonchain/btc-validator/tools -go 1.20 +go 1.21 + +toolchain go1.21.4 require github.com/babylonchain/babylon v0.7.1 require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go v0.110.8 // indirect + cloud.google.com/go/compute v1.23.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.29.0 // indirect - cosmossdk.io/api v0.3.1 // indirect - cosmossdk.io/core v0.5.1 // indirect - cosmossdk.io/depinject v1.0.0-alpha.3 // indirect - cosmossdk.io/errors v1.0.0-beta.7 // indirect - cosmossdk.io/log v1.1.0 // indirect - cosmossdk.io/math v1.0.1 // indirect + cloud.google.com/go/iam v1.1.3 // indirect + cloud.google.com/go/storage v1.30.1 // indirect + cosmossdk.io/api v0.7.2 // indirect + cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.0 // indirect + cosmossdk.io/log v1.2.1 // indirect + cosmossdk.io/math v1.2.0 // indirect cosmossdk.io/tools/rosetta v0.2.1 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/CosmWasm/wasmd v0.40.0 // indirect - github.com/CosmWasm/wasmvm v1.2.3 // indirect + github.com/CosmWasm/wasmd v0.50.0-rc.2 // indirect + github.com/CosmWasm/wasmvm v1.5.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.44.203 // indirect + github.com/aws/aws-sdk-go v1.44.224 // 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 @@ -40,23 +42,23 @@ require ( github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect - github.com/cometbft/cometbft v0.37.2 // indirect + github.com/cometbft/cometbft v0.38.0 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/cosmos-sdk v0.47.3 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect + github.com/cosmos/cosmos-sdk v0.50.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/gogoproto v1.4.10 // indirect - github.com/cosmos/iavl v0.20.0 // indirect + github.com/cosmos/gogoproto v1.4.11 // indirect + github.com/cosmos/iavl v1.0.0 // indirect github.com/cosmos/ibc-go/v7 v7.0.1 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect github.com/creachadair/taskgroup v0.4.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // 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 @@ -66,7 +68,7 @@ require ( github.com/docker/distribution v2.8.2+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -74,23 +76,23 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect 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/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.5.9 // 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.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.8.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // 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/grpc-ecosystem/go-grpc-middleware v1.3.0 // 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/gtank/merlin v0.1.1 // indirect @@ -100,7 +102,7 @@ require ( github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/huandu/skiplist v1.2.0 // indirect @@ -109,14 +111,14 @@ require ( 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/klauspost/compress v1.16.3 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/linxGnu/grocksdb v1.8.4 // 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.18 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect @@ -125,62 +127,61 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + 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.0 // indirect - github.com/prometheus/client_golang v1.15.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // 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/procfs v0.12.0 // indirect github.com/rakyll/statik v0.1.7 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.29.1 // indirect + github.com/rs/zerolog v1.31.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.16.0 // indirect + github.com/spf13/viper v1.17.0 // indirect github.com/stretchr/testify v1.8.4 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.8 // 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.6.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.122.0 // indirect + google.golang.org/api v0.143.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect - pgregory.net/rapid v0.5.5 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + pgregory.net/rapid v1.1.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f - github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index fcd4dafa..49813e88 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -34,6 +34,7 @@ cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34h cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= 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= @@ -72,6 +73,7 @@ cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQH cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= 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= @@ -113,6 +115,7 @@ cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= 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= @@ -177,6 +180,7 @@ cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeL cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= 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= @@ -190,16 +194,22 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= +cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= +cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= +cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= +cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -216,8 +226,10 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/CosmWasm/wasmd v0.40.0 h1:3Vvq1m8dPQdvZR+QJc86VIx6QoWAEVnuHxqBPshJvyo= github.com/CosmWasm/wasmd v0.40.0/go.mod h1:SuxskRBB7+bpwXGhUXaEfdpjg5WKpdxBy7Tm36VRMUU= +github.com/CosmWasm/wasmd v0.50.0-rc.2/go.mod h1:KtrZmXmh/V1ZmQ2/3dU6VRuZ09moRDpRqTL3L/mnPIE= github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= @@ -252,12 +264,16 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.224/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-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f/go.mod h1:Omv/7j7d/KioUlGhffrA1uajzYwx959cLElstveJwKc= +github.com/babylonchain/babylon-private v0.0.0-20231123033744-c31e470a8b0d/go.mod h1:nTxsy7JADtFtehkvn4ktf4DYXPcX/bssMTNLJbALo04= +github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= +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= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -342,6 +358,7 @@ github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONN github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= +github.com/cometbft/cometbft v0.38.0/go.mod h1:5Jz0Z8YsHSf0ZaAqGvi/ifioSdVFPtEGrm8Y9T/993k= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= @@ -357,8 +374,10 @@ 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-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= github.com/cosmos/cosmos-sdk v0.47.3 h1:r0hGmZoAzP2D+MaPaFGHwAaTdFQq3pNpHaUp1BsffbM= github.com/cosmos/cosmos-sdk v0.47.3/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= +github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -367,17 +386,22 @@ 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.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= 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/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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= @@ -389,6 +413,7 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= @@ -436,6 +461,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= @@ -457,6 +483,7 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -497,6 +524,7 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -557,6 +585,7 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -587,15 +616,18 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= 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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1/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= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -607,16 +639,19 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +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= @@ -625,6 +660,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +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/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= @@ -667,6 +703,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -726,6 +763,7 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -745,6 +783,7 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/linxGnu/grocksdb v1.8.4/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= @@ -762,6 +801,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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= @@ -843,10 +884,12 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +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/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -857,6 +900,7 @@ github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6J github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -866,6 +910,7 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= 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= @@ -874,6 +919,7 @@ github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 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= @@ -882,6 +928,7 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 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= @@ -890,6 +937,7 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -904,8 +952,10 @@ 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.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/zerolog v1.31.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= @@ -930,6 +980,7 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= @@ -937,6 +988,7 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -947,6 +999,7 @@ 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.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= 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= @@ -969,6 +1022,7 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -977,6 +1031,7 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= @@ -1000,8 +1055,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= @@ -1021,11 +1078,15 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe 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.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 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.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 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= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1044,6 +1105,7 @@ golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 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= @@ -1057,6 +1119,7 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= 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= @@ -1148,6 +1211,7 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 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= @@ -1175,6 +1239,7 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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= @@ -1265,6 +1330,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1290,11 +1356,14 @@ 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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 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= @@ -1308,6 +1377,7 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1333,6 +1403,7 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn 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= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1435,6 +1506,7 @@ google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= 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= @@ -1554,10 +1626,13 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= 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= @@ -1601,6 +1676,7 @@ google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= @@ -1619,6 +1695,7 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -1664,10 +1741,12 @@ 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 v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/types/delegation.go b/types/delegation.go index 4e66838b..de53d4cb 100644 --- a/types/delegation.go +++ b/types/delegation.go @@ -1,59 +1,99 @@ package types import ( + "math" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" ) type Delegation struct { - // btc_pk is the Bitcoin secp256k1 PK of this BTC delegation + // The Bitcoin secp256k1 PK of this BTC delegation BtcPk *btcec.PublicKey - // val_btc_pk is the Bitcoin secp256k1 PK of the BTC validator that + // The Bitcoin secp256k1 PKs of the BTC validators that // this BTC delegation delegates to - ValBtcPk *btcec.PublicKey - // start_height is the start BTC height of the BTC delegation + ValBtcPks []*btcec.PublicKey + // The start BTC height of the BTC delegation // it is the start BTC height of the timelock StartHeight uint64 - // end_height is the end height of the BTC delegation + // The end height of the BTC delegation // it is the end BTC height of the timelock - w EndHeight uint64 - // staking_tx_hex is the hex string of the staking tx + // The total amount of BTC stakes in this delegation + // quantified in satoshi + TotalSat uint64 + // The hex string of the staking tx StakingTxHex string - // slashing_tx_hex is the hex string of the slashing tx - // It is partially signed by SK corresponding to btc_pk, but not signed by - // validator or covenant yet. + // The index of the staking output in the staking tx + StakingOutputIdx uint32 + // The hex string of the slashing tx SlashingTxHex string - // covenant_sig is the signature on the slashing tx - // by the covenant (i.e., SK corresponding to covenant_pk in params) + // The signatures on the slashing tx + // by the covenants (i.e., SKs corresponding to covenant_pks in params) // It will be a part of the witness for the staking tx output. - CovenantSig *schnorr.Signature - // if this object is present it menans that staker requested undelegation, and whole - // delegation is being undelegated. - // directly in delegation object + CovenantSigs []*CovenantAdaptorSigInfo + // if this object is present it means that staker requested undelegation, and whole + // delegation is being undelegated directly in delegation object BtcUndelegation *Undelegation } +// HasCovenantQuorum returns whether a delegation has sufficient sigs +// from Covenant members to make a quorum +func (d *Delegation) HasCovenantQuorum(quorum uint32) bool { + return uint32(len(d.CovenantSigs)) >= quorum +} + +func (d *Delegation) GetStakingTime() uint16 { + diff := d.EndHeight - d.StartHeight + + if diff > math.MaxUint16 { + // In valid delegation, EndHeight is always greater than StartHeight and it is always uint16 value + panic("invalid delegation in database") + } + + return uint16(diff) +} + // Undelegation signalizes that the delegation is being undelegated type Undelegation struct { - // unbonding_tx_hex is the hex string of the transaction which will transfer the funds from staking + // How long the funds will be locked in the unbonding output + UnbondingTime uint32 + // The hex string of the transaction which will transfer the funds from staking // output to unbonding output. Unbonding output will usually have lower timelock // than staking output. UnbondingTxHex string - // slashing_tx is the hex string of the slashing tx for unbodning transactions + // The hex string of the slashing tx for unbonding transactions // It is partially signed by SK corresponding to btc_pk, but not signed by // validator or covenant yet. SlashingTxHex string - // covenant_slashing_sig is the signature on the slashing tx - // by the covenant (i.e., SK corresponding to covenant_pk in params) + // The signatures on the slashing tx by the covenant + // (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain - CovenantSlashingSig *schnorr.Signature - // covenant_unbonding_sig is the signature on the unbonding tx - // by the covenant (i.e., SK corresponding to covenant_pk in params) - // It must be provided after processing undelagate message by the consumer chain and after - // validator sig will be provided by validator - CovenantUnbondingSig *schnorr.Signature - // validator_unbonding_sig is the signature on the unbonding tx - // by the validator (i.e., SK corresponding to covenant_pk in params) + CovenantSlashingSigs []*CovenantAdaptorSigInfo + // The signatures on the unbonding tx by the covenant + // (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain - ValidatorUnbondingSig *schnorr.Signature + CovenantUnbondingSigs []*CovenantSchnorrSigInfo +} + +func (ud *Undelegation) HasCovenantQuorumOnSlashing(quorum uint32) bool { + return len(ud.CovenantUnbondingSigs) >= int(quorum) +} + +func (ud *Undelegation) HasCovenantQuorumOnUnbonding(quorum uint32) bool { + return len(ud.CovenantUnbondingSigs) >= int(quorum) +} + +func (ud *Undelegation) HasAllSignatures(covenantQuorum uint32) bool { + return ud.HasCovenantQuorumOnUnbonding(covenantQuorum) && ud.HasCovenantQuorumOnSlashing(covenantQuorum) +} + +type CovenantAdaptorSigInfo struct { + Pk *btcec.PublicKey + Sigs [][]byte +} + +type CovenantSchnorrSigInfo struct { + Pk *btcec.PublicKey + Sig *schnorr.Signature } diff --git a/types/errors.go b/types/errors.go deleted file mode 100644 index c950bfd5..00000000 --- a/types/errors.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -import ( - "errors" -) - -var ( - ErrValidatorSlashed = errors.New("the validator has been slashed") - ErrTooFewPubRand = errors.New("the request contains too few public randomness") - ErrBlockNotFound = errors.New("the block is not found") - ErrHeightTooHigh = errors.New("the chain has not reached the given height yet") - ErrInvalidPubRand = errors.New("the public randomness list is invalid") - ErrNoPubRandYet = errors.New("the BTC validator has not committed any public randomness yet") - ErrPubRandNotFound = errors.New("public randomness is not found") - ErrInvalidFinalitySig = errors.New("finality signature is not valid") - ErrDuplicatedFinalitySig = errors.New("the finality signature has been casted before") -) diff --git a/types/key.go b/types/key.go new file mode 100644 index 00000000..b73dcb9d --- /dev/null +++ b/types/key.go @@ -0,0 +1,8 @@ +package types + +import "github.com/btcsuite/btcd/btcec/v2" + +type KeyPair struct { + PublicKey *btcec.PublicKey + PrivateKey *btcec.PrivateKey +} diff --git a/types/params.go b/types/params.go index 007059be..44294200 100644 --- a/types/params.go +++ b/types/params.go @@ -1,6 +1,7 @@ package types import ( + sdkmath "cosmossdk.io/math" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" ) @@ -11,15 +12,18 @@ type StakingParams struct { // W-deep FinalizationTimeoutBlocks uint64 - // Minimum amount of satoshis required for slashing transaction + // Minimum amount of tx fee (quantified in Satoshi) needed for the pre-signed slashing tx MinSlashingTxFeeSat btcutil.Amount - // Bitcoin public key of the current covenant - CovenantPk *btcec.PublicKey + // Bitcoin public keys of the covenant committee + CovenantPks []*btcec.PublicKey // Address to which slashing transactions are sent - SlashingAddress string + SlashingAddress btcutil.Address - // Minimum commission required by the consumer chain - MinCommissionRate string + // Minimum number of signatures needed for the covenant multisignature + CovenantQuorum uint32 + + // The staked amount to be slashed, expressed as a decimal (e.g., 0.5 for 50%). + SlashingRate sdkmath.LegacyDec } diff --git a/val/keyringcontroller.go b/val/keyringcontroller.go index 7c8a2c34..36223d50 100644 --- a/val/keyringcontroller.go +++ b/val/keyringcontroller.go @@ -8,8 +8,10 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdksecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" + + "github.com/babylonchain/btc-validator/types" ) const ( @@ -68,7 +70,7 @@ func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { return kc.kr } -func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*secp256k1.PubKey, error) { +func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*types.KeyPair, error) { keyringAlgos, _ := kc.kr.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { @@ -96,14 +98,12 @@ func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*se return nil, err } - pubKey, err := record.GetPubKey() - if err != nil { - return nil, err - } + privKey := record.GetLocal().PrivKey.GetCachedValue() - switch v := pubKey.(type) { - case *secp256k1.PubKey: - return v, nil + switch v := privKey.(type) { + case *sdksecp256k1.PrivKey: + sk, pk := btcec.PrivKeyFromBytes(v.Key) + return &types.KeyPair{PublicKey: pk, PrivateKey: sk}, nil default: return nil, fmt.Errorf("unsupported key type in keyring") } @@ -121,7 +121,7 @@ func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey, passph return bstypes.NewPoP(bbnPrivKey, btcPrivKey) } -func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*secp256k1.PrivKey, error) { +func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*sdksecp256k1.PrivKey, error) { kc.input.Reset(passphrase) k, err := kc.kr.Key(kc.valName) if err != nil { @@ -131,7 +131,7 @@ func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*secp256k1 privKeyCached := k.GetLocal().PrivKey.GetCachedValue() switch v := privKeyCached.(type) { - case *secp256k1.PrivKey: + case *sdksecp256k1.PrivKey: return v, nil default: return nil, fmt.Errorf("unsupported key type in keyring") diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go index 9f473c12..58f4c27c 100644 --- a/val/keyringcontroller_test.go +++ b/val/keyringcontroller_test.go @@ -8,6 +8,7 @@ import ( "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/sirupsen/logrus" "github.com/stretchr/testify/require" @@ -50,8 +51,9 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) btcPk, err := types.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - bbnPk, err := kc.CreateChainKey(passphrase, hdPath) + keyPair, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) + bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) diff --git a/val/valstore.go b/val/valstore.go index 2ee40e2b..4c578263 100644 --- a/val/valstore.go +++ b/val/valstore.go @@ -4,11 +4,10 @@ import ( "fmt" "math" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" gproto "google.golang.org/protobuf/proto" "github.com/babylonchain/btc-validator/proto" @@ -20,7 +19,7 @@ const ( validatorPrefix = "validator" ) -func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des *stakingtypes.Description, com *sdktypes.Dec) *proto.StoreValidator { +func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des []byte, com *sdkmath.LegacyDec) *proto.StoreValidator { return &proto.StoreValidator{ KeyName: keyName, BabylonPk: babylonPk.Bytes(), diff --git a/valcfg/babylon.go b/valcfg/babylon.go index 2fb59ded..3b6ff58f 100644 --- a/valcfg/babylon.go +++ b/valcfg/babylon.go @@ -3,8 +3,7 @@ package valcfg import ( "time" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + bbncfg "github.com/babylonchain/rpc-client/config" ) type BBNConfig struct { @@ -25,41 +24,43 @@ type BBNConfig struct { } func DefaultBBNConfig() BBNConfig { + dc := bbncfg.DefaultBabylonConfig() // fill up the config from dc config return BBNConfig{ - Key: "node0", - ChainID: "chain-test", - RPCAddr: "http://localhost:26657", - GRPCAddr: "https://localhost:9090", - AccountPrefix: "bbn", - KeyringBackend: keyring.BackendTest, - GasAdjustment: 1.2, - GasPrices: "0.01ubbn", - KeyDirectory: defaultDataDir, - Debug: true, - Timeout: 20 * time.Second, + Key: dc.Key, + ChainID: dc.ChainID, + RPCAddr: dc.RPCAddr, + GRPCAddr: dc.GRPCAddr, + AccountPrefix: dc.AccountPrefix, + KeyringBackend: dc.KeyringBackend, + GasAdjustment: dc.GasAdjustment, + GasPrices: dc.GasPrices, + KeyDirectory: DefaultValdDir, + Debug: dc.Debug, + Timeout: dc.Timeout, // Setting this to relatively low value, out currnet babylon client (lens) will // block for this amout of time to wait for transaction inclusion in block BlockTimeout: 1 * time.Minute, - OutputFormat: "json", - SignModeStr: "direct", + OutputFormat: dc.OutputFormat, + SignModeStr: dc.SignModeStr, } } -func BBNConfigToCosmosProviderConfig(bc *BBNConfig) cosmos.CosmosProviderConfig { - return cosmos.CosmosProviderConfig{ - Key: bc.Key, - ChainID: bc.ChainID, - RPCAddr: bc.RPCAddr, - AccountPrefix: bc.AccountPrefix, - KeyringBackend: bc.KeyringBackend, - GasAdjustment: bc.GasAdjustment, - GasPrices: bc.GasPrices, - KeyDirectory: bc.KeyDirectory, - Debug: bc.Debug, - Timeout: bc.Timeout.String(), - BlockTimeout: bc.BlockTimeout.String(), - OutputFormat: bc.OutputFormat, - SignModeStr: bc.SignModeStr, +func BBNConfigToBabylonConfig(bc *BBNConfig) bbncfg.BabylonConfig { + return bbncfg.BabylonConfig{ + Key: bc.Key, + ChainID: bc.ChainID, + RPCAddr: bc.RPCAddr, + AccountPrefix: bc.AccountPrefix, + KeyringBackend: bc.KeyringBackend, + GasAdjustment: bc.GasAdjustment, + GasPrices: bc.GasPrices, + KeyDirectory: bc.KeyDirectory, + Debug: bc.Debug, + Timeout: bc.Timeout, + BlockTimeout: bc.BlockTimeout, + OutputFormat: bc.OutputFormat, + SignModeStr: bc.SignModeStr, + SubmitterAddress: "", } } From 5257dcd2f1a8b3f84171b34e2f0bf52e89f938c9 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Mon, 4 Dec 2023 06:11:28 +0100 Subject: [PATCH 26/66] Fix make file (#159) --- Makefile | 2 +- go.mod | 5 +- go.sum | 6 - tools/go.mod | 60 ++++++-- tools/go.sum | 407 +++++++++++++++++++++++++++------------------------ 5 files changed, 259 insertions(+), 221 deletions(-) diff --git a/Makefile b/Makefile index 78ef8490..bb2ad0b6 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ test: go test ./... test-e2e: - go install -trimpath $(BABYLON_PKG) + cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e ############################################################################### diff --git a/go.mod b/go.mod index 847cc41c..59775ef0 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.3 github.com/cosmos/cosmos-sdk v0.50.1 github.com/cosmos/go-bip39 v1.0.0 @@ -45,7 +46,6 @@ require ( cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/log v1.2.1 // indirect cosmossdk.io/store v1.0.0 // indirect - cosmossdk.io/tools/confix v0.1.0 // 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 @@ -65,7 +65,6 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -92,8 +91,6 @@ require ( github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/creachadair/atomicfile v0.3.1 // indirect - github.com/creachadair/tomledit v0.0.24 // indirect 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 diff --git a/go.sum b/go.sum index 27f14bd9..911be3ba 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,6 @@ cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= -cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= -cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= @@ -431,12 +429,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0q github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= -github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= -github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= -github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= 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= diff --git a/tools/go.mod b/tools/go.mod index a5beb47b..51c21d95 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -13,23 +13,33 @@ require ( cloud.google.com/go/iam v1.1.3 // indirect cloud.google.com/go/storage v1.30.1 // indirect cosmossdk.io/api v0.7.2 // 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.0 // indirect cosmossdk.io/log v1.2.1 // indirect cosmossdk.io/math v1.2.0 // indirect - cosmossdk.io/tools/rosetta v0.2.1 // indirect + cosmossdk.io/store v1.0.0 // indirect + cosmossdk.io/tools/confix v0.1.0 // 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.12.0 // 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 github.com/99designs/keyring v1.2.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/CosmWasm/wasmd v0.50.0-rc.2 // indirect github.com/CosmWasm/wasmvm v1.5.0 // indirect - github.com/armon/go-metrics v0.4.1 // 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/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/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -41,22 +51,27 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/coinbase/rosetta-sdk-go/types v1.0.0 // 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/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v0.38.0 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect - github.com/confio/ics23/go v0.9.0 // 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-sdk v0.50.1 // 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/ibc-go/v7 v7.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 github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect - github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect - github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/creachadair/atomicfile v0.3.1 // indirect + github.com/creachadair/tomledit v0.0.24 // indirect 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 @@ -65,11 +80,14 @@ require ( 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/docker/distribution v2.8.2+incompatible // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/emicklei/dot v1.6.0 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/getsentry/sentry-go v0.25.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 @@ -95,23 +113,29 @@ require ( 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/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.1 // 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 + github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect 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/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/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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/klauspost/compress v1.17.2 // 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.4 // indirect @@ -119,13 +143,14 @@ require ( 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 v1.0.4 // indirect - github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // 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 github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // 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 @@ -135,15 +160,17 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/rakyll/statik v0.1.7 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.31.0 // indirect + github.com/sagikazarmark/locafero v0.3.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/cobra v1.8.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.17.0 // indirect github.com/stretchr/testify v1.8.4 // indirect @@ -157,10 +184,12 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -175,6 +204,7 @@ require ( gopkg.in/ini.v1 v1.67.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 nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/tools/go.sum b/tools/go.sum index 49813e88..cf095a22 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -32,8 +32,7 @@ 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.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= @@ -71,8 +70,7 @@ 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.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= @@ -113,14 +111,12 @@ 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 v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc= cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= 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= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -178,8 +174,7 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f 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.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= 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= @@ -192,26 +187,38 @@ 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.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= -cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= +cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= -cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= +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= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= -cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= -cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= +cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= -cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= +cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= -cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= -cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= +cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= +cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= +cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= +cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= +cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= +cosmossdk.io/x/evidence v0.1.0/go.mod h1:hTaiiXsoiJ3InMz1uptgF0BnGqROllAN8mwisOMMsfw= +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.12.0 h1:Ry2btjQdrfrje9qZ3iZeZSmDArjgxUJMMcLMrX4wj5U= +cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +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= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= @@ -219,21 +226,22 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +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/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.40.0 h1:3Vvq1m8dPQdvZR+QJc86VIx6QoWAEVnuHxqBPshJvyo= -github.com/CosmWasm/wasmd v0.40.0/go.mod h1:SuxskRBB7+bpwXGhUXaEfdpjg5WKpdxBy7Tm36VRMUU= +github.com/CosmWasm/wasmd v0.50.0-rc.2 h1:CK7bRrAxYo8xooGhAwCRWyJqog+/M/7G1/p1BQVDNNU= github.com/CosmWasm/wasmd v0.50.0-rc.2/go.mod h1:KtrZmXmh/V1ZmQ2/3dU6VRuZ09moRDpRqTL3L/mnPIE= -github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= -github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +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/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -241,9 +249,10 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -255,24 +264,16 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= 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.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= -github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98 h1:mA0BYkWkv4IrOyaFEPweSHproGzuJD3hiUpSGZ1L+Ew= -github.com/babylonchain/babylon-private v0.0.0-20231025095102-7c3744b15d98/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= -github.com/babylonchain/babylon-private v0.0.0-20231109083355-a680fcc5261f/go.mod h1:Omv/7j7d/KioUlGhffrA1uajzYwx959cLElstveJwKc= -github.com/babylonchain/babylon-private v0.0.0-20231123033744-c31e470a8b0d/go.mod h1:nTxsy7JADtFtehkvn4ktf4DYXPcX/bssMTNLJbALo04= +github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= 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= @@ -283,13 +284,14 @@ 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/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.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= -github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 h1:FZR6mILlSI/GDx8ydNVBZAlXlRXsoRBWX2Un64mpfsI= github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= @@ -313,7 +315,8 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= +github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -351,19 +354,26 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +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/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= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= -github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= +github.com/cometbft/cometbft v0.38.0 h1:ogKnpiPX7gxCvqTEF4ly25/wAxUqf181t30P3vqdpdc= github.com/cometbft/cometbft v0.38.0/go.mod h1:5Jz0Z8YsHSf0ZaAqGvi/ifioSdVFPtEGrm8Y9T/993k= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= -github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= -github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= 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= @@ -372,47 +382,44 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV 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-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= +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.47.3 h1:r0hGmZoAzP2D+MaPaFGHwAaTdFQq3pNpHaUp1BsffbM= -github.com/cosmos/cosmos-sdk v0.47.3/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= +github.com/cosmos/cosmos-sdk v0.50.1 h1:2SYwAYqd7ZwtrWxu/J8PwbQV/cDcu90bCr/a78g3lVw= github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= 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= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= -github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= +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 v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +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/ibc-go/v7 v7.0.1/go.mod h1:vEaapV6nuLPQlS+g8IKmxMo6auPi0i7HMv1PhViht/E= +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= +github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +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/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= -github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= 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/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= -github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= +github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= @@ -432,10 +439,12 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +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/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/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= @@ -446,6 +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/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= @@ -458,23 +469,31 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. 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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +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/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= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +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/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= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -492,25 +511,30 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG 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-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +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/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= 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= @@ -522,8 +546,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -583,8 +606,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -596,6 +619,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -614,19 +638,17 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= 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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/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= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -637,20 +659,17 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +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= @@ -658,8 +677,7 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +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/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -667,11 +685,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 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-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -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= @@ -681,11 +694,17 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n 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-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= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y= +github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -693,16 +712,16 @@ github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoD github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -710,6 +729,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -718,6 +739,8 @@ github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0Jr github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -728,7 +751,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= 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/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -747,6 +771,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -756,13 +781,13 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 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 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/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.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 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= @@ -770,19 +795,21 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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.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/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.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= -github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= github.com/linxGnu/grocksdb v1.8.4/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= @@ -791,6 +818,7 @@ 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.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= @@ -799,19 +827,15 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx 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= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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 v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +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/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/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= @@ -833,6 +857,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -849,24 +874,33 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 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= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -876,30 +910,32 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6nYUPxQEP+ReTsceJTKizeuwjWOPUA= 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/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= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -908,8 +944,7 @@ 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.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +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_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -917,8 +952,7 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: 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.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +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/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -926,8 +960,7 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 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= @@ -935,31 +968,31 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= -github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= 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 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +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/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.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +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/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= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= +github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 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= @@ -970,35 +1003,33 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd 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/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/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= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= 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= @@ -1015,13 +1046,12 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +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.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= @@ -1029,22 +1059,23 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= -github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 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.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= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 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/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= @@ -1053,11 +1084,9 @@ 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/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +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.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= @@ -1083,6 +1112,8 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A 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.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.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= @@ -1096,15 +1127,12 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U 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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 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= @@ -1117,8 +1145,7 @@ 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-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +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/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= @@ -1146,7 +1173,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.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +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/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= @@ -1209,8 +1237,7 @@ 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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 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= @@ -1237,8 +1264,7 @@ 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.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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= @@ -1254,7 +1280,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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +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/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= @@ -1354,15 +1381,13 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 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= @@ -1373,10 +1398,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1445,7 +1468,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.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +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/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= @@ -1504,8 +1528,7 @@ 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.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA= google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= 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= @@ -1624,14 +1647,11 @@ 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-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= 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= @@ -1674,8 +1694,7 @@ 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.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= @@ -1693,8 +1712,7 @@ 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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -1702,6 +1720,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1727,8 +1746,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1739,14 +1758,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 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 v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From b04de0e9dab4f52e9d2bf02b790a3b1f13d7ea4a Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Mon, 4 Dec 2023 16:02:10 +0400 Subject: [PATCH 27/66] feat: Refactor to separate validator operation to separate directory (#161) --- .circleci/config.yml | 2 +- Makefile | 8 ++--- clientcontroller/babylon.go | 8 ++--- clientcontroller/interface.go | 9 ++--- {valcfg => config}/babylon.go | 3 +- covenant/Makefile | 33 +------------------ covenant/config/config.go | 9 +++-- covenant/covenant.go | 21 ++++++------ covenant/types.go | 5 +++ eotsmanager/Makefile | 33 +------------------ eotsmanager/proto/eotsmanager.pb.go | 2 +- eotsmanager/types/errors.go | 3 +- go.mod | 2 +- itest/test_manager.go | 4 +-- {service => keyring}/keyring.go | 2 +- {val => keyring}/keyringcontroller.go | 2 +- {val => keyring}/keyringcontroller_test.go | 9 ++--- store/bbolt.go | 7 ++-- testutil/datagen.go | 6 ++-- Dockerfile => validator/Dockerfile | 0 validator/Makefile | 18 ++++++++++ {cmd => validator/cmd}/valcli/admin.go | 2 +- {cmd => validator/cmd}/valcli/daemoncmd.go | 4 +-- {cmd => validator/cmd}/valcli/main.go | 2 +- {cmd => validator/cmd}/vald/main.go | 0 {cmd => validator/cmd}/vald/start.go | 7 ++-- {valcfg => validator/config}/config.go | 8 +++-- {valcfg => validator/config}/dbcfg.go | 0 {valcfg => validator/config}/eotsmanager.go | 0 {valcfg => validator/config}/poller.go | 0 {valcfg => validator/config}/validator.go | 0 {proto => validator/proto}/.clang-format | 0 {proto => validator/proto}/buf.gen.yaml | 0 {proto => validator/proto}/buf.lock | 0 {proto => validator/proto}/buf.yaml | 0 .../proto}/scripts/protocgen.sh | 0 {proto => validator/proto}/validators.go | 9 ----- {proto => validator/proto}/validators.pb.go | 30 ++++++++--------- {proto => validator/proto}/validators.proto | 2 +- .../proto}/validators_grpc.pb.go | 0 {service => validator/service}/app.go | 21 ++++++------ {service => validator/service}/app_test.go | 6 ++-- .../service}/chain_poller.go | 2 +- .../service}/client/rpcclient.go | 2 +- {service => validator/service}/event_loop.go | 2 +- {service => validator/service}/fastsync.go | 0 .../service}/fastsync_test.go | 0 {service => validator/service}/rpcserver.go | 2 +- {service => validator/service}/server.go | 2 +- {service => validator/service}/types.go | 10 ++---- .../service}/validator_instance.go | 8 ++--- .../service}/validator_instance_test.go | 6 ++-- .../service}/validator_manager.go | 10 +++--- .../service}/validator_manager_test.go | 17 +++++----- {val => validator/store}/valstore.go | 6 ++-- {val => validator/store}/valstore_test.go | 6 ++-- 56 files changed, 150 insertions(+), 200 deletions(-) rename {valcfg => config}/babylon.go (98%) create mode 100644 covenant/types.go rename {service => keyring}/keyring.go (98%) rename {val => keyring}/keyringcontroller.go (99%) rename {val => keyring}/keyringcontroller_test.go (83%) rename Dockerfile => validator/Dockerfile (100%) create mode 100644 validator/Makefile rename {cmd => validator/cmd}/valcli/admin.go (95%) rename {cmd => validator/cmd}/valcli/daemoncmd.go (98%) rename {cmd => validator/cmd}/valcli/main.go (94%) rename {cmd => validator/cmd}/vald/main.go (100%) rename {cmd => validator/cmd}/vald/start.go (91%) rename {valcfg => validator/config}/config.go (97%) rename {valcfg => validator/config}/dbcfg.go (100%) rename {valcfg => validator/config}/eotsmanager.go (100%) rename {valcfg => validator/config}/poller.go (100%) rename {valcfg => validator/config}/validator.go (100%) rename {proto => validator/proto}/.clang-format (100%) rename {proto => validator/proto}/buf.gen.yaml (100%) rename {proto => validator/proto}/buf.lock (100%) rename {proto => validator/proto}/buf.yaml (100%) rename {proto => validator/proto}/scripts/protocgen.sh (100%) rename {proto => validator/proto}/validators.go (85%) rename {proto => validator/proto}/validators.pb.go (98%) rename {proto => validator/proto}/validators.proto (99%) rename {proto => validator/proto}/validators_grpc.pb.go (100%) rename {service => validator/service}/app.go (92%) rename {service => validator/service}/app_test.go (94%) rename {service => validator/service}/chain_poller.go (99%) rename {service => validator/service}/client/rpcclient.go (98%) rename {service => validator/service}/event_loop.go (98%) rename {service => validator/service}/fastsync.go (100%) rename {service => validator/service}/fastsync_test.go (100%) rename {service => validator/service}/rpcserver.go (98%) rename {service => validator/service}/server.go (97%) rename {service => validator/service}/types.go (97%) rename {service => validator/service}/validator_instance.go (99%) rename {service => validator/service}/validator_instance_test.go (96%) rename {service => validator/service}/validator_manager.go (97%) rename {service => validator/service}/validator_manager_test.go (88%) rename {val => validator/store}/valstore.go (97%) rename {val => validator/store}/valstore_test.go (88%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0fe66ad8..cc6ecfdd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,7 +50,7 @@ jobs: - aws-ecr/build-image: push-image: false dockerfile: Dockerfile - path: ./ + path: ./validator build-path: ./ tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "$CIRCLE_PROJECT_REPONAME" diff --git a/Makefile b/Makefile index bb2ad0b6..ed9840ec 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ BABYLON_PKG := github.com/babylonchain/babylon/cmd/babylond GO_BIN := ${GOPATH}/bin BTCD_BIN := $(GO_BIN)/btcd -DOCKER := $(shell which docker) CUR_DIR := $(shell pwd) MOCKS_DIR=$(CUR_DIR)/testutil/mocks MOCKGEN_REPO=github.com/golang/mock/mockgen @@ -41,8 +40,9 @@ $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ - $(shell git rev-parse --show-toplevel) + make -C covenant build-docker + make -C validator build-docker + make -C eotsmanager build-docker .PHONY: build build-docker @@ -60,8 +60,8 @@ test-e2e: proto-all: proto-gen proto-gen: - ./proto/scripts/protocgen.sh make -C eotsmanager proto-gen + make -C validator proto-gen .PHONY: proto-gen diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index e0823dfc..bfddfed1 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -26,26 +26,26 @@ import ( "github.com/cosmos/relayer/v2/relayer/provider" "github.com/sirupsen/logrus" + "github.com/babylonchain/btc-validator/config" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" ) var _ ClientController = &BabylonController{} type BabylonController struct { bbnClient *bbnclient.Client - cfg *valcfg.BBNConfig + cfg *config.BBNConfig btcParams *chaincfg.Params logger *logrus.Logger } func NewBabylonController( - cfg *valcfg.BBNConfig, + cfg *config.BBNConfig, btcParams *chaincfg.Params, logger *logrus.Logger, ) (*BabylonController, error) { - bbnConfig := valcfg.BBNConfigToBabylonConfig(cfg) + bbnConfig := config.BBNConfigToBabylonConfig(cfg) if err := bbnConfig.Validate(); err != nil { return nil, fmt.Errorf("invalid config for Babylon client: %w", err) diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 3860b114..d2dafb3c 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -2,14 +2,15 @@ package clientcontroller import ( "fmt" + "github.com/btcsuite/btcd/chaincfg" "math/big" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/sirupsen/logrus" + "github.com/babylonchain/btc-validator/config" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" ) const ( @@ -96,14 +97,14 @@ type CovenantAPIs interface { QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) } -func NewClientController(cfg *valcfg.Config, logger *logrus.Logger) (ClientController, error) { +func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *logrus.Logger) (ClientController, error) { var ( cc ClientController err error ) - switch cfg.ChainName { + switch chainName { case babylonConsumerChainName: - cc, err = NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, logger) + cc, err = NewBabylonController(bbnConfig, netParams, logger) if err != nil { return nil, fmt.Errorf("failed to create Babylon rpc client: %w", err) } diff --git a/valcfg/babylon.go b/config/babylon.go similarity index 98% rename from valcfg/babylon.go rename to config/babylon.go index 3b6ff58f..7567c28a 100644 --- a/valcfg/babylon.go +++ b/config/babylon.go @@ -1,4 +1,4 @@ -package valcfg +package config import ( "time" @@ -35,7 +35,6 @@ func DefaultBBNConfig() BBNConfig { KeyringBackend: dc.KeyringBackend, GasAdjustment: dc.GasAdjustment, GasPrices: dc.GasPrices, - KeyDirectory: DefaultValdDir, Debug: dc.Debug, Timeout: dc.Timeout, // Setting this to relatively low value, out currnet babylon client (lens) will diff --git a/covenant/Makefile b/covenant/Makefile index daf2edcf..8831caeb 100644 --- a/covenant/Makefile +++ b/covenant/Makefile @@ -1,38 +1,7 @@ -BUILDDIR ?= $(CURDIR)/build - DOCKER := $(shell which docker) -CUR_DIR := $(shell pwd) - -ldflags := $(LDFLAGS) -build_tags := $(BUILD_TAGS) -build_args := $(BUILD_ARGS) - -ifeq ($(LINK_STATICALLY),true) - ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v -endif - -ifeq ($(VERBOSE),true) - build_args += -v -endif - -BUILD_TARGETS := build install -BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' - -all: build install - -build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) - -clean: - rm -rf $(BUILDDIR) - -$(BUILD_TARGETS): go.sum $(BUILDDIR)/ - go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... - -$(BUILDDIR)/: - mkdir -p $(BUILDDIR)/ build-docker: $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/covenant -f Dockerfile \ $(shell git rev-parse --show-toplevel) -.PHONY: build build-docker clean +.PHONY: build-docker diff --git a/covenant/config/config.go b/covenant/config/config.go index b8fc3ffc..6a5a18ca 100644 --- a/covenant/config/config.go +++ b/covenant/config/config.go @@ -2,17 +2,16 @@ package config import ( "fmt" + "github.com/sirupsen/logrus" "io" "os" "path/filepath" "time" + "github.com/babylonchain/btc-validator/config" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/valcfg" ) const ( @@ -47,7 +46,7 @@ type Config struct { ActiveNetParams chaincfg.Params - BabylonConfig *valcfg.BBNConfig `group:"babylon" namespace:"babylon"` + BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` } // LoadConfig initializes and parses the config using a config file and command @@ -180,7 +179,7 @@ func FileExists(name string) bool { } func DefaultConfig() Config { - bbnCfg := valcfg.DefaultBBNConfig() + bbnCfg := config.DefaultBBNConfig() bbnCfg.Key = defaultCovenantKeyName bbnCfg.KeyDirectory = DefaultCovenantDir cfg := Config{ diff --git a/covenant/covenant.go b/covenant/covenant.go index 2e5aa025..f350692e 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -2,6 +2,7 @@ package covenant import ( "fmt" + "github.com/babylonchain/btc-validator/keyring" "strings" "sync" "time" @@ -17,9 +18,7 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" ) var ( @@ -40,7 +39,7 @@ type CovenantEmulator struct { pk *btcec.PublicKey cc clientcontroller.ClientController - kc *val.ChainKeyringController + kc *keyring.ChainKeyringController config *covcfg.Config params *types.StakingParams @@ -58,7 +57,7 @@ func NewCovenantEmulator( logger *logrus.Logger, ) (*CovenantEmulator, error) { input := strings.NewReader("") - kr, err := service.CreateKeyring( + kr, err := keyring.CreateKeyring( config.BabylonConfig.KeyDirectory, config.BabylonConfig.ChainID, config.BabylonConfig.KeyringBackend, @@ -68,7 +67,7 @@ func NewCovenantEmulator( return nil, fmt.Errorf("failed to create keyring: %w", err) } - kc, err := val.NewChainKeyringControllerWithKeyring(kr, config.BabylonConfig.Key, input) + kc, err := keyring.NewChainKeyringControllerWithKeyring(kr, config.BabylonConfig.Key, input) if err != nil { return nil, err } @@ -106,7 +105,7 @@ func (ce *CovenantEmulator) UpdateParams() error { } // AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*service.AddCovenantSigResponse, error) { +func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { // 1. the quorum is already achieved, skip sending more sigs if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) { return nil, nil @@ -196,11 +195,11 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*ser return nil, err } - return &service.AddCovenantSigResponse{TxHash: res.TxHash}, nil + return &AddCovenantSigResponse{TxHash: res.TxHash}, nil } // AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon -func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*service.AddCovenantSigResponse, error) { +func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { if del == nil { return nil, fmt.Errorf("btc delegation is nil") } @@ -337,7 +336,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, err } - return &service.AddCovenantSigResponse{ + return &AddCovenantSigResponse{ TxHash: res.TxHash, }, nil } @@ -427,14 +426,14 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.KeyPair, error) { - sdkCtx, err := service.CreateClientCtx( + sdkCtx, err := keyring.CreateClientCtx( keyringDir, chainID, ) if err != nil { return nil, err } - krController, err := val.NewChainKeyringController( + krController, err := keyring.NewChainKeyringController( sdkCtx, keyName, backend, diff --git a/covenant/types.go b/covenant/types.go new file mode 100644 index 00000000..16d99d0f --- /dev/null +++ b/covenant/types.go @@ -0,0 +1,5 @@ +package covenant + +type AddCovenantSigResponse struct { + TxHash string +} diff --git a/eotsmanager/Makefile b/eotsmanager/Makefile index c06703af..b455e724 100644 --- a/eotsmanager/Makefile +++ b/eotsmanager/Makefile @@ -1,41 +1,10 @@ -BUILDDIR ?= $(CURDIR)/build - DOCKER := $(shell which docker) -CUR_DIR := $(shell pwd) - -ldflags := $(LDFLAGS) -build_tags := $(BUILD_TAGS) -build_args := $(BUILD_ARGS) - -ifeq ($(LINK_STATICALLY),true) - ldflags += -linkmode=external -extldflags "-Wl,-z,muldefs -static" -v -endif - -ifeq ($(VERBOSE),true) - build_args += -v -endif - -BUILD_TARGETS := build install -BUILD_FLAGS := --tags "$(build_tags)" --ldflags '$(ldflags)' - -all: build install - -build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) - -clean: - rm -rf $(BUILDDIR) - -$(BUILD_TARGETS): go.sum $(BUILDDIR)/ - go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... - -$(BUILDDIR)/: - mkdir -p $(BUILDDIR)/ build-docker: $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/eots-manager -f Dockerfile \ $(shell git rev-parse --show-toplevel) -.PHONY: build build-docker clean +.PHONY: build-docker ############################################################################### ### Protobuf ### diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index 0b7d3a68..7b295d37 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.28.0 // protoc (unknown) // source: eotsmanager.proto diff --git a/eotsmanager/types/errors.go b/eotsmanager/types/errors.go index 12176765..d5419969 100644 --- a/eotsmanager/types/errors.go +++ b/eotsmanager/types/errors.go @@ -3,6 +3,5 @@ package types import "errors" var ( - ErrValidatorAlreadyExisted = errors.New("the validator has already existed") - ErrSchnorrRandomnessAlreadyCreated = errors.New("the Schnorr randomness has already been created") + ErrValidatorAlreadyExisted = errors.New("the validator has already existed") ) diff --git a/go.mod b/go.mod index 59775ef0..4903f7a0 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.3 github.com/cosmos/cosmos-sdk v0.50.1 github.com/cosmos/go-bip39 v1.0.0 @@ -65,6 +64,7 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect diff --git a/itest/test_manager.go b/itest/test_manager.go index 24aa5a0f..6bd33427 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -30,9 +30,9 @@ import ( covcfg "github.com/babylonchain/btc-validator/covenant/config" "github.com/babylonchain/btc-validator/eotsmanager/client" eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/service" ) var ( diff --git a/service/keyring.go b/keyring/keyring.go similarity index 98% rename from service/keyring.go rename to keyring/keyring.go index 8de0a551..920d0cfd 100644 --- a/service/keyring.go +++ b/keyring/keyring.go @@ -1,4 +1,4 @@ -package service +package keyring import ( "fmt" diff --git a/val/keyringcontroller.go b/keyring/keyringcontroller.go similarity index 99% rename from val/keyringcontroller.go rename to keyring/keyringcontroller.go index 36223d50..d8d40d34 100644 --- a/val/keyringcontroller.go +++ b/keyring/keyringcontroller.go @@ -1,4 +1,4 @@ -package val +package keyring import ( "fmt" diff --git a/val/keyringcontroller_test.go b/keyring/keyringcontroller_test.go similarity index 83% rename from val/keyringcontroller_test.go rename to keyring/keyringcontroller_test.go index 58f4c27c..fa670468 100644 --- a/val/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -1,11 +1,13 @@ -package val_test +package keyring_test import ( + valstore "github.com/babylonchain/btc-validator/validator/store" "math/rand" "os" "testing" "github.com/babylonchain/babylon/types" + valkr "github.com/babylonchain/btc-validator/keyring" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -14,7 +16,6 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/val" ) var ( @@ -32,7 +33,7 @@ func FuzzCreatePoP(f *testing.F) { sdkCtx := testutil.GenSdkContext(r, t) chainID := testutil.GenRandomHexStr(r, 4) - kc, err := val.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) + kc, err := valkr.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) require.NoError(t, err) cfg := testutil.GenEOTSConfig(r, t) @@ -58,7 +59,7 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) require.NoError(t, err) - validator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + validator := valstore.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) btcSig := new(types.BIP340Signature) err = btcSig.Unmarshal(validator.Pop.BtcSig) diff --git a/store/bbolt.go b/store/bbolt.go index d874dbc2..34acd6ef 100644 --- a/store/bbolt.go +++ b/store/bbolt.go @@ -3,10 +3,9 @@ package store import ( "bytes" "errors" + "fmt" bolt "go.etcd.io/bbolt" - - "github.com/babylonchain/btc-validator/valcfg" ) // BboltStore implements the Store interface @@ -165,10 +164,10 @@ func NewBboltStore(path string, bucketName string) (BboltStore, error) { // Set default values if path == "" { - path = valcfg.DefaultDBPath + return BboltStore{}, fmt.Errorf("db path is empty") } if bucketName == "" { - bucketName = valcfg.DefaultDBName + return BboltStore{}, fmt.Errorf("db bucket name is empty") } // Open DB diff --git a/testutil/datagen.go b/testutil/datagen.go index 941e07e2..4cd542f7 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -19,10 +19,10 @@ import ( "github.com/babylonchain/btc-validator/codec" "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" + "github.com/babylonchain/btc-validator/validator/service" ) func GenRandomByteArray(r *rand.Rand, length uint64) []byte { diff --git a/Dockerfile b/validator/Dockerfile similarity index 100% rename from Dockerfile rename to validator/Dockerfile diff --git a/validator/Makefile b/validator/Makefile new file mode 100644 index 00000000..96763996 --- /dev/null +++ b/validator/Makefile @@ -0,0 +1,18 @@ +DOCKER := $(shell which docker) + +build-docker: + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ + $(shell git rev-parse --show-toplevel) + +.PHONY: build-docker + +############################################################################### +### Protobuf ### +############################################################################### + +proto-all: proto-gen + +proto-gen: + ./proto/scripts/protocgen.sh + +.PHONY: proto-gen diff --git a/cmd/valcli/admin.go b/validator/cmd/valcli/admin.go similarity index 95% rename from cmd/valcli/admin.go rename to validator/cmd/valcli/admin.go index 9ed4e15a..7c7f567a 100644 --- a/cmd/valcli/admin.go +++ b/validator/cmd/valcli/admin.go @@ -8,7 +8,7 @@ import ( "github.com/jessevdk/go-flags" "github.com/urfave/cli" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" ) var adminCommands = []cli.Command{ diff --git a/cmd/valcli/daemoncmd.go b/validator/cmd/valcli/daemoncmd.go similarity index 98% rename from cmd/valcli/daemoncmd.go rename to validator/cmd/valcli/daemoncmd.go index 9d73595a..f7bd73d5 100644 --- a/cmd/valcli/daemoncmd.go +++ b/validator/cmd/valcli/daemoncmd.go @@ -11,8 +11,8 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" - dc "github.com/babylonchain/btc-validator/service/client" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + dc "github.com/babylonchain/btc-validator/validator/service/client" ) var daemonCommands = []cli.Command{ diff --git a/cmd/valcli/main.go b/validator/cmd/valcli/main.go similarity index 94% rename from cmd/valcli/main.go rename to validator/cmd/valcli/main.go index 0e60380b..cc9cbd78 100644 --- a/cmd/valcli/main.go +++ b/validator/cmd/valcli/main.go @@ -7,7 +7,7 @@ import ( "github.com/urfave/cli" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" ) func fatal(err error) { diff --git a/cmd/vald/main.go b/validator/cmd/vald/main.go similarity index 100% rename from cmd/vald/main.go rename to validator/cmd/vald/main.go diff --git a/cmd/vald/start.go b/validator/cmd/vald/start.go similarity index 91% rename from cmd/vald/start.go rename to validator/cmd/vald/start.go index 6fb43ac6..22c2fbed 100644 --- a/cmd/vald/start.go +++ b/validator/cmd/vald/start.go @@ -7,9 +7,8 @@ import ( "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/service" ) const ( @@ -33,7 +32,7 @@ var startValidator = cli.Command{ cli.StringFlag{ Name: configFileFlag, Usage: "The path to the covenant config file", - Value: covcfg.DefaultConfigFile, + Value: valcfg.DefaultConfigFile, }, cli.StringFlag{ Name: valPkFlag, diff --git a/valcfg/config.go b/validator/config/config.go similarity index 97% rename from valcfg/config.go rename to validator/config/config.go index aa87d922..ffad175c 100644 --- a/valcfg/config.go +++ b/validator/config/config.go @@ -2,6 +2,7 @@ package valcfg import ( "fmt" + "github.com/babylonchain/btc-validator/config" "io" "net" "os" @@ -25,6 +26,7 @@ const ( defaultLogLevel = "info" defaultLogDirname = "logs" defaultLogFilename = "vald.log" + defaultValidatorKeyName = "btc-validator" DefaultRPCPort = 15812 defaultConfigFileName = "vald.conf" defaultNumPubRand = 100 @@ -89,7 +91,7 @@ type Config struct { EOTSManagerConfig *EOTSManagerConfig `group:"eotsmanagerconfig" namespace:"eotsmanagerconfig"` - BabylonConfig *BBNConfig `group:"babylon" namespace:"babylon"` + BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` @@ -97,7 +99,9 @@ type Config struct { } func DefaultConfig() Config { - bbnCfg := DefaultBBNConfig() + bbnCfg := config.DefaultBBNConfig() + bbnCfg.Key = defaultValidatorKeyName + bbnCfg.KeyDirectory = DefaultValdDir dbCfg := DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() diff --git a/valcfg/dbcfg.go b/validator/config/dbcfg.go similarity index 100% rename from valcfg/dbcfg.go rename to validator/config/dbcfg.go diff --git a/valcfg/eotsmanager.go b/validator/config/eotsmanager.go similarity index 100% rename from valcfg/eotsmanager.go rename to validator/config/eotsmanager.go diff --git a/valcfg/poller.go b/validator/config/poller.go similarity index 100% rename from valcfg/poller.go rename to validator/config/poller.go diff --git a/valcfg/validator.go b/validator/config/validator.go similarity index 100% rename from valcfg/validator.go rename to validator/config/validator.go diff --git a/proto/.clang-format b/validator/proto/.clang-format similarity index 100% rename from proto/.clang-format rename to validator/proto/.clang-format diff --git a/proto/buf.gen.yaml b/validator/proto/buf.gen.yaml similarity index 100% rename from proto/buf.gen.yaml rename to validator/proto/buf.gen.yaml diff --git a/proto/buf.lock b/validator/proto/buf.lock similarity index 100% rename from proto/buf.lock rename to validator/proto/buf.lock diff --git a/proto/buf.yaml b/validator/proto/buf.yaml similarity index 100% rename from proto/buf.yaml rename to validator/proto/buf.yaml diff --git a/proto/scripts/protocgen.sh b/validator/proto/scripts/protocgen.sh similarity index 100% rename from proto/scripts/protocgen.sh rename to validator/proto/scripts/protocgen.sh diff --git a/proto/validators.go b/validator/proto/validators.go similarity index 85% rename from proto/validators.go rename to validator/proto/validators.go index 29a5ce3b..45128f06 100644 --- a/proto/validators.go +++ b/validator/proto/validators.go @@ -16,15 +16,6 @@ func (v *StoreValidator) GetBabylonPK() *secp256k1.PubKey { } } -func NewBabylonPkFromHex(hexStr string) (*secp256k1.PubKey, error) { - pkBytes, err := hex.DecodeString(hexStr) - if err != nil { - return nil, err - } - - return &secp256k1.PubKey{Key: pkBytes}, nil -} - func (v *StoreValidator) GetBabylonPkHexString() string { return hex.EncodeToString(v.BabylonPk) } diff --git a/proto/validators.pb.go b/validator/proto/validators.pb.go similarity index 98% rename from proto/validators.pb.go rename to validator/proto/validators.pb.go index ae10ec24..163e22e2 100644 --- a/proto/validators.pb.go +++ b/validator/proto/validators.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.28.0 // protoc (unknown) // source: validators.proto @@ -25,19 +25,18 @@ const ( // ValidatorStatus is the status of a BTC validator // a Validator object has 4 states: -// - Created - created and managed by validator client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, 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. -// Validator was already active. -// +// - Created - created and managed by validator client, not registered to +// babylon yet +// - Registered - created and registered to Babylon, 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. +// Validator was already active. // Valid State Transactions: -// - Created -> Registered -// - Registered -> Active -// - Active -> Inactive -// - Inactive -> Active +// - Created -> Registered +// - Registered -> Active +// - Active -> Inactive +// - Inactive -> Active type ValidatorStatus int32 const ( @@ -1274,10 +1273,11 @@ var file_validators_proto_rawDesc = []byte{ 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x37, 0x5a, 0x35, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/validators.proto b/validator/proto/validators.proto similarity index 99% rename from proto/validators.proto rename to validator/proto/validators.proto index 17ba1784..66aa0531 100644 --- a/proto/validators.proto +++ b/validator/proto/validators.proto @@ -6,7 +6,7 @@ import "gogoproto/gogo.proto"; import "cosmos/staking/v1beta1/staking.proto"; import "cosmos_proto/cosmos.proto"; -option go_package = "github.com/babylonchain/btc-validator/proto"; +option go_package = "github.com/babylonchain/btc-validator/validator/proto"; service BtcValidators { // GetInfo returns the information of the daemon diff --git a/proto/validators_grpc.pb.go b/validator/proto/validators_grpc.pb.go similarity index 100% rename from proto/validators_grpc.pb.go rename to validator/proto/validators_grpc.pb.go diff --git a/service/app.go b/validator/service/app.go similarity index 92% rename from service/app.go rename to validator/service/app.go index 362f5ef6..9bc26117 100644 --- a/service/app.go +++ b/validator/service/app.go @@ -8,6 +8,7 @@ import ( sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + valkr "github.com/babylonchain/btc-validator/keyring" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -16,10 +17,10 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/client" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/val" + valstore "github.com/babylonchain/btc-validator/validator/store" ) type ValidatorApp struct { @@ -37,7 +38,7 @@ type ValidatorApp struct { cc clientcontroller.ClientController kr keyring.Keyring - vs *val.ValidatorStore + vs *valstore.ValidatorStore config *valcfg.Config logger *logrus.Logger input *strings.Reader @@ -54,7 +55,7 @@ func NewValidatorAppFromConfig( config *valcfg.Config, logger *logrus.Logger, ) (*ValidatorApp, error) { - cc, err := clientcontroller.NewClientController(config, logger) + cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.ActiveNetParams, logger) if err != nil { return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) } @@ -92,7 +93,7 @@ func NewValidatorApp( logger *logrus.Logger, ) (*ValidatorApp, error) { input := strings.NewReader("") - kr, err := CreateKeyring( + kr, err := valkr.CreateKeyring( config.BabylonConfig.KeyDirectory, config.BabylonConfig.ChainID, config.BabylonConfig.KeyringBackend, @@ -102,7 +103,7 @@ func NewValidatorApp( return nil, fmt.Errorf("failed to create keyring: %w", err) } - valStore, err := val.NewValidatorStore(config.DatabaseConfig) + valStore, err := valstore.NewValidatorStore(config.DatabaseConfig) if err != nil { return nil, fmt.Errorf("failed to open the store for validators: %w", err) } @@ -134,7 +135,7 @@ func (app *ValidatorApp) GetConfig() *valcfg.Config { return app.config } -func (app *ValidatorApp) GetValidatorStore() *val.ValidatorStore { +func (app *ValidatorApp) GetValidatorStore() *valstore.ValidatorStore { return app.vs } @@ -325,7 +326,7 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, err } - kr, err := val.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) + kr, err := valkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) if err != nil { return nil, err } @@ -346,7 +347,7 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) } - validator := val.NewStoreValidator(pk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) + validator := valstore.NewStoreValidator(pk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) if err := app.vs.SaveValidator(validator); err != nil { return nil, fmt.Errorf("failed to save validator: %w", err) diff --git a/service/app_test.go b/validator/service/app_test.go similarity index 94% rename from service/app_test.go rename to validator/service/app_test.go index 9237d50f..f65f8398 100644 --- a/service/app_test.go +++ b/validator/service/app_test.go @@ -12,11 +12,11 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" + "github.com/babylonchain/btc-validator/validator/service" ) var ( diff --git a/service/chain_poller.go b/validator/service/chain_poller.go similarity index 99% rename from service/chain_poller.go rename to validator/service/chain_poller.go index 046e73dd..0ddf8047 100644 --- a/service/chain_poller.go +++ b/validator/service/chain_poller.go @@ -10,7 +10,7 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/types" - cfg "github.com/babylonchain/btc-validator/valcfg" + cfg "github.com/babylonchain/btc-validator/validator/config" ) var ( diff --git a/service/client/rpcclient.go b/validator/service/client/rpcclient.go similarity index 98% rename from service/client/rpcclient.go rename to validator/service/client/rpcclient.go index 58dba473..e8793550 100644 --- a/service/client/rpcclient.go +++ b/validator/service/client/rpcclient.go @@ -10,7 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/validator/proto" ) type ValidatorServiceGRpcClient struct { diff --git a/service/event_loop.go b/validator/service/event_loop.go similarity index 98% rename from service/event_loop.go rename to validator/service/event_loop.go index bad8b163..a4ea4bde 100644 --- a/service/event_loop.go +++ b/validator/service/event_loop.go @@ -5,7 +5,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/validator/proto" ) // main event loop for the validator app diff --git a/service/fastsync.go b/validator/service/fastsync.go similarity index 100% rename from service/fastsync.go rename to validator/service/fastsync.go diff --git a/service/fastsync_test.go b/validator/service/fastsync_test.go similarity index 100% rename from service/fastsync_test.go rename to validator/service/fastsync_test.go diff --git a/service/rpcserver.go b/validator/service/rpcserver.go similarity index 98% rename from service/rpcserver.go rename to validator/service/rpcserver.go index ef1095cd..9e0848d8 100644 --- a/service/rpcserver.go +++ b/validator/service/rpcserver.go @@ -11,8 +11,8 @@ import ( bbntypes "github.com/babylonchain/babylon/types" "google.golang.org/grpc" - "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/version" ) diff --git a/service/server.go b/validator/service/server.go similarity index 97% rename from service/server.go rename to validator/service/server.go index 5e8c0ff9..59b9443b 100644 --- a/service/server.go +++ b/validator/service/server.go @@ -10,7 +10,7 @@ import ( "github.com/sirupsen/logrus" "google.golang.org/grpc" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" ) // Server is the main daemon construct for the BTC-Validator server. It handles diff --git a/service/types.go b/validator/service/types.go similarity index 97% rename from service/types.go rename to validator/service/types.go index 0c710b67..ecf5ace8 100644 --- a/service/types.go +++ b/validator/service/types.go @@ -10,8 +10,8 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/sirupsen/logrus" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/val" + "github.com/babylonchain/btc-validator/validator/proto" + valstore "github.com/babylonchain/btc-validator/validator/store" ) type createValidatorResponse struct { @@ -52,10 +52,6 @@ type RegisterValidatorResponse struct { TxHash string } -type AddCovenantSigResponse struct { - TxHash string -} - type CreateValidatorResult struct { ValPk *bbntypes.BIP340PubKey } @@ -63,7 +59,7 @@ type CreateValidatorResult struct { type valState struct { mu sync.Mutex v *proto.StoreValidator - s *val.ValidatorStore + s *valstore.ValidatorStore } func (vs *valState) getStoreValidator() *proto.StoreValidator { diff --git a/service/validator_instance.go b/validator/service/validator_instance.go similarity index 99% rename from service/validator_instance.go rename to validator/service/validator_instance.go index 20eca70d..40b401d6 100644 --- a/service/validator_instance.go +++ b/validator/service/validator_instance.go @@ -19,10 +19,10 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + valstore "github.com/babylonchain/btc-validator/validator/store" ) type ValidatorInstance struct { @@ -56,7 +56,7 @@ type ValidatorInstance struct { func NewValidatorInstance( valPk *bbntypes.BIP340PubKey, cfg *valcfg.Config, - s *val.ValidatorStore, + s *valstore.ValidatorStore, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, passphrase string, diff --git a/service/validator_instance_test.go b/validator/service/validator_instance_test.go similarity index 96% rename from service/validator_instance_test.go rename to validator/service/validator_instance_test.go index 04b6f1f9..ef245f4c 100644 --- a/service/validator_instance_test.go +++ b/validator/service/validator_instance_test.go @@ -11,11 +11,11 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" + "github.com/babylonchain/btc-validator/validator/service" ) func FuzzCommitPubRandList(f *testing.F) { diff --git a/service/validator_manager.go b/validator/service/validator_manager.go similarity index 97% rename from service/validator_manager.go rename to validator/service/validator_manager.go index 17cdc651..89249f1d 100644 --- a/service/validator_manager.go +++ b/validator/service/validator_manager.go @@ -14,10 +14,10 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/proto" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" + valstore "github.com/babylonchain/btc-validator/validator/store" ) const instanceTerminatingMsg = "terminating the validator instance due to critical error" @@ -41,7 +41,7 @@ type ValidatorManager struct { vals map[string]*ValidatorInstance // needed for initiating validator instances - vs *val.ValidatorStore + vs *valstore.ValidatorStore config *valcfg.Config cc clientcontroller.ClientController em eotsmanager.EOTSManager @@ -52,7 +52,7 @@ type ValidatorManager struct { quit chan struct{} } -func NewValidatorManager(vs *val.ValidatorStore, +func NewValidatorManager(vs *valstore.ValidatorStore, config *valcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, diff --git a/service/validator_manager_test.go b/validator/service/validator_manager_test.go similarity index 88% rename from service/validator_manager_test.go rename to validator/service/validator_manager_test.go index 6025573e..e2ac1da2 100644 --- a/service/validator_manager_test.go +++ b/validator/service/validator_manager_test.go @@ -1,6 +1,7 @@ package service_test import ( + "github.com/babylonchain/btc-validator/keyring" "math/rand" "os" "strings" @@ -16,13 +17,13 @@ import ( "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/testutil/mocks" "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" + "github.com/babylonchain/btc-validator/validator/service" + valstore "github.com/babylonchain/btc-validator/validator/store" ) var ( @@ -95,7 +96,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c logger := logrus.New() input := strings.NewReader("") - kr, err := service.CreateKeyring( + kr, err := keyring.CreateKeyring( cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, cfg.BabylonConfig.KeyringBackend, @@ -103,7 +104,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c ) require.NoError(t, err) - valStore, err := val.NewValidatorStore(cfg.DatabaseConfig) + valStore, err := valstore.NewValidatorStore(cfg.DatabaseConfig) require.NoError(t, err) eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) @@ -117,7 +118,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c // create registered validator keyName := datagen.GenRandomHexStr(r, 10) chainID := datagen.GenRandomHexStr(r, 10) - kc, err := val.NewChainKeyringControllerWithKeyring(kr, keyName, input) + kc, err := keyring.NewChainKeyringControllerWithKeyring(kr, keyName, input) require.NoError(t, err) btcPkBytes, err := em.CreateKey(keyName, passphrase, hdPath) require.NoError(t, err) @@ -131,7 +132,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) require.NoError(t, err) - storedValidator := val.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + storedValidator := valstore.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) storedValidator.Status = proto.ValidatorStatus_REGISTERED err = valStore.SaveValidator(storedValidator) require.NoError(t, err) diff --git a/val/valstore.go b/validator/store/valstore.go similarity index 97% rename from val/valstore.go rename to validator/store/valstore.go index 4c578263..cbc6c61a 100644 --- a/val/valstore.go +++ b/validator/store/valstore.go @@ -1,4 +1,4 @@ -package val +package store import ( "fmt" @@ -10,9 +10,9 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" gproto "google.golang.org/protobuf/proto" - "github.com/babylonchain/btc-validator/proto" + "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/valcfg" + valcfg "github.com/babylonchain/btc-validator/validator/config" ) const ( diff --git a/val/valstore_test.go b/validator/store/valstore_test.go similarity index 88% rename from val/valstore_test.go rename to validator/store/valstore_test.go index dadce32b..39f4c8a2 100644 --- a/val/valstore_test.go +++ b/validator/store/valstore_test.go @@ -1,4 +1,4 @@ -package val_test +package store_test import ( "math/rand" @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/val" + valstore "github.com/babylonchain/btc-validator/validator/store" ) // FuzzValidators tests save and list validators properly @@ -18,7 +18,7 @@ func FuzzValidatorStore(f *testing.F) { r := rand.New(rand.NewSource(seed)) dbcfg := testutil.GenDBConfig(r, t) - vs, err := val.NewValidatorStore(dbcfg) + vs, err := valstore.NewValidatorStore(dbcfg) require.NoError(t, err) defer func() { From eebea0398de4fff877f72edbeec1ebebeeb3be7d Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 5 Dec 2023 15:00:51 +0800 Subject: [PATCH 28/66] chore: Replace logrus with zap as logger (#164) --- clientcontroller/babylon.go | 8 +- clientcontroller/interface.go | 7 +- covenant/config/config.go | 32 +-- covenant/covenant.go | 74 +++--- covenant/covenant_test.go | 4 +- covenant/service/server.go | 8 +- eotsmanager/cmd/eotsd/main.go | 4 +- eotsmanager/config/config.go | 32 +-- eotsmanager/localmanager.go | 12 +- eotsmanager/localmanager_test.go | 6 +- eotsmanager/service/server.go | 10 +- go.mod | 7 +- go.sum | 9 +- itest/e2e_test.go | 8 +- itest/eotsmanager_handler.go | 4 +- itest/test_manager.go | 38 +-- keyring/keyringcontroller_test.go | 11 +- log/log.go | 56 ++++ validator/config/config.go | 38 ++- validator/service/app.go | 129 +++++++++- validator/service/app_test.go | 4 +- validator/service/chain_poller.go | 66 +++-- validator/service/event_loop.go | 111 -------- validator/service/fastsync.go | 13 +- validator/service/server.go | 10 +- validator/service/types.go | 30 +-- validator/service/validator_instance.go | 255 ++++++++++--------- validator/service/validator_instance_test.go | 4 +- validator/service/validator_manager.go | 80 +++--- validator/service/validator_manager_test.go | 8 +- 30 files changed, 544 insertions(+), 534 deletions(-) create mode 100644 log/log.go delete mode 100644 validator/service/event_loop.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index bfddfed1..cb22b7bb 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -24,7 +24,7 @@ import ( sdkquery "github.com/cosmos/cosmos-sdk/types/query" sttypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/config" "github.com/babylonchain/btc-validator/types" @@ -36,13 +36,13 @@ type BabylonController struct { bbnClient *bbnclient.Client cfg *config.BBNConfig btcParams *chaincfg.Params - logger *logrus.Logger + logger *zap.Logger } func NewBabylonController( cfg *config.BBNConfig, btcParams *chaincfg.Params, - logger *logrus.Logger, + logger *zap.Logger, ) (*BabylonController, error) { bbnConfig := config.BBNConfigToBabylonConfig(cfg) @@ -683,7 +683,6 @@ func (bc *BabylonController) CreateBTCDelegation( return nil, err } - bc.logger.Infof("successfully submitted a BTC delegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) return &types.TxResponse{TxHash: res.TxHash}, nil } @@ -709,7 +708,6 @@ func (bc *BabylonController) CreateBTCUndelegation( return nil, err } - bc.logger.Infof("successfully submitted a BTC undelegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) return res, nil } diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index d2dafb3c..d0d6edda 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -2,12 +2,13 @@ package clientcontroller import ( "fmt" - "github.com/btcsuite/btcd/chaincfg" "math/big" + "github.com/btcsuite/btcd/chaincfg" + "go.uber.org/zap" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/config" "github.com/babylonchain/btc-validator/types" @@ -97,7 +98,7 @@ type CovenantAPIs interface { QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) } -func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *logrus.Logger) (ClientController, error) { +func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { var ( cc ClientController err error diff --git a/covenant/config/config.go b/covenant/config/config.go index 6a5a18ca..89fdbad0 100644 --- a/covenant/config/config.go +++ b/covenant/config/config.go @@ -2,16 +2,19 @@ package config import ( "fmt" - "github.com/sirupsen/logrus" "io" "os" "path/filepath" "time" - "github.com/babylonchain/btc-validator/config" + "go.uber.org/zap" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" + + "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/btc-validator/log" ) const ( @@ -57,7 +60,7 @@ type Config struct { // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { +func LoadConfig(filePath string) (*Config, *zap.Logger, error) { // Pre-parse the command line options to pick up an alternative config // file. preCfg := DefaultConfig() @@ -86,18 +89,11 @@ func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { configFileError = err } - cfgLogger := logrus.New() - cfgLogger.Out = os.Stdout // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { return nil, nil, err } - logRuslLevel, err := logrus.ParseLevel(cfg.LogLevel) - if err != nil { - return nil, nil, err - } - // At this point we know config is valid, create logger which also log to file logFilePath := filepath.Join(cfg.CovenantDir, defaultLogFilename) f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) @@ -106,20 +102,21 @@ func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { } mw := io.MultiWriter(os.Stdout, f) - cfgLogger.SetOutput(mw) - cfgLogger.SetLevel(logRuslLevel) + cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) + if err != nil { + return nil, nil, err + } // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. if configFileError != nil { - cfgLogger.Warnf("%v", configFileError) if cfg.DumpCfg { - cfgLogger.Infof("Writing configuration file to %s", filePath) + cfgLogger.Info("Writing configuration file", zap.String("path", filePath)) fileParser := flags.NewParser(&cfg, flags.Default) err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) if err != nil { - cfgLogger.Warnf("Error writing configuration file: %v", err) + cfgLogger.Error("Error writing configuration file", zap.Error(err)) return nil, nil, err } } @@ -161,11 +158,6 @@ func (cfg *Config) Validate() error { return fmt.Errorf("unsupported Bitcoin network: %s", cfg.BitcoinNetwork) } - _, err = logrus.ParseLevel(cfg.LogLevel) - if err != nil { - return err - } - return nil } diff --git a/covenant/covenant.go b/covenant/covenant.go index f350692e..29335446 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -2,11 +2,14 @@ package covenant import ( "fmt" - "github.com/babylonchain/btc-validator/keyring" "strings" "sync" "time" + "go.uber.org/zap" + + "github.com/babylonchain/btc-validator/keyring" + "github.com/avast/retry-go/v4" "github.com/babylonchain/babylon/btcstaking" asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" @@ -14,7 +17,6 @@ import ( bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" - "github.com/sirupsen/logrus" "github.com/babylonchain/btc-validator/clientcontroller" covcfg "github.com/babylonchain/btc-validator/covenant/config" @@ -43,7 +45,7 @@ type CovenantEmulator struct { config *covcfg.Config params *types.StakingParams - logger *logrus.Logger + logger *zap.Logger // input is used to pass passphrase to the keyring input *strings.Reader @@ -54,7 +56,7 @@ func NewCovenantEmulator( config *covcfg.Config, cc clientcontroller.ClientController, passphrase string, - logger *logrus.Logger, + logger *zap.Logger, ) (*CovenantEmulator, error) { input := strings.NewReader("") kr, err := keyring.CreateKeyring( @@ -185,13 +187,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add // 4. submit covenant sigs res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs) - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(btcDel.BtcPk).MarshalHex() if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - "validator_pks": btcDel.ValBtcPks, - "delegator_pk": delPkHex, - }).Error("failed to submit Covenant signature") return nil, err } @@ -326,13 +322,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation covSlashingSigs, ) - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(del.BtcPk).MarshalHex() - if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - "delegator_pk": delPkHex, - }).Error("failed to submit covenant signatures") return nil, err } @@ -365,55 +355,52 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { case <-covenantSigTicker.C: // 0. Update slashing address in case it is changed upon governance proposal if err := ce.UpdateParams(); err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get staking params") + ce.logger.Debug("failed to get staking params", zap.Error(err)) continue } // 1. Get all pending delegations first, these are more important than the unbonding ones dels, err := ce.cc.QueryPendingDelegations(limit) if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") + ce.logger.Debug("failed to get pending delegations", zap.Error(err)) continue } if len(dels) == 0 { - ce.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") + ce.logger.Debug("no pending delegations are found") } for _, d := range dels { _, err := ce.AddCovenantSignature(d) if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin delegation") + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(d.BtcPk).MarshalHex() + ce.logger.Error( + "failed to submit covenant signatures to the BTC delegation", + zap.String("del_btc_pk", delPkHex), + zap.Error(err), + ) } } // 2. Get all unbonding delegations unbondingDels, err := ce.cc.QueryUnbondingDelegations(limit) - if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") + ce.logger.Debug("failed to get unbonding delegations", zap.Error(err)) continue } if len(unbondingDels) == 0 { - ce.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") + ce.logger.Debug("no unbonding delegations are found") } for _, d := range unbondingDels { _, err := ce.AddCovenantUnbondingSignatures(d) if err != nil { - ce.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Covenant sig to the Bitcoin undelegation") + delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(d.BtcPk).MarshalHex() + ce.logger.Error( + "failed to submit covenant signatures to the BTC undelegation", + zap.String("del_btc_pk", delPkHex), + zap.Error(err), + ) } } @@ -458,11 +445,12 @@ func (ce *CovenantEmulator) getParamsWithRetry() (*types.StakingParams, error) { } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - ce.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the consumer chain for the staking params") + ce.logger.Debug( + "failed to query the consumer chain for the staking params", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return nil, err } @@ -473,7 +461,7 @@ func (ce *CovenantEmulator) getParamsWithRetry() (*types.StakingParams, error) { func (ce *CovenantEmulator) Start() error { var startErr error ce.startOnce.Do(func() { - ce.logger.Infof("Starting Covenant Emulator") + ce.logger.Info("Starting Covenant Emulator") ce.wg.Add(1) go ce.covenantSigSubmissionLoop() @@ -485,7 +473,7 @@ func (ce *CovenantEmulator) Start() error { func (ce *CovenantEmulator) Stop() error { var stopErr error ce.stopOnce.Do(func() { - ce.logger.Infof("Stopping Covenant Emulator") + ce.logger.Info("Stopping Covenant Emulator") // Always stop the submission loop first to not generate additional events and actions ce.logger.Debug("Stopping submission loop") diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index f0b3f0f2..2899c87a 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -12,8 +12,8 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/covenant" covcfg "github.com/babylonchain/btc-validator/covenant/config" @@ -52,7 +52,7 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) // create and start covenant emulator - ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, logrus.New()) + ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, zap.NewNop()) require.NoError(t, err) err = ce.UpdateParams() diff --git a/covenant/service/server.go b/covenant/service/server.go index b0ed3b4a..36162a8b 100644 --- a/covenant/service/server.go +++ b/covenant/service/server.go @@ -5,7 +5,7 @@ import ( "sync/atomic" "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/covenant" ) @@ -16,7 +16,7 @@ type CovenantServer struct { ce *covenant.CovenantEmulator - logger *logrus.Logger + logger *zap.Logger interceptor signal.Interceptor @@ -24,7 +24,7 @@ type CovenantServer struct { } // NewCovenantServer creates a new server with the given config. -func NewCovenantServer(l *logrus.Logger, ce *covenant.CovenantEmulator, sig signal.Interceptor) *CovenantServer { +func NewCovenantServer(l *zap.Logger, ce *covenant.CovenantEmulator, sig signal.Interceptor) *CovenantServer { return &CovenantServer{ logger: l, ce: ce, @@ -49,7 +49,7 @@ func (s *CovenantServer) RunUntilShutdown() error { return fmt.Errorf("failed to start covenant emulator: %w", err) } - s.logger.Infof("Covenant Emulator Daemon is fully active!") + s.logger.Info("Covenant Emulator Daemon is fully active!") // Wait for shutdown signal from either a graceful server stop or from // the interrupt handler. diff --git a/eotsmanager/cmd/eotsd/main.go b/eotsmanager/cmd/eotsd/main.go index e5795b57..2e4f91cf 100644 --- a/eotsmanager/cmd/eotsd/main.go +++ b/eotsmanager/cmd/eotsd/main.go @@ -6,6 +6,7 @@ import ( "github.com/jessevdk/go-flags" "github.com/lightningnetwork/lnd/signal" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/config" @@ -35,8 +36,7 @@ func main() { eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, cfgLogger) if err != nil { - cfgLogger.Errorf("failed to create EOTS manager: %v", err) - os.Exit(1) + cfgLogger.Fatal("failed to create EOTS manager", zap.Error(err)) } eotsServer := eotsservice.NewEOTSManagerServer(cfg, cfgLogger, eotsManager, shutdownInterceptor) diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 82846bd7..927c2083 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -13,7 +13,9 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/jessevdk/go-flags" - "github.com/sirupsen/logrus" + "go.uber.org/zap" + + "github.com/babylonchain/btc-validator/log" ) const ( @@ -62,7 +64,7 @@ type Config struct { // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig() (*Config, *logrus.Logger, error) { +func LoadConfig() (*Config, *zap.Logger, error) { // Pre-parse the command line options to pick up an alternative config // file. preCfg := DefaultConfig() @@ -116,18 +118,11 @@ func LoadConfig() (*Config, *logrus.Logger, error) { return nil, nil, err } - cfgLogger := logrus.New() - cfgLogger.Out = os.Stdout // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { return nil, nil, err } - logRuslLevel, err := logrus.ParseLevel(cfg.LogLevel) - if err != nil { - return nil, nil, err - } - // TODO: Add log rotation // At this point we know config is valid, create logger which also log to file logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) @@ -137,20 +132,21 @@ func LoadConfig() (*Config, *logrus.Logger, error) { } mw := io.MultiWriter(os.Stdout, f) - cfgLogger.SetOutput(mw) - cfgLogger.SetLevel(logRuslLevel) + cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) + if err != nil { + return nil, nil, err + } // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. if configFileError != nil { - cfgLogger.Warnf("%v", configFileError) if cfg.DumpCfg { - cfgLogger.Infof("Writing configuration file to %s", configFilePath) + cfgLogger.Info("Writing configuration file", zap.String("path", configFilePath)) fileParser := flags.NewParser(&cfg, flags.Default) err := flags.NewIniParser(fileParser).WriteFile(configFilePath, flags.IniIncludeComments|flags.IniIncludeDefaults) if err != nil { - cfgLogger.Warnf("Error writing configuration file: %v", err) + cfgLogger.Error("Error writing configuration file", zap.Error(err)) return nil, nil, err } } @@ -209,13 +205,7 @@ func (cfg *Config) Validate() error { } } - _, err := logrus.ParseLevel(cfg.LogLevel) - - if err != nil { - return err - } - - _, err = net.ResolveTCPAddr("tcp", cfg.RpcListener) + _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) if err != nil { return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) } diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index be485a94..7058c89a 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/codec" "github.com/babylonchain/btc-validator/eotsmanager/config" @@ -31,12 +31,12 @@ var _ EOTSManager = &LocalEOTSManager{} type LocalEOTSManager struct { kr keyring.Keyring es *EOTSStore - logger *logrus.Logger + logger *zap.Logger // input is to send passphrase to kr input *strings.Reader } -func NewLocalEOTSManager(eotsCfg *config.Config, logger *logrus.Logger) (*LocalEOTSManager, error) { +func NewLocalEOTSManager(eotsCfg *config.Config, logger *zap.Logger) (*LocalEOTSManager, error) { keyringDir := eotsCfg.KeyDirectory if keyringDir == "" { homeDir, err := os.UserHomeDir() @@ -127,7 +127,11 @@ func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, return nil, err } - lm.logger.Infof("successfully created an EOTS key %s: %s", name, eotsPk.MarshalHex()) + lm.logger.Info( + "successfully created an EOTS key", + zap.String("key name", name), + zap.String("pk", eotsPk.MarshalHex()), + ) return eotsPk.MustMarshal(), nil } diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go index f944aeab..68ba7a1e 100644 --- a/eotsmanager/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/babylonchain/babylon/testutil/datagen" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/types" @@ -34,7 +34,7 @@ func FuzzCreateKey(f *testing.F) { require.NoError(t, err) }() - lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) + lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, zap.NewNop()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, passphrase, hdPath) @@ -67,7 +67,7 @@ func FuzzCreateRandomnessPairList(f *testing.F) { require.NoError(t, err) }() - lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logrus.New()) + lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, zap.NewNop()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, passphrase, hdPath) diff --git a/eotsmanager/service/server.go b/eotsmanager/service/server.go index 1098e9de..c475e2c8 100644 --- a/eotsmanager/service/server.go +++ b/eotsmanager/service/server.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "google.golang.org/grpc" "github.com/babylonchain/btc-validator/eotsmanager" @@ -21,7 +21,7 @@ type Server struct { started int32 cfg *config.Config - logger *logrus.Logger + logger *zap.Logger rpcServer *rpcServer interceptor signal.Interceptor @@ -30,7 +30,7 @@ type Server struct { } // NewEOTSManagerServer creates a new server with the given config. -func NewEOTSManagerServer(cfg *config.Config, l *logrus.Logger, em eotsmanager.EOTSManager, sig signal.Interceptor) *Server { +func NewEOTSManagerServer(cfg *config.Config, l *zap.Logger, em eotsmanager.EOTSManager, sig signal.Interceptor) *Server { return &Server{ cfg: cfg, logger: l, @@ -73,7 +73,7 @@ func (s *Server) RunUntilShutdown() error { return fmt.Errorf("failed to start gRPC listener: %v", err) } - s.logger.Infof("EOTS Manager Daemon is fully active!") + s.logger.Info("EOTS Manager Daemon is fully active!") // Wait for shutdown signal from either a graceful server stop or from // the interrupt handler. @@ -92,7 +92,7 @@ func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listen for _, lis := range listeners { wg.Add(1) go func(lis net.Listener) { - s.logger.Infof("RPC server listening on %s", lis.Addr()) + s.logger.Info("RPC server listening", zap.String("address", lis.Addr().String())) // Close the ready chan to indicate we are listening. defer lis.Close() diff --git a/go.mod b/go.mod index 4903f7a0..d22cdd7c 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,13 @@ require ( 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/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.14 go.etcd.io/bbolt v1.3.7 go.uber.org/atomic v1.10.0 + go.uber.org/zap v1.26.0 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 ) @@ -153,7 +154,6 @@ require ( 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/jsternberg/zap-logfmt v1.3.0 // indirect github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/klauspost/compress v1.17.2 // indirect @@ -211,7 +211,6 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.15.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.14.0 // indirect @@ -239,7 +238,7 @@ require ( replace ( github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 - github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af + github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 911be3ba..09710a9e 100644 --- a/go.sum +++ b/go.sum @@ -281,8 +281,8 @@ github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8 github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af h1:qzjmuFWgiamSvTXUQT/uDJEn4PA2ndV2Srq0qZauL1c= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231124142452-c4ed1331b6af/go.mod h1:2Dwjgml0C7vO/JSFs2ZJtgGrnP1oa5G21+DDQ6IqQTk= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 h1:Cf1aNeXcSfZczocNxZZ1mM+KU4NDopzaIyi1fSoezxo= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1/go.mod h1:M/tRKH7cc0gpAqCEpHTiaYob/6xoTD4v3A4FZQ3Y3ks= 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= @@ -1063,8 +1063,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx 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.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/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= @@ -1451,7 +1451,6 @@ 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= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index b0d5849d..ee0afd45 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -187,6 +187,12 @@ func TestCovenantLifeCycle(t *testing.T) { return false } - return len(del.BtcUndelegation.CovenantSlashingSigs) != 0 && len(del.BtcUndelegation.CovenantUnbondingSigs) != 0 + if len(del.BtcUndelegation.CovenantSlashingSigs) != 0 && len(del.BtcUndelegation.CovenantUnbondingSigs) != 0 { + return true + } + + return false }, 1*time.Minute, eventuallyPollTime) + + t.Log("covenant signatures for undelegation are submitted") } diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go index f6c9398b..5479fb7b 100644 --- a/itest/eotsmanager_handler.go +++ b/itest/eotsmanager_handler.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/config" @@ -24,7 +24,7 @@ func NewEOTSServerHandler(t *testing.T, cfg *config.Config) *EOTSServerHandler { shutdownInterceptor, err := signal.Intercept() require.NoError(t, err) - logger := logrus.New() + logger := zap.NewNop() eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, logger) require.NoError(t, err) diff --git a/itest/test_manager.go b/itest/test_manager.go index 6bd33427..ea65feed 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -22,8 +22,8 @@ import ( "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/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/covenant" @@ -82,9 +82,7 @@ func StartManager(t *testing.T) *TestManager { testDir, err := tempDirWithName("vale2etest") require.NoError(t, err) - logger := logrus.New() - logger.SetLevel(logrus.DebugLevel) - logger.Out = os.Stdout + logger := zap.NewNop() // 1. prepare covenant key, which will be used as input of Babylon node covenantConfig := defaultCovenantConfig(testDir) @@ -274,27 +272,6 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 return dels } -func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { - var ( - dels []*types.Delegation - err error - ) - // wait for our validator to: - // - detect new unbonding - // - send signature - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(btcPk, 1000) - if err != nil { - return false - } - - return len(dels) == 1 && dels[0].BtcUndelegation != nil - - }, 1*time.Minute, eventuallyPollTime) - - return dels -} - func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { allChecked := true for _, d := range dels { @@ -388,13 +365,6 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo return blocks } -func (tm *TestManager) WaitForValStopped(t *testing.T, valPk *bbntypes.BIP340PubKey) { - require.Eventually(t, func() bool { - _, err := tm.Va.GetValidatorInstance(valPk) - return err != nil - }, eventuallyWaitTimeOut, eventuallyPollTime) -} - func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, valIns *service.ValidatorInstance) { blockBeforeStop, err := tm.BabylonClient.QueryBestBlock() require.NoError(t, err) @@ -506,6 +476,8 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P delegatorSig) require.NoError(t, err) + t.Log("successfully submitted a BTC delegation") + return &TestDelegationData{ DelegatorPrivKey: delBtcPrivKey, DelegatorKey: delBtcPubKey, @@ -574,6 +546,8 @@ func (tm *TestManager) InsertBTCUnbonding( serializedUnbondingTx, uint32(unbondingTime), unbondingValue, testUnbondingInfo.SlashingTx, unbondingSig, ) require.NoError(t, err) + + t.Log("successfully submitted a BTC undelegation") } func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go index fa670468..900e5ce5 100644 --- a/keyring/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -1,19 +1,22 @@ package keyring_test import ( - valstore "github.com/babylonchain/btc-validator/validator/store" "math/rand" "os" "testing" + "go.uber.org/zap" + + valstore "github.com/babylonchain/btc-validator/validator/store" + "github.com/babylonchain/babylon/types" - valkr "github.com/babylonchain/btc-validator/keyring" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + valkr "github.com/babylonchain/btc-validator/keyring" + "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" ) @@ -37,7 +40,7 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) cfg := testutil.GenEOTSConfig(r, t) - em, err := eotsmanager.NewLocalEOTSManager(cfg, logrus.New()) + em, err := eotsmanager.NewLocalEOTSManager(cfg, zap.NewNop()) defer func() { err := os.RemoveAll(sdkCtx.KeyringDir) require.NoError(t, err) diff --git a/log/log.go b/log/log.go new file mode 100644 index 00000000..736c8557 --- /dev/null +++ b/log/log.go @@ -0,0 +1,56 @@ +package log + +import ( + "fmt" + "io" + "strings" + "time" + + zaplogfmt "github.com/jsternberg/zap-logfmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func NewRootLogger(format string, level string, w io.Writer) (*zap.Logger, error) { + cfg := zap.NewProductionEncoderConfig() + cfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00")) + } + cfg.LevelKey = "lvl" + + var enc zapcore.Encoder + switch format { + case "json": + enc = zapcore.NewJSONEncoder(cfg) + case "auto", "console": + enc = zapcore.NewConsoleEncoder(cfg) + case "logfmt": + enc = zaplogfmt.NewEncoder(cfg) + default: + return nil, fmt.Errorf("unrecognized log format %q", format) + } + + var lvl zapcore.Level + switch strings.ToLower(level) { + case "panic": + lvl = zap.PanicLevel + case "fatal": + lvl = zap.FatalLevel + case "error": + lvl = zap.ErrorLevel + case "warn", "warning": + lvl = zap.WarnLevel + case "info": + lvl = zap.InfoLevel + case "debug": + lvl = zap.DebugLevel + default: + return nil, fmt.Errorf("unsupported log level: %s", level) + } + + return zap.New(zapcore.NewCore( + enc, + zapcore.AddSync(w), + lvl, + )), nil +} diff --git a/validator/config/config.go b/validator/config/config.go index ffad175c..16af999e 100644 --- a/validator/config/config.go +++ b/validator/config/config.go @@ -2,7 +2,6 @@ package valcfg import ( "fmt" - "github.com/babylonchain/btc-validator/config" "io" "net" "os" @@ -12,10 +11,14 @@ import ( "strings" "time" + "go.uber.org/zap" + + "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/btc-validator/log" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/sirupsen/logrus" eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" ) @@ -60,7 +63,7 @@ var ( // Config is the main config for the vald cli command type Config struct { - DebugLevel string `long:"debuglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` + LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` // ChainName and ChainID (if any) of the chain config identify a consumer chain ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` ValdDir string `long:"validatorddir" description:"The base directory that contains validator's data, logs, configuration file, etc."` @@ -111,7 +114,7 @@ func DefaultConfig() Config { ChainName: defaultChainName, ConfigFile: DefaultConfigFile, DataDir: defaultDataDir, - DebugLevel: defaultLogLevel, + LogLevel: defaultLogLevel, LogDir: defaultLogDir, DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, @@ -150,7 +153,7 @@ func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) return nil, err } return &eotscfg.Config{ - LogLevel: appCfg.DebugLevel, + LogLevel: appCfg.LogLevel, EOTSDir: appCfg.ValdDir, ConfigFile: appCfg.ConfigFile, KeyDirectory: appCfg.BabylonConfig.KeyDirectory, @@ -167,7 +170,7 @@ func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { +func LoadConfig(filePath string) (*Config, *zap.Logger, error) { // Pre-parse the command line options to pick up an alternative config // file. preCfg := DefaultConfig() @@ -196,16 +199,11 @@ func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { configFileError = err } - cfgLogger := logrus.New() - cfgLogger.Out = os.Stdout // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { return nil, nil, err } - // ignore error here as we already validated the value - logRuslLevel, _ := logrus.ParseLevel(cfg.DebugLevel) - // At this point we know config is valid, create logger which also log to file logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) @@ -214,20 +212,21 @@ func LoadConfig(filePath string) (*Config, *logrus.Logger, error) { } mw := io.MultiWriter(os.Stdout, f) - cfgLogger.Out = mw - cfgLogger.Level = logRuslLevel + cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) + if err != nil { + return nil, nil, err + } // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. if configFileError != nil { - cfgLogger.Warnf("%v", configFileError) if cfg.DumpCfg { - cfgLogger.Infof("Writing configuration file to %s", filePath) + cfgLogger.Info("Writing configuration file", zap.String("path", filePath)) fileParser := flags.NewParser(&cfg, flags.Default) err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) if err != nil { - cfgLogger.Warnf("Error writing configuration file: %v", err) + cfgLogger.Error("Error writing configuration file", zap.Error(err)) return nil, nil, err } } @@ -303,12 +302,7 @@ func (cfg *Config) Validate() error { } } - _, err := logrus.ParseLevel(cfg.DebugLevel) - if err != nil { - return err - } - - _, err = net.ResolveTCPAddr("tcp", cfg.RpcListener) + _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) if err != nil { return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) } diff --git a/validator/service/app.go b/validator/service/app.go index 9bc26117..44c9213c 100644 --- a/validator/service/app.go +++ b/validator/service/app.go @@ -1,6 +1,7 @@ package service import ( + "encoding/hex" "fmt" "strings" "sync" @@ -8,11 +9,12 @@ import ( sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - valkr "github.com/babylonchain/btc-validator/keyring" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/sirupsen/logrus" + "go.uber.org/zap" + + valkr "github.com/babylonchain/btc-validator/keyring" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" @@ -40,7 +42,7 @@ type ValidatorApp struct { kr keyring.Keyring vs *valstore.ValidatorStore config *valcfg.Config - logger *logrus.Logger + logger *zap.Logger input *strings.Reader validatorManager *ValidatorManager @@ -53,7 +55,7 @@ type ValidatorApp struct { func NewValidatorAppFromConfig( config *valcfg.Config, - logger *logrus.Logger, + logger *zap.Logger, ) (*ValidatorApp, error) { cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.ActiveNetParams, logger) if err != nil { @@ -80,7 +82,7 @@ func NewValidatorAppFromConfig( return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) } // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy - logger.Infof("successfully connected to a remote EOTS manager at %s", config.EOTSManagerAddress) + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) } return NewValidatorApp(config, cc, em, logger) @@ -90,7 +92,7 @@ func NewValidatorApp( config *valcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, - logger *logrus.Logger, + logger *zap.Logger, ) (*ValidatorApp, error) { input := strings.NewReader("") kr, err := valkr.CreateKeyring( @@ -229,7 +231,7 @@ func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) func (app *ValidatorApp) Start() error { var startErr error app.startOnce.Do(func() { - app.logger.Infof("Starting ValidatorApp") + app.logger.Info("Starting ValidatorApp") app.eventWg.Add(1) go app.eventLoop() @@ -244,7 +246,7 @@ func (app *ValidatorApp) Start() error { func (app *ValidatorApp) Stop() error { var stopErr error app.stopOnce.Do(func() { - app.logger.Infof("Stopping ValidatorApp") + app.logger.Info("Stopping ValidatorApp") // Always stop the submission loop first to not generate additional events and actions app.logger.Debug("Stopping submission loop") @@ -353,12 +355,115 @@ func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorReques return nil, fmt.Errorf("failed to save validator: %w", err) } - app.logger.WithFields(logrus.Fields{ - "btc_pub_key": valPk.MarshalHex(), - "name": req.keyName, - }).Debug("successfully created a validator") + app.logger.Info("successfully created a validator", + zap.String("btc_pk", valPk.MarshalHex()), + zap.String("key_name", req.keyName), + ) return &createValidatorResponse{ ValPk: valPk, }, nil } + +// main event loop for the validator app +func (app *ValidatorApp) eventLoop() { + defer app.eventWg.Done() + + for { + select { + case req := <-app.createValidatorRequestChan: + res, err := app.handleCreateValidatorRequest(req) + if err != nil { + req.errResponse <- err + continue + } + + req.successResponse <- &createValidatorResponse{ValPk: res.ValPk} + + case ev := <-app.validatorRegisteredEventChan: + valStored, err := app.vs.GetStoreValidator(ev.btcPubKey.MustMarshal()) + if err != nil { + // we always check if the validator is in the DB before sending the registration request + app.logger.Fatal( + "registered validator not found in DB", + zap.String("pk", ev.btcPubKey.MarshalHex()), + zap.Error(err), + ) + } + + // change the status of the validator to registered + err = app.vs.SetValidatorStatus(valStored, proto.ValidatorStatus_REGISTERED) + if err != nil { + app.logger.Fatal("failed to set validator status to REGISTERED", + zap.String("pk", ev.btcPubKey.MarshalHex()), + zap.Error(err), + ) + } + + // return to the caller + ev.successResponse <- &RegisterValidatorResponse{ + bbnPubKey: valStored.GetBabylonPK(), + btcPubKey: valStored.MustGetBIP340BTCPK(), + TxHash: ev.txHash, + } + + case <-app.eventQuit: + app.logger.Debug("exiting main event loop") + return + } + } +} + +func (app *ValidatorApp) registrationLoop() { + defer app.sentWg.Done() + for { + select { + case req := <-app.registerValidatorRequestChan: + // we won't do any retries here to not block the loop for more important messages. + // Most probably it fails due so some user error so we just return the error to the user. + // TODO: need to start passing context here to be able to cancel the request in case of app quiting + popBytes, err := req.pop.Marshal() + if err != nil { + req.errResponse <- err + continue + } + + res, err := app.cc.RegisterValidator( + req.bbnPubKey.Key, + req.btcPubKey.MustToBTCPK(), + popBytes, + req.commission.BigInt(), + req.description, + ) + + if err != nil { + app.logger.Error( + "failed to register validator", + zap.String("pk", req.btcPubKey.MarshalHex()), + zap.Error(err), + ) + req.errResponse <- err + continue + } + + app.logger.Info( + "successfully registered validator on babylon", + zap.String("btc_pk", req.btcPubKey.MarshalHex()), + zap.String("babylon_pk", hex.EncodeToString(req.bbnPubKey.Key)), + zap.String("txHash", res.TxHash), + ) + + app.validatorRegisteredEventChan <- &validatorRegisteredEvent{ + btcPubKey: req.btcPubKey, + bbnPubKey: req.bbnPubKey, + txHash: res.TxHash, + // 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: + app.logger.Debug("exiting registration loop") + return + } + } +} diff --git a/validator/service/app_test.go b/validator/service/app_test.go index f65f8398..2a967495 100644 --- a/validator/service/app_test.go +++ b/validator/service/app_test.go @@ -8,8 +8,8 @@ import ( bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" @@ -48,7 +48,7 @@ func FuzzRegisterValidator(f *testing.F) { mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) - logger := logrus.New() + logger := zap.NewNop() em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) require.NoError(t, err) app, err := service.NewValidatorApp(&cfg, mockClientController, em, logger) diff --git a/validator/service/chain_poller.go b/validator/service/chain_poller.go index 0ddf8047..51b3c137 100644 --- a/validator/service/chain_poller.go +++ b/validator/service/chain_poller.go @@ -6,7 +6,7 @@ import ( "time" "github.com/avast/retry-go/v4" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/types" @@ -37,11 +37,11 @@ type ChainPoller struct { cfg *cfg.ChainPollerConfig blockInfoChan chan *types.BlockInfo nextHeight uint64 - logger *logrus.Logger + logger *zap.Logger } func NewChainPoller( - logger *logrus.Logger, + logger *zap.Logger, cfg *cfg.ChainPollerConfig, cc clientcontroller.ClientController, ) *ChainPoller { @@ -57,7 +57,7 @@ func NewChainPoller( func (cp *ChainPoller) Start(startHeight uint64) error { var startErr error cp.startOnce.Do(func() { - cp.logger.Infof("Starting the chain poller") + cp.logger.Info("Starting the chain poller") err := cp.validateStartHeight(startHeight) if err != nil { @@ -77,7 +77,7 @@ func (cp *ChainPoller) Start(startHeight uint64) error { func (cp *ChainPoller) Stop() error { var stopError error cp.stopOnce.Do(func() { - cp.logger.Infof("Stopping the chain poller") + cp.logger.Info("Stopping the chain poller") err := cp.cc.Close() if err != nil { stopError = err @@ -110,11 +110,12 @@ func (cp *ChainPoller) latestBlockWithRetry() (*types.BlockInfo, error) { } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - cp.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the consumer chain for the latest block") + cp.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return nil, err } @@ -133,12 +134,13 @@ func (cp *ChainPoller) blockWithRetry(height uint64) (*types.BlockInfo, error) { } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - cp.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "height": height, - "error": err, - }).Debug("failed to query the consumer chain for the block") + cp.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Uint64("height", height), + zap.Error(err), + ) })); err != nil { return nil, err } @@ -158,9 +160,7 @@ func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { for { lastestBlock, err := cp.latestBlockWithRetry() if err != nil { - cp.logger.WithFields(logrus.Fields{ - "error": err, - }).Error("Failed to query babylon for the latest status") + cp.logger.Debug("failed to query babylon for the latest status", zap.Error(err)) continue } @@ -182,9 +182,7 @@ func (cp *ChainPoller) waitForActivation() { for { activatedHeight, err := cp.cc.QueryActivatedHeight() if err != nil { - cp.logger.WithFields(logrus.Fields{ - "error": err, - }).Debug("failed to query the consumer chain for the activated height") + cp.logger.Debug("failed to query the consumer chain for the activated height", zap.Error(err)) } else { if cp.GetNextHeight() < activatedHeight { cp.SetNextHeight(activatedHeight) @@ -207,7 +205,7 @@ func (cp *ChainPoller) pollChain() { cp.waitForActivation() - var failedCycles uint64 + var failedCycles uint32 for { // TODO: Handlig of request cancellation, as otherwise shutdown will be blocked @@ -216,24 +214,24 @@ func (cp *ChainPoller) pollChain() { block, err := cp.blockWithRetry(blockToRetrieve) if err != nil { failedCycles++ - cp.logger.WithFields(logrus.Fields{ - "error": err, - "currFailures": failedCycles, - "blockToGet": blockToRetrieve, - }).Error("failed to query the consumer chain for the block") + cp.logger.Debug( + "failed to query the consumer chain for the block", + zap.Uint32("current_failures", failedCycles), + zap.Uint64("block_to_retrieve", blockToRetrieve), + zap.Error(err), + ) } else { // no error and we got the header we wanted to get, bump the state and push // notification about data cp.SetNextHeight(blockToRetrieve + 1) failedCycles = 0 - cp.logger.WithFields(logrus.Fields{ - "height": block.Height, - }).Info("the poller retrieved the block from the consumer chain") + cp.logger.Info("the poller retrieved the block from the consumer chain", + zap.Uint64("height", block.Height)) - // Push the data to the channel. - // If the cosumers are to slow i.e the buffer is full, this will block and we will - // stop retrieving data from the node. + // push the data to the channel + // Note: if the consumer is too slow -- the buffer is full + // the channel will block, and we will stop retrieving data from the node cp.blockInfoChan <- block } diff --git a/validator/service/event_loop.go b/validator/service/event_loop.go deleted file mode 100644 index a4ea4bde..00000000 --- a/validator/service/event_loop.go +++ /dev/null @@ -1,111 +0,0 @@ -package service - -import ( - "encoding/hex" - - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/validator/proto" -) - -// main event loop for the validator app -func (app *ValidatorApp) eventLoop() { - defer app.eventWg.Done() - - for { - select { - case req := <-app.createValidatorRequestChan: - res, err := app.handleCreateValidatorRequest(req) - if err != nil { - req.errResponse <- err - continue - } - - req.successResponse <- &createValidatorResponse{ValPk: res.ValPk} - - case ev := <-app.validatorRegisteredEventChan: - valStored, err := app.vs.GetStoreValidator(ev.btcPubKey.MustMarshal()) - - if err != nil { - // we always check if the validator is in the DB before sending the registration request - app.logger.WithFields(logrus.Fields{ - "btc_pk": ev.btcPubKey.MarshalHex(), - "babylon_pk": hex.EncodeToString(ev.bbnPubKey.Key), - }).Fatal("registered validator not found in DB") - } - - // change the status of the validator to registered - err = app.vs.SetValidatorStatus(valStored, proto.ValidatorStatus_REGISTERED) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "bbn_pk": ev.bbnPubKey, - }).Fatal("err while saving validator to DB") - } - - // return to the caller - ev.successResponse <- &RegisterValidatorResponse{ - bbnPubKey: valStored.GetBabylonPK(), - btcPubKey: valStored.MustGetBIP340BTCPK(), - TxHash: ev.txHash, - } - - case <-app.eventQuit: - app.logger.Debug("exiting main eventLoop") - return - } - } -} - -func (app *ValidatorApp) registrationLoop() { - defer app.sentWg.Done() - for { - select { - case req := <-app.registerValidatorRequestChan: - // we won't do any retries here to not block the loop for more important messages. - // Most probably it fails due so some user error so we just return the error to the user. - // TODO: need to start passing context here to be able to cancel the request in case of app quiting - popBytes, err := req.pop.Marshal() - if err != nil { - req.errResponse <- err - continue - } - - res, err := app.cc.RegisterValidator( - req.bbnPubKey.Key, - req.btcPubKey.MustToBTCPK(), - popBytes, - req.commission.BigInt(), - req.description, - ) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk": req.btcPubKey.MarshalHex(), - "babylon_pk": hex.EncodeToString(req.bbnPubKey.Key), - }).Error("failed to register validator") - req.errResponse <- err - continue - } - - app.logger.WithFields(logrus.Fields{ - "btc_pk": req.btcPubKey.MarshalHex(), - "babylon_pk": hex.EncodeToString(req.bbnPubKey.Key), - "txHash": res.TxHash, - }).Info("successfully registered validator on babylon") - - app.validatorRegisteredEventChan <- &validatorRegisteredEvent{ - btcPubKey: req.btcPubKey, - bbnPubKey: req.bbnPubKey, - txHash: res.TxHash, - // 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: - app.logger.Debug("exiting sentToBabylonLoop") - return - } - } -} diff --git a/validator/service/fastsync.go b/validator/service/fastsync.go index bb6b679c..0a7e7c82 100644 --- a/validator/service/fastsync.go +++ b/validator/service/fastsync.go @@ -3,7 +3,7 @@ package service import ( "fmt" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/types" ) @@ -78,11 +78,12 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe responses = append(responses, res) - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "start_height": catchUpBlocks[0].Height, - "synced_height": syncedHeight, - }).Debug("the validator is catching up by sending finality signatures in a batch") + v.logger.Debug( + "the validator is catching up by sending finality signatures in a batch", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("start_height", catchUpBlocks[0].Height), + zap.Uint64("synced_height", syncedHeight), + ) } v.MustSetLastProcessedHeight(endHeight) diff --git a/validator/service/server.go b/validator/service/server.go index 59b9443b..85ed5fee 100644 --- a/validator/service/server.go +++ b/validator/service/server.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "google.golang.org/grpc" valcfg "github.com/babylonchain/btc-validator/validator/config" @@ -20,7 +20,7 @@ type Server struct { started int32 cfg *valcfg.Config - logger *logrus.Logger + logger *zap.Logger rpcServer *rpcServer interceptor signal.Interceptor @@ -29,7 +29,7 @@ type Server struct { } // NewValidatorServer creates a new server with the given config. -func NewValidatorServer(cfg *valcfg.Config, l *logrus.Logger, v *ValidatorApp, sig signal.Interceptor) *Server { +func NewValidatorServer(cfg *valcfg.Config, l *zap.Logger, v *ValidatorApp, sig signal.Interceptor) *Server { return &Server{ cfg: cfg, logger: l, @@ -72,7 +72,7 @@ func (s *Server) RunUntilShutdown() error { return fmt.Errorf("failed to start gRPC listener: %v", err) } - s.logger.Infof("BTC Validator Daemon is fully active!") + s.logger.Info("BTC Validator Daemon is fully active!") // Wait for shutdown signal from either a graceful server stop or from // the interrupt handler. @@ -91,7 +91,7 @@ func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listen for _, lis := range listeners { wg.Add(1) go func(lis net.Listener) { - s.logger.Infof("RPC server listening on %s", lis.Addr()) + s.logger.Info("RPC server listening", zap.String("address", lis.Addr().String())) // Close the ready chan to indicate we are listening. defer lis.Close() diff --git a/validator/service/types.go b/validator/service/types.go index ecf5ace8..3eaff467 100644 --- a/validator/service/types.go +++ b/validator/service/types.go @@ -8,7 +8,7 @@ import ( btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/validator/proto" valstore "github.com/babylonchain/btc-validator/validator/store" @@ -147,11 +147,8 @@ func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { func (v *ValidatorInstance) MustSetStatus(s proto.ValidatorStatus) { if err := v.SetStatus(s); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "status": s.String(), - }).Fatal("failed to set validator status") + v.logger.Fatal("failed to set validator status", + zap.String("pk", v.GetBtcPkHex()), zap.String("status", s.String())) } } @@ -161,11 +158,8 @@ func (v *ValidatorInstance) SetLastProcessedHeight(height uint64) error { func (v *ValidatorInstance) MustSetLastProcessedHeight(height uint64) { if err := v.SetLastProcessedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last processed height") + v.logger.Fatal("failed to set last processed height", + zap.String("pk", v.GetBtcPkHex()), zap.Uint64("last_processed_height", height)) } } @@ -175,11 +169,8 @@ func (v *ValidatorInstance) SetLastCommittedHeight(height uint64) error { func (v *ValidatorInstance) MustSetLastCommittedHeight(height uint64) { if err := v.SetLastCommittedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last committed height") + v.logger.Fatal("failed to set last committed height", + zap.String("pk", v.GetBtcPkHex()), zap.Uint64("last_committed_height", height)) } } @@ -189,11 +180,8 @@ func (v *ValidatorInstance) updateStateAfterFinalitySigSubmission(height uint64) func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { if err := v.updateStateAfterFinalitySigSubmission(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to update state after finality sig submission") + v.logger.Fatal("failed to update state after finality signature submitted", + zap.String("pk", v.GetBtcPkHex()), zap.Uint64("height", height)) } } diff --git a/validator/service/validator_instance.go b/validator/service/validator_instance.go index 40b401d6..80f8e48c 100644 --- a/validator/service/validator_instance.go +++ b/validator/service/validator_instance.go @@ -14,14 +14,14 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/gogo/protobuf/jsonpb" - "github.com/sirupsen/logrus" "go.uber.org/atomic" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/types" valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" valstore "github.com/babylonchain/btc-validator/validator/store" ) @@ -32,7 +32,7 @@ type ValidatorInstance struct { state *valState cfg *valcfg.Config - logger *logrus.Logger + logger *zap.Logger em eotsmanager.EOTSManager cc clientcontroller.ClientController poller *ChainPoller @@ -61,7 +61,7 @@ func NewValidatorInstance( em eotsmanager.EOTSManager, passphrase string, errChan chan<- *CriticalError, - logger *logrus.Logger, + logger *zap.Logger, ) (*ValidatorInstance, error) { v, err := s.GetStoreValidator(valPk.MustMarshal()) if err != nil { @@ -97,14 +97,15 @@ func (v *ValidatorInstance) Start() error { return fmt.Errorf("the validator instance %s is already started", v.GetBtcPkHex()) } - v.logger.Infof("Starting thread handling validator %s", v.GetBtcPkHex()) + v.logger.Info("Starting validator instance", zap.String("pk", v.GetBtcPkHex())) startHeight, err := v.bootstrap() if err != nil { return fmt.Errorf("failed to bootstrap the validator %s: %w", v.GetBtcPkHex(), err) } - v.logger.Infof("the validator %s has been bootstrapped to %v", v.GetBtcPkHex(), startHeight) + v.logger.Info("the validator %s has been bootstrapped", + zap.String("pk", v.GetBtcPkHex()), zap.Uint64("height", startHeight)) poller := NewChainPoller(v.logger, v.cfg.PollerConfig, v.cc) @@ -158,12 +159,12 @@ func (v *ValidatorInstance) Stop() error { return fmt.Errorf("failed to stop the poller: %w", err) } - v.logger.Infof("stopping thread handling validator %s", v.GetBtcPkHex()) + v.logger.Info("stopping validator instance", zap.String("pk", v.GetBtcPkHex())) close(v.quit) v.wg.Wait() - v.logger.Debugf("the thread handling validator %s is successfully stopped", v.GetBtcPkHex()) + v.logger.Info("the validator instance %s is successfully stopped", zap.String("pk", v.GetBtcPkHex())) return nil } @@ -178,17 +179,18 @@ func (v *ValidatorInstance) finalitySigSubmissionLoop() { for { select { case b := <-v.poller.GetBlockInfoChan(): - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - }).Debug("the validator received a new block, start processing") + v.logger.Debug( + "the validator received a new block, start processing", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("height", b.Height), + ) if b.Height <= v.GetLastProcessedHeight() { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "last_processed_height": v.GetLastProcessedHeight(), - "last_voted_height": v.GetLastVotedHeight(), - }).Debug("the block has been processed before, skip processing") + v.logger.Debug( + "the block has been processed before, skip processing", + zap.Uint64("height", b.Height), + zap.Uint64("last_processed_height", v.GetLastProcessedHeight()), + zap.Uint64("last_voted_height", v.GetLastVotedHeight()), + ) continue } // use the copy of the block to avoid the impact to other receivers @@ -210,13 +212,13 @@ func (v *ValidatorInstance) finalitySigSubmissionLoop() { v.reportCriticalErr(err) continue } - if res != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "tx_hash": res.TxHash, - }).Info("successfully submitted a finality signature to the consumer chain") - } + v.logger.Info( + "successfully submitted a finality signature to the consumer chain", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("height", b.Height), + zap.String("tx_hash", res.TxHash), + ) + case targetBlock := <-v.laggingTargetChan: res, err := v.tryFastSync(targetBlock) v.isLagging.Store(false) @@ -225,20 +227,21 @@ func (v *ValidatorInstance) finalitySigSubmissionLoop() { v.reportCriticalErr(err) continue } - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Error("failed to sync up, will try again later") + v.logger.Debug( + "failed to sync up, will try again later", + zap.String("pk", v.GetBtcPkHex()), + zap.Error(err), + ) continue } // response might be nil if sync is not needed if res != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "tx_hashes": res.Responses, - "synced_height": res.SyncedHeight, - "last_processed_height": res.LastProcessedHeight, - }).Info("successfully synced to the latest block") + v.logger.Info( + "fast sync is finished", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("synced_height", res.SyncedHeight), + zap.Uint64("last_processed_height", res.LastProcessedHeight), + ) // set the poller to fetch blocks that have not been processed v.poller.SetNextHeightAndClearBuffer(v.GetLastProcessedHeight() + 1) @@ -269,12 +272,14 @@ func (v *ValidatorInstance) randomnessCommitmentLoop() { v.reportCriticalErr(err) continue } + // txRes could be nil if no need to commit more randomness if txRes != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "tx_hash": txRes.TxHash, - }).Info("successfully committed public randomness to the consumer chain") + v.logger.Info( + "successfully committed public randomness to the consumer chain", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("last_committed_height", v.GetLastCommittedHeight()), + zap.String("tx_hash", txRes.TxHash), + ) } case <-v.quit: @@ -305,10 +310,11 @@ func (v *ValidatorInstance) checkLaggingLoop() { latestBlock, err := v.getLatestBlockWithRetry() if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Error("failed to get the latest block of the consumer chain") + v.logger.Debug( + "failed to get the latest block of the consumer chain", + zap.String("pk", v.GetBtcPkHex()), + zap.Error(err), + ) continue } @@ -332,10 +338,11 @@ func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSync if err := v.SetLastProcessedHeight(targetBlock.Height); err != nil { return nil, err } - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("insufficient public randomness, jumping to the latest block") + v.logger.Debug( + "insufficient public randomness, jumping to the latest block", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) return nil, nil } @@ -345,10 +352,11 @@ func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSync return nil, err } if lastFinalizedBlocks == nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("no finalized blocks yet, no need to catch up") + v.logger.Debug( + "no finalized blocks yet, no need to catch up", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("height", targetBlock.Height), + ) return nil, nil } @@ -382,21 +390,23 @@ func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSync func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (bool, error) { // check last voted height if v.GetLastVotedHeight() >= b.Height { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "last_voted_height": v.GetLastVotedHeight(), - }).Debug("the block has been voted before, skip voting") + v.logger.Debug( + "the block has been voted before, skip voting", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + zap.Uint64("last_voted_height", v.GetLastVotedHeight()), + ) return false, nil } // check last committed height if v.GetLastCommittedHeight() < b.Height { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "block_height": b.Height, - }).Debug("public rand is not committed, skip voting") + v.logger.Debug( + "public rand is not committed, skip voting", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + zap.Uint64("last_committed_height", v.GetLastCommittedHeight()), + ) return false, nil } @@ -406,10 +416,11 @@ func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (b } if power == 0 { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - }).Debug("the validator does not have voting power, skip voting") + v.logger.Debug( + "the validator does not have voting power, skip voting", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + ) return false, nil } @@ -431,7 +442,7 @@ func (v *ValidatorInstance) checkLagging(currentBlock *types.BlockInfo) bool { // 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 (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { - var failedCycles uint64 + var failedCycles uint32 // we break the for loop if the block is finalized or the signature is successfully submitted // error will be returned if maximum retries have been reached or the query to the consumer chain fails @@ -442,14 +453,16 @@ func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targ if clientcontroller.IsUnrecoverable(err) { return nil, err } - v.logger.WithFields(logrus.Fields{ - "currFailures": failedCycles, - "target_block_height": targetBlock.Height, - "error": err, - }).Error("err submitting finality signature to the consumer chain") + v.logger.Debug( + "failed to submit finality signature to the consumer chain", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint32("current_failures", failedCycles), + zap.Uint64("target_block_height", targetBlock.Height), + zap.Error(err), + ) failedCycles += 1 - if failedCycles > v.cfg.MaxSubmissionRetries { + if failedCycles > uint32(v.cfg.MaxSubmissionRetries) { return nil, fmt.Errorf("reached max failed cycles with err: %w", err) } } else { @@ -464,15 +477,16 @@ func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targ return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) } if finalized { - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("the block is already finalized, skip submission") + v.logger.Debug( + "the block is already finalized, skip submission", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) return nil, nil } case <-v.quit: - v.logger.Debugf("the validator instance %s is closing", v.GetBtcPkHex()) + v.logger.Debug("the validator instance is closing", zap.String("pk", v.GetBtcPkHex())) return nil, nil } } @@ -490,7 +504,7 @@ func (v *ValidatorInstance) checkBlockFinalization(height uint64) (bool, error) // 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 (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { - var failedCycles uint64 + 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 @@ -501,15 +515,16 @@ func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *t if clientcontroller.IsUnrecoverable(err) { return nil, err } - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "currFailures": failedCycles, - "target_block_height": targetBlock.Height, - "error": err, - }).Error("err committing public randomness to the consumer chain") + v.logger.Debug( + "failed to commit public randomness to the consumer chain", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint32("current_failures", failedCycles), + zap.Uint64("target_block_height", targetBlock.Height), + zap.Error(err), + ) failedCycles += 1 - if failedCycles > v.cfg.MaxSubmissionRetries { + if failedCycles > uint32(v.cfg.MaxSubmissionRetries) { return nil, fmt.Errorf("reached max failed cycles with err: %w", err) } } else { @@ -524,15 +539,16 @@ func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *t return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) } if finalized { - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("the block is already finalized, skip submission") + v.logger.Debug( + "the block is already finalized, skip submission", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) return nil, nil } case <-v.quit: - v.logger.Debugf("the validator instance %s is closing", v.GetBtcPkHex()) + v.logger.Debug("the validator instance is closing", zap.String("pk", v.GetBtcPkHex())) return nil, nil } } @@ -553,11 +569,12 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxR // we are running out of the randomness startHeight = lastCommittedHeight + 1 } else { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.btcPk.MarshalHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "current_block_height": tipBlock.Height, - }).Debug("the validator has sufficient public randomness, skip committing more") + v.logger.Debug( + "the validator has sufficient public randomness, skip committing more", + zap.String("pk", v.GetBtcPkHex()), + zap.Uint64("block_height", tipBlock.Height), + zap.Uint64("last_committed_height", v.GetLastCommittedHeight()), + ) return nil, nil } @@ -716,7 +733,7 @@ func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *type for _, ev := range res.Events { if strings.Contains(ev.EventType, "EventSlashedBTCValidator") { evidenceStr := ev.Attributes["evidence"] - v.logger.Debugf("found slashing evidence %s", evidenceStr) + v.logger.Debug("found slashing evidence") var evidence ftypes.Evidence if err := jsonpb.UnmarshalString(evidenceStr, &evidence); err != nil { return nil, nil, fmt.Errorf("failed to decode evidence bytes to evidence: %s", err.Error()) @@ -774,11 +791,12 @@ func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*typ response = latestFinalisedBlock return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("Failed to query babylon for the latest finalised blocks") + v.logger.Debug( + "failed to query babylon for the latest finalised blocks", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return nil, err } @@ -798,11 +816,12 @@ func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the consumer chain for the latest block") + v.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return nil, err } @@ -823,11 +842,12 @@ func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, erro } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the voting power") + v.logger.Debug( + "failed to query the voting power", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return 0, err } @@ -848,11 +868,12 @@ func (v *ValidatorInstance) GetValidatorSlashedWithRetry() (bool, error) { } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the voting power") + v.logger.Debug( + "failed to query the validator", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return false, err } diff --git a/validator/service/validator_instance_test.go b/validator/service/validator_instance_test.go index ef245f4c..96ceaee8 100644 --- a/validator/service/validator_instance_test.go +++ b/validator/service/validator_instance_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" @@ -104,7 +104,7 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli cfg.NumPubRand = uint64(25) cfg.ValidatorModeConfig.AutoChainScanningMode = false cfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight - logger := logrus.New() + logger := zap.NewNop() eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) require.NoError(t, err) em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) diff --git a/validator/service/validator_manager.go b/validator/service/validator_manager.go index 89249f1d..b6507cbd 100644 --- a/validator/service/validator_manager.go +++ b/validator/service/validator_manager.go @@ -9,8 +9,8 @@ import ( "github.com/avast/retry-go/v4" bbntypes "github.com/babylonchain/babylon/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/sirupsen/logrus" "go.uber.org/atomic" + "go.uber.org/zap" "github.com/babylonchain/btc-validator/clientcontroller" "github.com/babylonchain/btc-validator/eotsmanager" @@ -45,7 +45,7 @@ type ValidatorManager struct { config *valcfg.Config cc clientcontroller.ClientController em eotsmanager.EOTSManager - logger *logrus.Logger + logger *zap.Logger criticalErrChan chan *CriticalError @@ -56,7 +56,7 @@ func NewValidatorManager(vs *valstore.ValidatorStore, config *valcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, - logger *logrus.Logger, + logger *zap.Logger, ) (*ValidatorManager, error) { return &ValidatorManager{ vals: make(map[string]*ValidatorInstance), @@ -88,14 +88,12 @@ func (vm *ValidatorManager) monitorCriticalErr() { } if errors.Is(criticalErr.err, btcstakingtypes.ErrBTCValAlreadySlashed) { vm.setValidatorSlashed(vi) - vm.logger.WithFields(logrus.Fields{ - "err": criticalErr, - }).Debug("the validator status has been slashed") + vm.logger.Debug("the validator has been slashed", + zap.String("pk", criticalErr.valBtcPk.MarshalHex())) continue } - vi.logger.WithFields(logrus.Fields{ - "err": criticalErr, - }).Fatal(instanceTerminatingMsg) + vi.logger.Fatal(instanceTerminatingMsg, + zap.String("pk", criticalErr.valBtcPk.MarshalHex()), zap.Error(criticalErr.err)) case <-vm.quit: return } @@ -125,9 +123,7 @@ func (vm *ValidatorManager) monitorStatusUpdate() { case <-statusUpdateTicker.C: latestBlock, err := vm.getLatestBlockWithRetry() if err != nil { - vm.logger.WithFields(logrus.Fields{ - "err": err, - }).Debug("failed to get the latest block") + vm.logger.Debug("failed to get the latest block", zap.Error(err)) continue } vals := vm.ListValidatorInstances() @@ -135,49 +131,54 @@ func (vm *ValidatorManager) monitorStatusUpdate() { oldStatus := v.GetStatus() power, err := v.GetVotingPowerWithRetry(latestBlock.Height) if err != nil { - vm.logger.WithFields(logrus.Fields{ - "err": err, - "val_btc_pk": v.GetBtcPkHex(), - "height": latestBlock.Height, - }).Debug("failed to get the voting power") + vm.logger.Debug( + "failed to get the voting power", + zap.String("val_btc_pk", v.GetBtcPkHex()), + zap.Uint64("height", latestBlock.Height), + zap.Error(err), + ) continue } // power > 0 (slashed_height must > 0), set status to ACTIVE if power > 0 { if oldStatus != proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_ACTIVE) - vm.logger.WithFields(logrus.Fields{ - "val_btc_pk": v.GetBtcPkHex(), - "old_status": oldStatus, - "power": power, - }).Debug("the validator status has changed to ACTIVE") + vm.logger.Debug( + "the validator status is changed to ACTIVE", + zap.String("val_btc_pk", v.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + zap.Uint64("power", power), + ) } continue } slashed, err := v.GetValidatorSlashedWithRetry() if err != nil { - vm.logger.WithFields(logrus.Fields{ - "err": err, - "val_btc_pk": v.GetBtcPkHex(), - }).Debug("failed to get the slashed height") + vm.logger.Debug( + "failed to get the slashed height", + zap.String("val_btc_pk", v.GetBtcPkHex()), + zap.Error(err), + ) continue } // power == 0 and slashed == true, set status to SLASHED and stop and remove the validator instance if slashed { vm.setValidatorSlashed(v) - vm.logger.WithFields(logrus.Fields{ - "val_btc_pk": v.GetBtcPkHex(), - "old_status": oldStatus, - }).Debug("the validator status has been slashed") + vm.logger.Debug( + "the validator is slashed", + zap.String("val_btc_pk", v.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) continue } // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE if oldStatus == proto.ValidatorStatus_ACTIVE { v.MustSetStatus(proto.ValidatorStatus_INACTIVE) - vm.logger.WithFields(logrus.Fields{ - "val_btc_pk": v.GetBtcPkHex(), - "old_status": oldStatus, - }).Debug("the validator status has changed to INACTIVE") + vm.logger.Debug( + "the validator status is changed to INACTIVE", + zap.String("val_btc_pk", v.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) } } case <-vm.quit: @@ -321,11 +322,12 @@ func (vm *ValidatorManager) getLatestBlockWithRetry() (*types.BlockInfo, error) } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - vm.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the consumer chain for the latest block") + vm.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) })); err != nil { return nil, err } diff --git a/validator/service/validator_manager_test.go b/validator/service/validator_manager_test.go index e2ac1da2..e791a587 100644 --- a/validator/service/validator_manager_test.go +++ b/validator/service/validator_manager_test.go @@ -1,18 +1,20 @@ package service_test import ( - "github.com/babylonchain/btc-validator/keyring" "math/rand" "os" "strings" "testing" "time" + "go.uber.org/zap" + + "github.com/babylonchain/btc-validator/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/sirupsen/logrus" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/clientcontroller" @@ -93,7 +95,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c cfg.StatusUpdateInterval = 10 * time.Millisecond cfg.DatabaseConfig = testutil.GenDBConfig(r, t) cfg.BabylonConfig.KeyDirectory = t.TempDir() - logger := logrus.New() + logger := zap.NewNop() input := strings.NewReader("") kr, err := keyring.CreateKeyring( From e61747874f2ff8e59ee6af63c97ee978563121b5 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Tue, 5 Dec 2023 14:45:57 +0400 Subject: [PATCH 29/66] fix: Do not perform conversions on the commission (#166) --- clientcontroller/babylon.go | 7 ++----- clientcontroller/interface.go | 5 ++--- itest/test_manager.go | 4 ++-- testutil/mocks/babylon.go | 6 +++--- validator/service/app.go | 2 +- validator/service/app_test.go | 2 +- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index cb22b7bb..1ab24866 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "math/big" "time" "cosmossdk.io/math" @@ -150,7 +149,7 @@ func (bc *BabylonController) RegisterValidator( chainPk []byte, valPk *btcec.PublicKey, pop []byte, - commission *big.Int, + commission *math.LegacyDec, description []byte, ) (*types.TxResponse, error) { var bbnPop btcstakingtypes.ProofOfPossession @@ -158,8 +157,6 @@ func (bc *BabylonController) RegisterValidator( return nil, fmt.Errorf("invalid proof-of-possession: %w", err) } - sdkCommission := math.LegacyNewDecFromBigInt(commission) - var sdkDescription sttypes.Description if err := sdkDescription.Unmarshal(description); err != nil { return nil, fmt.Errorf("invalid description: %w", err) @@ -170,7 +167,7 @@ func (bc *BabylonController) RegisterValidator( BabylonPk: &secp256k1.PubKey{Key: chainPk}, BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), Pop: &bbnPop, - Commission: &sdkCommission, + Commission: commission, Description: &sdkDescription, } diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index d0d6edda..4347e1c4 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -1,9 +1,8 @@ package clientcontroller import ( + "cosmossdk.io/math" "fmt" - "math/big" - "github.com/btcsuite/btcd/chaincfg" "go.uber.org/zap" @@ -36,7 +35,7 @@ type ValidatorAPIs interface { chainPk []byte, valPk *btcec.PublicKey, pop []byte, - commission *big.Int, + commission *math.LegacyDec, description []byte, ) (*types.TxResponse, error) diff --git a/itest/test_manager.go b/itest/test_manager.go index ea65feed..ff0bf0b7 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -200,6 +200,8 @@ func StartManagerWithValidator(t *testing.T) (*TestManager, *service.ValidatorIn func (tm *TestManager) Stop(t *testing.T) { err := tm.Va.Stop() require.NoError(t, err) + err = tm.CovenantEmulator.Stop() + require.NoError(t, err) err = tm.BabylonHandler.Stop() require.NoError(t, err) err = os.RemoveAll(tm.ValConfig.DatabaseConfig.Path) @@ -209,8 +211,6 @@ func (tm *TestManager) Stop(t *testing.T) { tm.EOTSServerHandler.Stop() err = os.RemoveAll(tm.EOTSServerHandler.baseDir) require.NoError(t, err) - err = tm.CovenantEmulator.Stop() - require.NoError(t, err) } func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 2779f19d..7aee9cc3 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -5,9 +5,9 @@ package mocks import ( - big "math/big" reflect "reflect" + math "cosmossdk.io/math" types "github.com/babylonchain/btc-validator/types" btcec "github.com/btcsuite/btcd/btcec/v2" schnorr "github.com/btcsuite/btcd/btcec/v2/schnorr" @@ -217,7 +217,7 @@ func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(valPk, blo } // RegisterValidator mocks base method. -func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description []byte) (*types.TxResponse, error) { +func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) @@ -435,7 +435,7 @@ func (mr *MockValidatorAPIsMockRecorder) QueryValidatorVotingPower(valPk, blockH } // RegisterValidator mocks base method. -func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *big.Int, description []byte) (*types.TxResponse, error) { +func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) diff --git a/validator/service/app.go b/validator/service/app.go index 44c9213c..8adb8c1e 100644 --- a/validator/service/app.go +++ b/validator/service/app.go @@ -432,7 +432,7 @@ func (app *ValidatorApp) registrationLoop() { req.bbnPubKey.Key, req.btcPubKey.MustToBTCPK(), popBytes, - req.commission.BigInt(), + req.commission, req.description, ) diff --git a/validator/service/app_test.go b/validator/service/app_test.go index 2a967495..1edb8f6f 100644 --- a/validator/service/app_test.go +++ b/validator/service/app_test.go @@ -80,7 +80,7 @@ func FuzzRegisterValidator(f *testing.F) { validator.GetBabylonPK().Key, validator.MustGetBIP340BTCPK().MustToBTCPK(), popBytes, - testutil.ZeroCommissionRate().BigInt(), + testutil.ZeroCommissionRate(), testutil.EmptyDescription(), ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() From fd8fc885366fccefa395050d48a22ef1dd1b036b Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Tue, 5 Dec 2023 16:00:17 +0400 Subject: [PATCH 30/66] feat: Use a single docker file (#167) --- .circleci/config.yml | 28 +-------------- validator/Dockerfile => Dockerfile | 8 ++--- Makefile | 6 ++-- covenant/Dockerfile | 57 ------------------------------ covenant/Makefile | 7 ---- eotsmanager/Dockerfile | 57 ------------------------------ eotsmanager/Makefile | 8 ----- validator/Makefile | 8 ----- 8 files changed, 8 insertions(+), 171 deletions(-) rename validator/Dockerfile => Dockerfile (84%) delete mode 100644 covenant/Dockerfile delete mode 100644 covenant/Makefile delete mode 100644 eotsmanager/Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index cc6ecfdd..870bb6f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,27 +50,11 @@ jobs: - aws-ecr/build-image: push-image: false dockerfile: Dockerfile - path: ./validator + path: ./ build-path: ./ tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "$CIRCLE_PROJECT_REPONAME" extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - - aws-ecr/build-image: - push-image: false - dockerfile: Dockerfile - path: ./eotsmanager - build-path: ./ - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - repo: "eotsmanager" - extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - - aws-ecr/build-image: - push-image: false - dockerfile: Dockerfile - path: ./covenant - build-path: ./ - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - repo: "covenant" - extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - run: name: Save Docker image to export it to workspace command: | @@ -100,16 +84,6 @@ jobs: region: "$AWS_REGION" repo: "$CIRCLE_PROJECT_REPONAME" tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - - aws-ecr/push-image: - registry-id: AWS_ECR_REGISTRY_ID - region: "$AWS_REGION" - repo: "eotsmanager" - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" - - aws-ecr/push-image: - registry-id: AWS_ECR_REGISTRY_ID - region: "$AWS_REGION" - repo: "covenant" - tag: "$CIRCLE_SHA1,$CIRCLE_TAG" workflows: CI: diff --git a/validator/Dockerfile b/Dockerfile similarity index 84% rename from validator/Dockerfile rename to Dockerfile index 4a0d4d85..72fd1697 100644 --- a/validator/Dockerfile +++ b/Dockerfile @@ -47,11 +47,11 @@ RUN apk add bash curl jq COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/vald /bin/vald COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/valcli /bin/valcli +COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/covd /bin/covd +COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/covcli /bin/covcli +COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/eotsd /bin/eotsd +COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/eotscli /bin/eotscli WORKDIR /home/btcvalidator RUN chown -R btcvalidator /home/btcvalidator USER btcvalidator - -ENTRYPOINT ["/bin/vald"] -CMD [] -STOPSIGNAL SIGTERM diff --git a/Makefile b/Makefile index ed9840ec..5db0f649 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ BABYLON_PKG := github.com/babylonchain/babylon/cmd/babylond GO_BIN := ${GOPATH}/bin BTCD_BIN := $(GO_BIN)/btcd +DOCKER := $(shell which docker) CUR_DIR := $(shell pwd) MOCKS_DIR=$(CUR_DIR)/testutil/mocks MOCKGEN_REPO=github.com/golang/mock/mockgen @@ -40,9 +41,8 @@ $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ build-docker: - make -C covenant build-docker - make -C validator build-docker - make -C eotsmanager build-docker + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ + $(shell git rev-parse --show-toplevel) .PHONY: build build-docker diff --git a/covenant/Dockerfile b/covenant/Dockerfile deleted file mode 100644 index 8ada7868..00000000 --- a/covenant/Dockerfile +++ /dev/null @@ -1,57 +0,0 @@ -FROM golang:1.21.4-alpine as builder - -# Version to build. Default is the Git HEAD. -ARG VERSION="HEAD" - -# Use muslc for static libs -ARG BUILD_TAGS="muslc" - - -RUN apk add --no-cache --update openssh git make build-base linux-headers libc-dev \ - pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \ - libzmq-static libsodium-static gcc - - -RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts -RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/* - -# Build -WORKDIR /go/src/github.com/babylonchain/covenant -# Cache dependencies -COPY ./../go.mod ./../go.sum /go/src/github.com/babylonchain/covenant/ -RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download -# Copy the rest of the files -COPY ./ /go/src/github.com/babylonchain/covenant/ - -# Cosmwasm - Download correct libwasmvm version -RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ - wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ - -O /lib/libwasmvm_muslc.a && \ - # verify checksum - wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ - sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) - -RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ - CGO_ENABLED=1 \ - BUILD_TAGS=$BUILD_TAGS \ - LINK_STATICALLY=true \ - make build - -# FINAL IMAGE -FROM alpine:3.16 AS run - -RUN addgroup --gid 1138 -S covenant && adduser --uid 1138 -S covenant -G covenant - -RUN apk add bash curl jq - -COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covd /bin/covd -COPY --from=builder /go/src/github.com/babylonchain/covenant/build/covcli /bin/covcli - -WORKDIR /home/covenant -RUN chown -R covenant /home/covenant -USER covenant - -ENTRYPOINT ["/bin/covd"] -CMD [] -STOPSIGNAL SIGTERM diff --git a/covenant/Makefile b/covenant/Makefile deleted file mode 100644 index 8831caeb..00000000 --- a/covenant/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -DOCKER := $(shell which docker) - -build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/covenant -f Dockerfile \ - $(shell git rev-parse --show-toplevel) - -.PHONY: build-docker diff --git a/eotsmanager/Dockerfile b/eotsmanager/Dockerfile deleted file mode 100644 index e6cb5688..00000000 --- a/eotsmanager/Dockerfile +++ /dev/null @@ -1,57 +0,0 @@ -FROM golang:1.21.4-alpine as builder - -# Version to build. Default is the Git HEAD. -ARG VERSION="HEAD" - -# Use muslc for static libs -ARG BUILD_TAGS="muslc" - - -RUN apk add --no-cache --update openssh git make build-base linux-headers libc-dev \ - pkgconfig zeromq-dev musl-dev alpine-sdk libsodium-dev \ - libzmq-static libsodium-static gcc - - -RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts -RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/* - -# Build -WORKDIR /go/src/github.com/babylonchain/eots-manager -# Cache dependencies -COPY ./../go.mod ./../go.sum /go/src/github.com/babylonchain/eots-manager/ -RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download -# Copy the rest of the files -COPY ./ /go/src/github.com/babylonchain/eots-manager/ - -# Cosmwasm - Download correct libwasmvm version -RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ - wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ - -O /lib/libwasmvm_muslc.a && \ - # verify checksum - wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/checksums.txt -O /tmp/checksums.txt && \ - sha256sum /lib/libwasmvm_muslc.a | grep $(cat /tmp/checksums.txt | grep libwasmvm_muslc.$(uname -m) | cut -d ' ' -f 1) - -RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ - CGO_ENABLED=1 \ - BUILD_TAGS=$BUILD_TAGS \ - LINK_STATICALLY=true \ - make build - -# FINAL IMAGE -FROM alpine:3.16 AS run - -RUN addgroup --gid 1138 -S eotsmanager && adduser --uid 1138 -S eotsmanager -G eotsmanager - -RUN apk add bash curl jq - -COPY --from=builder /go/src/github.com/babylonchain/eots-manager/build/eotsd /bin/eotsd -COPY --from=builder /go/src/github.com/babylonchain/eots-manager/build/eotscli /bin/eotscli - -WORKDIR /home/eotsmanager -RUN chown -R eotsmanager /home/eotsmanager -USER eotsmanager - -ENTRYPOINT ["/bin/eotsd"] -CMD [] -STOPSIGNAL SIGTERM diff --git a/eotsmanager/Makefile b/eotsmanager/Makefile index b455e724..abc4da72 100644 --- a/eotsmanager/Makefile +++ b/eotsmanager/Makefile @@ -1,11 +1,3 @@ -DOCKER := $(shell which docker) - -build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/eots-manager -f Dockerfile \ - $(shell git rev-parse --show-toplevel) - -.PHONY: build-docker - ############################################################################### ### Protobuf ### ############################################################################### diff --git a/validator/Makefile b/validator/Makefile index 96763996..abc4da72 100644 --- a/validator/Makefile +++ b/validator/Makefile @@ -1,11 +1,3 @@ -DOCKER := $(shell which docker) - -build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ - $(shell git rev-parse --show-toplevel) - -.PHONY: build-docker - ############################################################################### ### Protobuf ### ############################################################################### From 61d72a77fcbd41d0a7948a8d00cc2e10b002e404 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Thu, 7 Dec 2023 13:13:51 +0400 Subject: [PATCH 31/66] feat: Refactor configuration and cli of programs (#168) --- Dockerfile | 2 - README.md | 4 +- {eotsmanager/config => config}/db.go | 10 +- covenant/cmd/covcli/admin.go | 65 ----- covenant/cmd/covcli/main.go | 25 -- covenant/cmd/covd/flags.go | 18 ++ covenant/cmd/covd/init.go | 56 +++++ covenant/cmd/{covcli/new.go => covd/key.go} | 36 +-- covenant/cmd/covd/main.go | 4 +- covenant/cmd/covd/start.go | 45 ++-- covenant/config/config.go | 141 +++-------- covenant/covenant.go | 10 +- docs/eotsd/eotsd-config.md | 11 +- docs/eotsd/eotsd-startup-guide.md | 2 +- docs/vald/vald-config.md | 11 +- docs/vald/vald-startup-guide.md | 2 +- eotsmanager/cmd/eotscli/admin.go | 74 ------ eotsmanager/cmd/eotscli/main.go | 24 -- eotsmanager/cmd/eotsd/flags.go | 6 + eotsmanager/cmd/eotsd/init.go | 61 +++++ eotsmanager/cmd/eotsd/main.go | 49 +--- eotsmanager/cmd/eotsd/start.go | 60 +++++ eotsmanager/config/config.go | 223 ++++------------- eotsmanager/eotsstore.go | 11 +- eotsmanager/localmanager.go | 54 ++-- eotsmanager/localmanager_test.go | 20 +- itest/eotsmanager_handler.go | 8 +- itest/test_manager.go | 47 ++-- keyring/keyringcontroller_test.go | 13 +- log/log.go | 20 ++ testutil/datagen.go | 37 ++- util/path.go | 64 +++++ validator/cmd/valcli/admin.go | 74 ------ validator/cmd/valcli/daemoncmd.go | 17 -- validator/cmd/valcli/main.go | 23 +- validator/cmd/vald/flags.go | 10 + validator/cmd/vald/init.go | 56 +++++ validator/cmd/vald/main.go | 2 +- validator/cmd/vald/start.go | 41 +-- validator/config/config.go | 247 +++++-------------- validator/config/dbcfg.go | 44 ---- validator/service/app.go | 50 ++-- validator/service/app_test.go | 38 +-- validator/service/validator_instance.go | 4 + validator/service/validator_instance_test.go | 32 ++- validator/service/validator_manager_test.go | 44 ++-- validator/store/valstore.go | 13 +- validator/store/valstore_test.go | 6 +- 48 files changed, 776 insertions(+), 1138 deletions(-) rename {eotsmanager/config => config}/db.go (68%) delete mode 100644 covenant/cmd/covcli/admin.go delete mode 100644 covenant/cmd/covcli/main.go create mode 100644 covenant/cmd/covd/flags.go create mode 100644 covenant/cmd/covd/init.go rename covenant/cmd/{covcli/new.go => covd/key.go} (72%) delete mode 100644 eotsmanager/cmd/eotscli/admin.go delete mode 100644 eotsmanager/cmd/eotscli/main.go create mode 100644 eotsmanager/cmd/eotsd/flags.go create mode 100644 eotsmanager/cmd/eotsd/init.go create mode 100644 eotsmanager/cmd/eotsd/start.go create mode 100644 util/path.go delete mode 100644 validator/cmd/valcli/admin.go create mode 100644 validator/cmd/vald/flags.go create mode 100644 validator/cmd/vald/init.go delete mode 100644 validator/config/dbcfg.go diff --git a/Dockerfile b/Dockerfile index 72fd1697..5d527bc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,9 +48,7 @@ RUN apk add bash curl jq COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/vald /bin/vald COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/valcli /bin/valcli COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/covd /bin/covd -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/covcli /bin/covcli COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/eotsd /bin/eotsd -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/eotscli /bin/eotscli WORKDIR /home/btcvalidator RUN chown -R btcvalidator /home/btcvalidator diff --git a/README.md b/README.md index 94ed8f77..766ff02a 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ $ make install The above will produce the following binaries: - `eotsd`: The daemon program for the EOTS manager. -- `eotcli`: The CLI tool for interacting with the EOTS daemon. - `vald`: The daemon program for the btc-validator. - `valcli`: The CLI tool for interacting with the btc-validator daemon. +- `covd`: The daemon program for the covenant emulator. To build locally, @@ -113,7 +113,7 @@ The above will lead to a build directory having the following structure: ```bash $ ls build - ├── eotcli + ├── covd ├── eotsd ├── valcli └── vald diff --git a/eotsmanager/config/db.go b/config/db.go similarity index 68% rename from eotsmanager/config/db.go rename to config/db.go index acaac42f..e19be729 100644 --- a/eotsmanager/config/db.go +++ b/config/db.go @@ -4,33 +4,26 @@ import "fmt" const ( DefaultBackend = "bbolt" - DefaultDBPath = "bbolt-eots.db" DefaultDBName = "default" ) type DatabaseConfig struct { Backend string `long:"backend" description:"Possible database to choose as backend"` - Path string `long:"path" description:"The path that stores the database file"` Name string `long:"name" description:"The name of the database"` } -func NewDatabaseConfig(backend string, path string, name string) (*DatabaseConfig, error) { +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 path == "" { - return nil, fmt.Errorf("DB path should not be empty") - } - if name == "" { return nil, fmt.Errorf("bucket name should not be empty") } return &DatabaseConfig{ Backend: backend, - Path: path, Name: name, }, nil } @@ -38,7 +31,6 @@ func NewDatabaseConfig(backend string, path string, name string) (*DatabaseConfi func DefaultDatabaseConfig() DatabaseConfig { return DatabaseConfig{ Backend: DefaultBackend, - Path: DefaultDBPath, Name: DefaultDBName, } } diff --git a/covenant/cmd/covcli/admin.go b/covenant/cmd/covcli/admin.go deleted file mode 100644 index bf85a9a2..00000000 --- a/covenant/cmd/covcli/admin.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/jessevdk/go-flags" - "github.com/urfave/cli" - - covcfg "github.com/babylonchain/btc-validator/covenant/config" -) - -const configFileFlag = "config" - -var adminCommands = []cli.Command{ - { - Name: "admin", - ShortName: "ad", - Usage: "Different utility and admin commands.", - Category: "Admin", - Subcommands: []cli.Command{ - dumpCfgCommand, - }, - }, -} - -var dumpCfgCommand = cli.Command{ - Name: "dump-config", - ShortName: "dc", - Usage: "Dump default configuration file.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: configFileFlag, - Usage: "Path to where the default config file will be dumped", - Value: covcfg.DefaultConfigFile, - }, - }, - Action: dumpCfg, -} - -func dumpCfg(c *cli.Context) error { - configPath := c.String(configFileFlag) - - if covcfg.FileExists(configPath) { - return fmt.Errorf("config already exists under provided path: %s", configPath) - } - - // ensure the directory exists - configDir := filepath.Dir(configPath) - if err := os.MkdirAll(configDir, 0700); err != nil { - return err - } - - defaultConfig := covcfg.DefaultConfig() - fileParser := flags.NewParser(&defaultConfig, flags.Default) - - err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) - - if err != nil { - return err - } - - return nil -} diff --git a/covenant/cmd/covcli/main.go b/covenant/cmd/covcli/main.go deleted file mode 100644 index 11aa55e4..00000000 --- a/covenant/cmd/covcli/main.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func fatal(err error) { - fmt.Fprintf(os.Stderr, "[covenant-emulator cli] %v\n", err) - os.Exit(1) -} - -func main() { - app := cli.NewApp() - app.Name = "covcli" - app.Usage = "Control plane for the Covenant Emulator Daemon (covd)." - app.Commands = append(app.Commands, adminCommands...) - app.Commands = append(app.Commands, createCovenant) - - if err := app.Run(os.Args); err != nil { - fatal(err) - } -} diff --git a/covenant/cmd/covd/flags.go b/covenant/cmd/covd/flags.go new file mode 100644 index 00000000..58bea109 --- /dev/null +++ b/covenant/cmd/covd/flags.go @@ -0,0 +1,18 @@ +package main + +import "github.com/cosmos/cosmos-sdk/crypto/keyring" + +const ( + homeFlag = "home" + forceFlag = "force" + keyNameFlag = "key-name" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + keyringBackendFlag = "keyring-backend" + + defaultChainID = "chain-test" + defaultKeyringBackend = keyring.BackendTest + defaultPassphrase = "" + defaultHdPath = "" +) diff --git a/covenant/cmd/covd/init.go b/covenant/cmd/covd/init.go new file mode 100644 index 00000000..b28dfebb --- /dev/null +++ b/covenant/cmd/covd/init.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/btc-validator/util" + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + "path/filepath" +) + +var initCommand = cli.Command{ + Name: "init", + Usage: "Initialize a covenant home directory.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to where the home directory will be initialized", + Value: covcfg.DefaultCovenantDir, + }, + cli.BoolFlag{ + Name: forceFlag, + Usage: "Override existing configuration", + Required: false, + }, + }, + Action: initHome, +} + +func initHome(c *cli.Context) error { + homePath, err := filepath.Abs(c.String(homeFlag)) + if err != nil { + return err + } + // ensure the directory exists + homePath = util.CleanAndExpandPath(homePath) + force := c.Bool(forceFlag) + + if util.FileExists(homePath) && !force { + return fmt.Errorf("home path %s already exists", homePath) + } + + if err := util.MakeDirectory(homePath); err != nil { + return err + } + // Create log directory + logDir := covcfg.LogDir(homePath) + if err := util.MakeDirectory(logDir); err != nil { + return err + } + + defaultConfig := covcfg.DefaultConfigWithHomePath(homePath) + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(covcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} diff --git a/covenant/cmd/covcli/new.go b/covenant/cmd/covd/key.go similarity index 72% rename from covenant/cmd/covcli/new.go rename to covenant/cmd/covd/key.go index bb603127..46573398 100644 --- a/covenant/cmd/covcli/new.go +++ b/covenant/cmd/covd/key.go @@ -3,26 +3,10 @@ package main import ( "encoding/json" "fmt" - "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/urfave/cli" - "github.com/babylonchain/btc-validator/covenant" covcfg "github.com/babylonchain/btc-validator/covenant/config" -) - -const ( - keyNameFlag = "key-name" - passphraseFlag = "passphrase" - hdPathFlag = "hd-path" - chainIdFlag = "chain-id" - keyringDirFlag = "keyring-dir" - keyringBackendFlag = "keyring-backend" - defaultChainID = "chain-test" - defaultKeyringBackend = keyring.BackendTest - defaultPassphrase = "" - defaultHdPath = "" + "github.com/urfave/cli" ) type covenantKey struct { @@ -30,9 +14,9 @@ type covenantKey struct { PublicKey string `json:"public-key"` } -var createCovenant = cli.Command{ - Name: "create-covenant", - ShortName: "cc", +var createKeyCommand = cli.Command{ + Name: "create-key", + ShortName: "ck", Usage: "Create a Covenant account in the keyring.", Flags: []cli.Flag{ cli.StringFlag{ @@ -61,16 +45,16 @@ var createCovenant = cli.Command{ Value: defaultKeyringBackend, }, cli.StringFlag{ - Name: keyringDirFlag, - Usage: "The directory where the keyring is stored", + Name: homeFlag, + Usage: "The home directory for the covenant", Value: covcfg.DefaultCovenantDir, }, }, - Action: createCovenantKey, + Action: createKey, } -func createCovenantKey(ctx *cli.Context) error { - keyringDir := ctx.String(keyringDirFlag) +func createKey(ctx *cli.Context) error { + homePath := ctx.String(homeFlag) chainID := ctx.String(chainIdFlag) keyName := ctx.String(keyNameFlag) backend := ctx.String(keyringBackendFlag) @@ -78,7 +62,7 @@ func createCovenantKey(ctx *cli.Context) error { hdPath := ctx.String(hdPathFlag) keyPair, err := covenant.CreateCovenantKey( - keyringDir, + homePath, chainID, keyName, backend, diff --git a/covenant/cmd/covd/main.go b/covenant/cmd/covd/main.go index 9f4cd2a4..d14fce5f 100644 --- a/covenant/cmd/covd/main.go +++ b/covenant/cmd/covd/main.go @@ -8,7 +8,7 @@ import ( ) func fatal(err error) { - fmt.Fprintf(os.Stderr, "[covenant-emulator] %v\n", err) + fmt.Fprintf(os.Stderr, "[covd] %v\n", err) os.Exit(1) } @@ -16,7 +16,7 @@ func main() { app := cli.NewApp() app.Name = "covd" app.Usage = "Covenant Emulator Daemon (covd)." - app.Commands = append(app.Commands, startCovenant) + app.Commands = append(app.Commands, startCommand, initCommand, createKeyCommand) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go index 31fb288e..afe479bf 100644 --- a/covenant/cmd/covd/start.go +++ b/covenant/cmd/covd/start.go @@ -2,6 +2,10 @@ package main import ( "fmt" + "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/log" + "github.com/babylonchain/btc-validator/util" + "path/filepath" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" @@ -12,14 +16,7 @@ import ( covsrv "github.com/babylonchain/btc-validator/covenant/service" ) -const ( - passphraseFlag = "passphrase" - configFileFlag = "config" - - defaultPassphrase = "" -) - -var startCovenant = cli.Command{ +var startCommand = cli.Command{ Name: "start", Usage: "covd start", Description: "Start the Covenant Emulator Daemon. Note that the Covenant should be created beforehand", @@ -30,27 +27,37 @@ var startCovenant = cli.Command{ Value: defaultPassphrase, }, cli.StringFlag{ - Name: configFileFlag, - Usage: "The path to the covenant config file", - Value: covcfg.DefaultConfigFile, + Name: homeFlag, + Usage: "The path to the covenant home directory", + Value: covcfg.DefaultCovenantDir, }, }, - Action: startCovenantFn, + Action: start, } -func startCovenantFn(ctx *cli.Context) error { - configFilePath := ctx.String(configFileFlag) - cfg, cfgLogger, err := covcfg.LoadConfig(configFilePath) +func start(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) + + cfg, err := covcfg.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 config at %s: %w", configFilePath, err) + return fmt.Errorf("failed to load the logger") } - bbnClient, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, cfgLogger) + bbnClient, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) if err != nil { return fmt.Errorf("failed to create rpc client for the consumer chain: %w", err) } - ce, err := covenant.NewCovenantEmulator(cfg, bbnClient, ctx.String(passphraseFlag), cfgLogger) + ce, err := covenant.NewCovenantEmulator(cfg, bbnClient, ctx.String(passphraseFlag), logger) if err != nil { return fmt.Errorf("failed to start the covenant emulator: %w", err) } @@ -61,7 +68,7 @@ func startCovenantFn(ctx *cli.Context) error { return err } - srv := covsrv.NewCovenantServer(cfgLogger, ce, shutdownInterceptor) + srv := covsrv.NewCovenantServer(logger, ce, shutdownInterceptor) if err != nil { return fmt.Errorf("failed to create covenant server: %w", err) } diff --git a/covenant/config/config.go b/covenant/config/config.go index 89fdbad0..42e7dbe9 100644 --- a/covenant/config/config.go +++ b/covenant/config/config.go @@ -2,19 +2,15 @@ package config import ( "fmt" - "io" - "os" + "github.com/babylonchain/btc-validator/util" "path/filepath" "time" - "go.uber.org/zap" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/log" ) const ( @@ -25,29 +21,26 @@ const ( defaultQueryInterval = 15 * time.Second defaultDelegationLimit = uint64(100) defaultBitcoinNetwork = "simnet" - emptySlashingAddress = "" + defaultLogDirname = "logs" ) var ( + // DefaultCovenantDir specifies the default home directory for the covenant: // C:\Users\\AppData\Local\ on Windows // ~/.vald on Linux // ~/Library/Application Support/Covd on MacOS DefaultCovenantDir = btcutil.AppDataDir("covd", false) - DefaultConfigFile = filepath.Join(DefaultCovenantDir, defaultConfigFileName) + defaultBTCNetParams = chaincfg.SimNetParams ) 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"` - CovenantDir string `long:"covenantdir" description:"The base directory of the Covenant emulator"` - DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` - // slashing address can be empty as it will be set from Babylon params - SlashingAddress string `long:"slashingaddress" description:"The slashing address that the slashed fund is sent to"` - BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` + BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` - ActiveNetParams chaincfg.Params + BTCNetParams chaincfg.Params BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` } @@ -60,100 +53,46 @@ type Config struct { // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig(filePath string) (*Config, *zap.Logger, error) { - // Pre-parse the command line options to pick up an alternative config - // file. - preCfg := DefaultConfig() - if _, err := flags.Parse(&preCfg); err != nil { - return nil, nil, err - } - - if !FileExists(filePath) { - return nil, nil, fmt.Errorf("specified config file does "+ - "not exist in %s", filePath) +func LoadConfig(homePath string) (*Config, error) { + // The home directory is required to have a configuration file with a specific name + // under it. + cfgFile := ConfigFile(homePath) + if !util.FileExists(cfgFile) { + return nil, fmt.Errorf("specified config file does "+ + "not exist in %s", cfgFile) } - // Next, load any additional configuration options from the file. - var configFileError error - cfg := preCfg + // If there are issues parsing the config file, return an error + var cfg Config fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(filePath) + err := flags.NewIniParser(fileParser).ParseFile(cfgFile) if err != nil { - // If it's a parsing related error, then we'll return - // immediately, otherwise we can proceed as possibly the config - // file doesn't exist which is OK. - if _, ok := err.(*flags.IniError); ok { - return nil, nil, err - } - - configFileError = err + return nil, err } // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { - return nil, nil, err - } - - // At this point we know config is valid, create logger which also log to file - logFilePath := filepath.Join(cfg.CovenantDir, defaultLogFilename) - f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - return nil, nil, err + return nil, err } - mw := io.MultiWriter(os.Stdout, f) - cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) - if err != nil { - return nil, nil, err - } - - // Warn about missing config file only after all other configuration is - // done. This prevents the warning on help messages and invalid - // options. Note this should go directly before the return. - if configFileError != nil { - if cfg.DumpCfg { - cfgLogger.Info("Writing configuration file", zap.String("path", filePath)) - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) - if err != nil { - cfgLogger.Error("Error writing configuration file", zap.Error(err)) - return nil, nil, err - } - } - } - - return &cfg, cfgLogger, nil + return &cfg, nil } // Validate check the given configuration to be sane. This makes sure no // illegal values or combination of values are set. All file system paths are // normalized. The cleaned up config is returned on success. func (cfg *Config) Validate() error { - err := os.MkdirAll(cfg.CovenantDir, 0700) - if err != nil { - // Show a nicer error message if it's because a symlink - // is linked to a directory that does not exist - // (probably because it's not mounted). - if e, ok := err.(*os.PathError); ok && os.IsExist(err) { - link, lerr := os.Readlink(e.Path) - if lerr == nil { - str := "is symlink %s -> %s mounted?" - err = fmt.Errorf(str, e.Path, link) - } - } - - return fmt.Errorf("failed to create covd directory '%s': %w", cfg.CovenantDir, err) - } - switch cfg.BitcoinNetwork { + case "mainnet": + cfg.BTCNetParams = chaincfg.MainNetParams case "testnet": - cfg.ActiveNetParams = chaincfg.TestNet3Params + cfg.BTCNetParams = chaincfg.TestNet3Params case "regtest": - cfg.ActiveNetParams = chaincfg.RegressionNetParams + cfg.BTCNetParams = chaincfg.RegressionNetParams case "simnet": - cfg.ActiveNetParams = chaincfg.SimNetParams + cfg.BTCNetParams = chaincfg.SimNetParams case "signet": - cfg.ActiveNetParams = chaincfg.SigNetParams + cfg.BTCNetParams = chaincfg.SigNetParams default: return fmt.Errorf("unsupported Bitcoin network: %s", cfg.BitcoinNetwork) } @@ -161,32 +100,34 @@ func (cfg *Config) Validate() error { return nil } -func FileExists(name string) bool { - if _, err := os.Stat(name); err != nil { - if os.IsNotExist(err) { - return false - } - } - return true +func ConfigFile(homePath string) string { + return filepath.Join(homePath, defaultConfigFileName) } -func DefaultConfig() Config { +func LogDir(homePath string) string { + return filepath.Join(homePath, defaultLogDirname) +} + +func DefaultConfigWithHomePath(homePath string) Config { bbnCfg := config.DefaultBBNConfig() bbnCfg.Key = defaultCovenantKeyName - bbnCfg.KeyDirectory = DefaultCovenantDir + bbnCfg.KeyDirectory = homePath cfg := Config{ LogLevel: defaultLogLevel, - CovenantDir: DefaultCovenantDir, - DumpCfg: false, QueryInterval: defaultQueryInterval, DelegationLimit: defaultDelegationLimit, - SlashingAddress: emptySlashingAddress, BitcoinNetwork: defaultBitcoinNetwork, - ActiveNetParams: chaincfg.Params{}, + BTCNetParams: defaultBTCNetParams, BabylonConfig: &bbnCfg, } - _ = cfg.Validate() + if err := cfg.Validate(); err != nil { + panic(err) + } return cfg } + +func DefaultConfig() Config { + return DefaultConfigWithHomePath(DefaultCovenantDir) +} diff --git a/covenant/covenant.go b/covenant/covenant.go index 29335446..76881428 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -136,7 +136,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add int64(ce.params.MinSlashingTxFeeSat), ce.params.SlashingRate, ce.params.SlashingAddress, - &ce.config.ActiveNetParams, + &ce.config.BTCNetParams, ); err != nil { return nil, fmt.Errorf("invalid txs in the delegation: %w", err) } @@ -154,7 +154,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add ce.params.CovenantQuorum, btcDel.GetStakingTime(), btcutil.Amount(btcDel.TotalSat), - &ce.config.ActiveNetParams, + &ce.config.BTCNetParams, ) if err != nil { return nil, err @@ -227,7 +227,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation ce.params.CovenantQuorum, uint16(del.BtcUndelegation.UnbondingTime), btcutil.Amount(unbondingMsgTx.TxOut[0].Value), - &ce.config.ActiveNetParams, + &ce.config.BTCNetParams, ) if err != nil { return nil, err @@ -240,7 +240,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation int64(ce.params.MinSlashingTxFeeSat), ce.params.SlashingRate, ce.params.SlashingAddress, - &ce.config.ActiveNetParams, + &ce.config.BTCNetParams, ) if err != nil { return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) @@ -254,7 +254,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation ce.params.CovenantQuorum, del.GetStakingTime(), btcutil.Amount(del.TotalSat), - &ce.config.ActiveNetParams, + &ce.config.BTCNetParams, ) if err != nil { return nil, err diff --git a/docs/eotsd/eotsd-config.md b/docs/eotsd/eotsd-config.md index 35895132..497ab9f3 100644 --- a/docs/eotsd/eotsd-config.md +++ b/docs/eotsd/eotsd-config.md @@ -1,14 +1,14 @@ ## EOTS daemon (`eotsd`) configuration: -The `eotscli` tool serves as a control plane for the EOTS Daemon (`eotsd`). Below, +The `eotsd` tool serves as a control plane for the EOTS Daemon. Below, instructions are provided for configuring the `eotsd` daemon. -The `eotscli admin dump-config` command initializes a home directory for the EOTS +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 `--config-file-dir` flag. +specified by the `--home` flag. ```bash -$ eotscli admin dump-config --config-file-dir /path/to/eotsd-home/ +$ eotsd init --home /path/to/eotsd-home/ ``` After initialization, the home directory will have the following structure @@ -16,9 +16,10 @@ After initialization, the home directory will have the following structure ```bash $ ls /path/to/eotsd-home/ ├── eotsd.conf # Eotsd-specific configuration file. + ├── logs # Eotsd logs ``` -If the `--config-file-dir` flag is not specified, then the default home location will +If the `--home` flag is not specified, then the default home location will be used. For different operating systems, those are: - **MacOS** `~/Library/Application Support/Eotsd` diff --git a/docs/eotsd/eotsd-startup-guide.md b/docs/eotsd/eotsd-startup-guide.md index 343d4ac3..a8144754 100644 --- a/docs/eotsd/eotsd-startup-guide.md +++ b/docs/eotsd/eotsd-startup-guide.md @@ -14,7 +14,7 @@ You can start the EOTS daemon using the following command: ```bash -$ eotsd +$ eotsd --home /path/to/eotsd/home ``` This will start the rpc server at the address specified in the configuration under diff --git a/docs/vald/vald-config.md b/docs/vald/vald-config.md index 9e9d1711..cb47f3c4 100644 --- a/docs/vald/vald-config.md +++ b/docs/vald/vald-config.md @@ -9,15 +9,15 @@ to create a keyring and request funds. ## Validator daemon (`vald`) configuration -The `valcli` tools serves as a control plane for the Validator Daemon (`vald`). +The `vald` tools serves as a control plane for the Validator Daemon. Below, instructions are provided for configuring the daemons. -The `valcli admin dump-config` command initializes a home directory for the BTC +The `vald init` command initializes a home directory for the BTC validator daemon. This directory is created in the default home location or in a -location specified by the `--config-file-dir` flag. +location specified by the `--home` flag. ```bash -$ valcli admin dump-config --config-file-dir /path/to/vald-home/ +$ vald init --home /path/to/vald-home/ ``` After initialization, the home directory will have the following structure @@ -25,9 +25,10 @@ After initialization, the home directory will have the following structure ```bash $ ls /path/to/vald-home/ ├── vald.conf # Vald-specific configuration file. + ├── logs # Vald logs ``` -If the `--config-file-dir` flag is not specified, then the default home directory +If the `--home` flag is not specified, then the default home directory will be used. For different operating systems, those are: - **MacOS** `~/Library/Application Support/Vald` diff --git a/docs/vald/vald-startup-guide.md b/docs/vald/vald-startup-guide.md index ad059595..b8069f23 100644 --- a/docs/vald/vald-startup-guide.md +++ b/docs/vald/vald-startup-guide.md @@ -14,7 +14,7 @@ You can start the validator daemon using the following command: ```bash -$ vald +$ vald --home /path/to/vald/home ``` This will start the RPC server at the address specified in the configuration under diff --git a/eotsmanager/cmd/eotscli/admin.go b/eotsmanager/cmd/eotscli/admin.go deleted file mode 100644 index 5701b7cb..00000000 --- a/eotsmanager/cmd/eotscli/admin.go +++ /dev/null @@ -1,74 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/jessevdk/go-flags" - "github.com/urfave/cli" - - eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" -) - -var adminCommands = []cli.Command{ - { - Name: "admin", - ShortName: "ad", - Usage: "Different utility and admin commands.", - Category: "Admin", - Subcommands: []cli.Command{ - dumpCfgCommand, - }, - }, -} - -const ( - configFileDirFlag = "config-file-dir" -) - -var ( - defaultConfigPath = eotscfg.DefaultConfigFile -) - -var dumpCfgCommand = cli.Command{ - Name: "dump-config", - ShortName: "dc", - Usage: "Dump default configuration file.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: configFileDirFlag, - Usage: "Path to where the default config file will be dumped", - Value: defaultConfigPath, - }, - }, - Action: dumpCfg, -} - -func dumpCfg(c *cli.Context) error { - configPath := c.String(configFileDirFlag) - - if eotscfg.FileExists(configPath) { - return cli.NewExitError( - fmt.Sprintf("config already exists under provided path: %s", configPath), - 1, - ) - } - - // ensure the directory exists - configDir := filepath.Dir(configPath) - if err := os.MkdirAll(configDir, 0700); err != nil { - return err - } - - defaultConfig := eotscfg.DefaultConfig() - fileParser := flags.NewParser(&defaultConfig, flags.Default) - - err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) - - if err != nil { - return err - } - - return nil -} diff --git a/eotsmanager/cmd/eotscli/main.go b/eotsmanager/cmd/eotscli/main.go deleted file mode 100644 index e26988ce..00000000 --- a/eotsmanager/cmd/eotscli/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func fatal(err error) { - fmt.Fprintf(os.Stderr, "[eots-manager] %v\n", err) - os.Exit(1) -} - -func main() { - app := cli.NewApp() - app.Name = "eotscli" - app.Usage = "Control plane for the EOTS Manager Daemon (eotsd)." - app.Commands = append(app.Commands, adminCommands...) - - if err := app.Run(os.Args); err != nil { - fatal(err) - } -} diff --git a/eotsmanager/cmd/eotsd/flags.go b/eotsmanager/cmd/eotsd/flags.go new file mode 100644 index 00000000..6a3ede77 --- /dev/null +++ b/eotsmanager/cmd/eotsd/flags.go @@ -0,0 +1,6 @@ +package main + +const ( + homeFlag = "home" + forceFlag = "force" +) diff --git a/eotsmanager/cmd/eotsd/init.go b/eotsmanager/cmd/eotsd/init.go new file mode 100644 index 00000000..153397ef --- /dev/null +++ b/eotsmanager/cmd/eotsd/init.go @@ -0,0 +1,61 @@ +package main + +import ( + "fmt" + eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/util" + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + "path/filepath" +) + +var initCommand = cli.Command{ + Name: "init", + Usage: "Initialize eotsd home directory.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to where the home directory will be initialized", + Value: eotscfg.DefaultEOTSDir, + }, + cli.BoolFlag{ + Name: forceFlag, + Usage: "Override existing configuration", + Required: false, + }, + }, + Action: initHome, +} + +func initHome(c *cli.Context) error { + homePath, err := filepath.Abs(c.String(homeFlag)) + if err != nil { + return err + } + // Create home directory + homePath = util.CleanAndExpandPath(homePath) + force := c.Bool(forceFlag) + + if util.FileExists(homePath) && !force { + return fmt.Errorf("home path %s already exists", homePath) + } + + if err := util.MakeDirectory(homePath); err != nil { + return err + } + // Create log directory + logDir := eotscfg.LogDir(homePath) + if err := util.MakeDirectory(logDir); err != nil { + return err + } + // Create data directory + dataDir := eotscfg.DataDir(homePath) + if err := util.MakeDirectory(dataDir); err != nil { + return err + } + + defaultConfig := eotscfg.DefaultConfig() + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(eotscfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} diff --git a/eotsmanager/cmd/eotsd/main.go b/eotsmanager/cmd/eotsd/main.go index 2e4f91cf..e9380374 100644 --- a/eotsmanager/cmd/eotsd/main.go +++ b/eotsmanager/cmd/eotsd/main.go @@ -2,47 +2,22 @@ package main import ( "fmt" + "github.com/urfave/cli" "os" - - "github.com/jessevdk/go-flags" - "github.com/lightningnetwork/lnd/signal" - "go.uber.org/zap" - - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/config" - eotsservice "github.com/babylonchain/btc-validator/eotsmanager/service" ) -func main() { - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - cfg, cfgLogger, err := config.LoadConfig() - if err != nil { - if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { - // Print error if not due to help request. - err = fmt.Errorf("failed to load config: %w", err) - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - // Help was requested, exit normally. - os.Exit(0) - } - - eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, cfgLogger) - if err != nil { - cfgLogger.Fatal("failed to create EOTS manager", zap.Error(err)) - } +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[eotsd] %v\n", err) + os.Exit(1) +} - eotsServer := eotsservice.NewEOTSManagerServer(cfg, cfgLogger, eotsManager, shutdownInterceptor) +func main() { + app := cli.NewApp() + app.Name = "eotsd" + app.Usage = "Extractable One Time Signature Daemon (eotsd)." + app.Commands = append(app.Commands, startCommand, initCommand) - if err := eotsServer.RunUntilShutdown(); err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) + if err := app.Run(os.Args); err != nil { + fatal(err) } } diff --git a/eotsmanager/cmd/eotsd/start.go b/eotsmanager/cmd/eotsd/start.go new file mode 100644 index 00000000..055deab0 --- /dev/null +++ b/eotsmanager/cmd/eotsd/start.go @@ -0,0 +1,60 @@ +package main + +import ( + "fmt" + "github.com/babylonchain/btc-validator/eotsmanager" + "github.com/babylonchain/btc-validator/eotsmanager/config" + eotsservice "github.com/babylonchain/btc-validator/eotsmanager/service" + "github.com/babylonchain/btc-validator/log" + "github.com/babylonchain/btc-validator/util" + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + "path/filepath" +) + +var startCommand = cli.Command{ + Name: "start", + Usage: "eotsd start", + Description: "Start the Extractable One Time Signature Daemon.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "The path to the eots home directory", + Value: config.DefaultEOTSDir, + }, + }, + Action: startFn, +} + +func startFn(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) + + 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") + } + + eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, cfg, logger) + if err != nil { + return fmt.Errorf("failed to create EOTS manager: %w", err) + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + return err + } + + eotsServer := eotsservice.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + + return eotsServer.RunUntilShutdown() +} diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 927c2083..89a84ea8 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -2,20 +2,14 @@ package config import ( "fmt" - "io" - "net" - "os" - "os/user" - "path/filepath" - "strconv" - "strings" - + "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/btc-validator/util" "github.com/btcsuite/btcd/btcutil" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/jessevdk/go-flags" - "go.uber.org/zap" - - "github.com/babylonchain/btc-validator/log" + "net" + "path/filepath" + "strconv" ) const ( @@ -23,35 +17,27 @@ const ( defaultDataDirname = "data" defaultLogDirname = "logs" defaultLogFilename = "eotsd.log" + defaultDBPath = "bbolt-eots.db" defaultConfigFileName = "eotsd.conf" DefaultRPCPort = 15813 defaultKeyringBackend = keyring.BackendFile ) var ( + // DefaultEOTSDir the default EOTS home directory: // C:\Users\\AppData\Local\ on Windows // ~/.vald on Linux // ~/Library/Application Support/Eotsd on MacOS DefaultEOTSDir = btcutil.AppDataDir("eotsd", false) - DefaultConfigFile = filepath.Join(DefaultEOTSDir, defaultConfigFileName) - - defaultDataDir = filepath.Join(DefaultEOTSDir, defaultDataDirname) - defaultLogDir = filepath.Join(DefaultEOTSDir, defaultLogDirname) defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) ) 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"` - EOTSDir string `long:"workdir" description:"The base directory that contains the EOTS manager's data, logs, configuration file, etc."` - ConfigFile string `long:"configfile" description:"Path to configuration file"` - DataDir string `long:"datadir" description:"The directory to store validator's data within"` - LogDir string `long:"logdir" description:"Directory to log output."` - DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` - KeyDirectory string `long:"key-dir" description:"Directory to store keys in"` KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` - DatabaseConfig *DatabaseConfig + DatabaseConfig *config.DatabaseConfig RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` } @@ -64,200 +50,77 @@ type Config struct { // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig() (*Config, *zap.Logger, error) { - // Pre-parse the command line options to pick up an alternative config - // file. - preCfg := DefaultConfig() - if _, err := flags.Parse(&preCfg); err != nil { - return nil, nil, err - } - - // If the config file path has not been modified by the user, then - // we'll use the default config file path. However, if the user has - // modified their default dir, then we should assume they intend to use - // the config file within it. - configFileDir := cleanAndExpandPath(preCfg.EOTSDir) - configFilePath := cleanAndExpandPath(preCfg.ConfigFile) - switch { - case configFileDir != DefaultEOTSDir && - configFilePath == DefaultConfigFile: - - configFilePath = filepath.Join( - configFileDir, defaultConfigFileName, - ) - - // User did specify an explicit --configfile, so we check that it does - // exist under that path to avoid surprises. - case configFilePath != DefaultConfigFile: - if !FileExists(configFilePath) { - return nil, nil, fmt.Errorf("specified config file does "+ - "not exist in %s", configFilePath) - } +func LoadConfig(homePath string) (*Config, error) { + // The home directory is required to have a configuration file with a specific name + // under it. + cfgFile := ConfigFile(homePath) + if !util.FileExists(cfgFile) { + return nil, fmt.Errorf("specified config file does "+ + "not exist in %s", cfgFile) } // Next, load any additional configuration options from the file. - var configFileError error - cfg := preCfg + var cfg Config fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(configFilePath) + err := flags.NewIniParser(fileParser).ParseFile(cfgFile) if err != nil { - // If it's a parsing related error, then we'll return - // immediately, otherwise we can proceed as possibly the config - // file doesn't exist which is OK. - if _, ok := err.(*flags.IniError); ok { - return nil, nil, err - } - - configFileError = err - } - - // Finally, parse the remaining command line options again to ensure - // they take precedence. - flagParser := flags.NewParser(&cfg, flags.Default) - if _, err := flagParser.Parse(); err != nil { - return nil, nil, err + return nil, err } // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { - return nil, nil, err - } - - // TODO: Add log rotation - // At this point we know config is valid, create logger which also log to file - logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) - f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - return nil, nil, err - } - mw := io.MultiWriter(os.Stdout, f) - - cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) - if err != nil { - return nil, nil, err + return nil, err } - // Warn about missing config file only after all other configuration is - // done. This prevents the warning on help messages and invalid - // options. Note this should go directly before the return. - if configFileError != nil { - if cfg.DumpCfg { - cfgLogger.Info("Writing configuration file", zap.String("path", configFilePath)) - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).WriteFile(configFilePath, flags.IniIncludeComments|flags.IniIncludeDefaults) - if err != nil { - cfgLogger.Error("Error writing configuration file", zap.Error(err)) - return nil, nil, err - } - } - } - - return &cfg, cfgLogger, nil + return &cfg, nil } // Validate check the given configuration to be sane. This makes sure no // illegal values or combination of values are set. All file system paths are // normalized. The cleaned up config is returned on success. func (cfg *Config) Validate() error { - // If the provided eotsd directory is not the default, we'll modify the - // path to all the files and directories that will live within it. - eotsdDir := cleanAndExpandPath(cfg.EOTSDir) - if eotsdDir != DefaultEOTSDir { - cfg.DataDir = filepath.Join(eotsdDir, defaultDataDirname) - cfg.LogDir = filepath.Join(eotsdDir, defaultLogDirname) - } - - makeDirectory := func(dir string) error { - err := os.MkdirAll(dir, 0700) - if err != nil { - // Show a nicer error message if it's because a symlink - // is linked to a directory that does not exist - // (probably because it's not mounted). - if e, ok := err.(*os.PathError); ok && os.IsExist(err) { - link, lerr := os.Readlink(e.Path) - if lerr == nil { - str := "is symlink %s -> %s mounted?" - err = fmt.Errorf(str, e.Path, link) - } - } - - return fmt.Errorf("failed to create eotsd directory '%s': %w", dir, err) - } - - return nil - } - - // As soon as we're done parsing configuration options, ensure all - // paths to directories and files are cleaned and expanded before - // attempting to use them later on. - cfg.DataDir = cleanAndExpandPath(cfg.DataDir) - cfg.LogDir = cleanAndExpandPath(cfg.LogDir) - - // Create the eotsd directory and all other subdirectories if they - // don't already exist. This makes sure that directory trees are also - // created for files that point to outside the eotsd dir. - dirs := []string{ - eotsdDir, cfg.DataDir, cfg.LogDir, - } - for _, dir := range dirs { - if err := makeDirectory(dir); err != nil { - return err - } - } - _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) if err != nil { return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) } + if cfg.KeyringBackend == "" { + return fmt.Errorf("the keyring backend should not be empty") + } + return nil } -func FileExists(name string) bool { - if _, err := os.Stat(name); err != nil { - if os.IsNotExist(err) { - return false - } - } - return true +func ConfigFile(homePath string) string { + return filepath.Join(homePath, defaultConfigFileName) } -// cleanAndExpandPath expands environment variables and leading ~ in the -// passed path, cleans the result, and returns it. -func cleanAndExpandPath(path string) string { - if path == "" { - return "" - } +func LogDir(homePath string) string { + return filepath.Join(homePath, defaultLogDirname) +} - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - var homeDir string - u, err := user.Current() - if err == nil { - homeDir = u.HomeDir - } else { - homeDir = os.Getenv("HOME") - } +func LogFile(homePath string) string { + return filepath.Join(LogDir(homePath), defaultLogFilename) +} - path = strings.Replace(path, "~", homeDir, 1) - } +func DataDir(homePath string) string { + return filepath.Join(homePath, defaultDataDirname) +} - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but the variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) +func DBPath(homePath string) string { + return filepath.Join(DataDir(homePath), defaultDBPath) } func DefaultConfig() Config { - dbCfg := DefaultDatabaseConfig() - return Config{ + dbCfg := config.DefaultDatabaseConfig() + cfg := Config{ LogLevel: defaultLogLevel, - EOTSDir: DefaultEOTSDir, - ConfigFile: DefaultConfigFile, - DataDir: defaultDataDir, - LogDir: defaultLogDir, KeyringBackend: defaultKeyringBackend, - KeyDirectory: defaultDataDir, DatabaseConfig: &dbCfg, RpcListener: defaultRpcListener, } + if err := cfg.Validate(); err != nil { + panic(err) + } + return cfg } diff --git a/eotsmanager/eotsstore.go b/eotsmanager/eotsstore.go index 8430b247..39992aca 100644 --- a/eotsmanager/eotsstore.go +++ b/eotsmanager/eotsstore.go @@ -3,7 +3,6 @@ package eotsmanager import ( "fmt" - "github.com/babylonchain/btc-validator/eotsmanager/config" "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/store" ) @@ -16,8 +15,8 @@ type EOTSStore struct { s store.Store } -func NewEOTSStore(cfg *config.DatabaseConfig) (*EOTSStore, error) { - s, err := openStore(cfg) +func NewEOTSStore(dbPath string, dbName string, dbBackend string) (*EOTSStore, error) { + s, err := openStore(dbPath, dbName, dbBackend) if err != nil { return nil, err } @@ -61,10 +60,10 @@ func getValidatorKeyNameKey(pk []byte) []byte { return append([]byte(validatorKeyNamePrefix), pk...) } -func openStore(dbcfg *config.DatabaseConfig) (store.Store, error) { - switch dbcfg.Backend { +func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { + switch dbBackend { case "bbolt": - return store.NewBboltStore(dbcfg.Path, dbcfg.Name) + return store.NewBboltStore(dbPath, dbName) default: return nil, fmt.Errorf("unsupported database type") } diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index 7058c89a..dc9d55bb 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -2,8 +2,7 @@ package eotsmanager import ( "fmt" - "os" - "path" + "github.com/babylonchain/btc-validator/util" "strings" "github.com/babylonchain/babylon/crypto/eots" @@ -36,45 +35,46 @@ type LocalEOTSManager struct { input *strings.Reader } -func NewLocalEOTSManager(eotsCfg *config.Config, logger *zap.Logger) (*LocalEOTSManager, error) { - keyringDir := eotsCfg.KeyDirectory - if keyringDir == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, err - } - keyringDir = path.Join(homeDir, ".eots-manager") - } - - if eotsCfg.KeyringBackend == "" { - return nil, fmt.Errorf("the keyring backend should not be empty") - } - +func NewLocalEOTSManager(homeDir string, eotsCfg *config.Config, logger *zap.Logger) (*LocalEOTSManager, error) { inputReader := strings.NewReader("") - kr, err := keyring.New( - "eots-manager", - eotsCfg.KeyringBackend, - keyringDir, - inputReader, - codec.MakeCodec(), - ) + + store, err := initEotsStore(homeDir, eotsCfg) if err != nil { - return nil, fmt.Errorf("failed to create keyring: %w", err) + return nil, fmt.Errorf("failed to initialize store: %w", err) } - es, err := NewEOTSStore(eotsCfg.DatabaseConfig) + kr, err := initKeyring(homeDir, eotsCfg, inputReader) if err != nil { - return nil, fmt.Errorf("failed to open the store for validators: %w", err) + return nil, fmt.Errorf("failed to initialize keyring: %w", err) } return &LocalEOTSManager{ kr: kr, - es: es, + es: store, logger: logger, input: inputReader, }, 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) { + return keyring.New( + "eots-manager", + eotsCfg.KeyringBackend, + homeDir, + inputReader, + codec.MakeCodec(), + ) +} + func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, error) { if lm.keyExists(name) { return nil, eotstypes.ErrValidatorAlreadyExisted diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go index 68ba7a1e..24a90fb6 100644 --- a/eotsmanager/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -1,17 +1,17 @@ package eotsmanager_test import ( + "go.uber.org/zap" "math/rand" "os" + "path/filepath" "testing" "github.com/babylonchain/babylon/testutil/datagen" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/eotsmanager/types" "github.com/babylonchain/btc-validator/testutil" + "github.com/stretchr/testify/require" ) var ( @@ -26,15 +26,14 @@ func FuzzCreateKey(f *testing.F) { r := rand.New(rand.NewSource(seed)) valName := testutil.GenRandomHexStr(r, 4) + homeDir := filepath.Join(t.TempDir(), "eots-home") eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { - err := os.RemoveAll(eotsCfg.KeyDirectory) - require.NoError(t, err) - err = os.RemoveAll(eotsCfg.DatabaseConfig.Path) + err := os.RemoveAll(homeDir) require.NoError(t, err) }() - lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, zap.NewNop()) + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, passphrase, hdPath) @@ -59,15 +58,14 @@ func FuzzCreateRandomnessPairList(f *testing.F) { r := rand.New(rand.NewSource(seed)) valName := testutil.GenRandomHexStr(r, 4) + homeDir := filepath.Join(t.TempDir(), "eots-home") eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { - err := os.RemoveAll(eotsCfg.KeyDirectory) - require.NoError(t, err) - err = os.RemoveAll(eotsCfg.DatabaseConfig.Path) + err := os.RemoveAll(homeDir) require.NoError(t, err) }() - lm, err := eotsmanager.NewLocalEOTSManager(eotsCfg, zap.NewNop()) + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) require.NoError(t, err) valPk, err := lm.CreateKey(valName, passphrase, hdPath) diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go index 5479fb7b..0a041c97 100644 --- a/itest/eotsmanager_handler.go +++ b/itest/eotsmanager_handler.go @@ -1,7 +1,6 @@ package e2etest import ( - "os" "testing" "github.com/lightningnetwork/lnd/signal" @@ -17,15 +16,14 @@ type EOTSServerHandler struct { t *testing.T interceptor *signal.Interceptor eotsServer *service.Server - baseDir string } -func NewEOTSServerHandler(t *testing.T, cfg *config.Config) *EOTSServerHandler { +func NewEOTSServerHandler(t *testing.T, cfg *config.Config, eotsHomeDir string) *EOTSServerHandler { shutdownInterceptor, err := signal.Intercept() require.NoError(t, err) logger := zap.NewNop() - eotsManager, err := eotsmanager.NewLocalEOTSManager(cfg, logger) + eotsManager, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, cfg, logger) require.NoError(t, err) eotsServer := service.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) @@ -48,6 +46,4 @@ func (eh *EOTSServerHandler) startServer() { func (eh *EOTSServerHandler) Stop() { eh.interceptor.RequestShutdown() - err := os.RemoveAll(eh.baseDir) - require.NoError(eh.t, err) } diff --git a/itest/test_manager.go b/itest/test_manager.go index ff0bf0b7..eae4bf2d 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -59,6 +59,7 @@ type TestManager struct { Va *service.ValidatorApp EOTSClient *client.EOTSManagerGRpcClient BabylonClient *clientcontroller.BabylonController + baseDir string } type TestDelegationData struct { @@ -95,19 +96,21 @@ func StartManager(t *testing.T) *TestManager { bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covKeyPair.PublicKey)) err = bh.Start() require.NoError(t, err) - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir) - bc, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.ActiveNetParams, logger) + valHomeDir := filepath.Join(testDir, "val-home") + cfg := defaultValidatorConfig(bh.GetNodeDataDir(), valHomeDir) + bc, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) require.NoError(t, err) // 3. prepare EOTS manager - eotsCfg := defaultEOTSConfig(t) - eh := NewEOTSServerHandler(t, eotsCfg) + eotsHomeDir := filepath.Join(testDir, "eots-home") + eotsCfg := defaultEOTSConfig() + eh := NewEOTSServerHandler(t, eotsCfg, eotsHomeDir) eh.Start() eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) // 4. prepare validator - valApp, err := service.NewValidatorApp(cfg, bc, eotsCli, logger) + valApp, err := service.NewValidatorApp(valHomeDir, cfg, bc, eotsCli, logger) require.NoError(t, err) err = valApp.Start() require.NoError(t, err) @@ -128,6 +131,7 @@ func StartManager(t *testing.T) *TestManager { CovenanConfig: covenantConfig, EOTSClient: eotsCli, BabylonClient: bc, + baseDir: testDir, } tm.WaitForServicesStart(t) @@ -204,13 +208,9 @@ func (tm *TestManager) Stop(t *testing.T) { require.NoError(t, err) err = tm.BabylonHandler.Stop() require.NoError(t, err) - err = os.RemoveAll(tm.ValConfig.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(tm.ValConfig.BabylonConfig.KeyDirectory) + err = os.RemoveAll(tm.baseDir) require.NoError(t, err) tm.EOTSServerHandler.Stop() - err = os.RemoveAll(tm.EOTSServerHandler.baseDir) - require.NoError(t, err) } func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { @@ -556,8 +556,8 @@ func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { return p } -func defaultValidatorConfig(keyringDir, testDir string) *valcfg.Config { - cfg := valcfg.DefaultConfig() +func defaultValidatorConfig(keyringDir, homeDir string) *valcfg.Config { + cfg := valcfg.DefaultConfigWithHome(homeDir) cfg.ValidatorModeConfig.AutoChainScanningMode = false // babylon configs for sending transactions @@ -567,36 +567,21 @@ func defaultValidatorConfig(keyringDir, testDir string) *valcfg.Config { cfg.BabylonConfig.Key = "test-spending-key" // Big adjustment to make sure we have enough gas in our transactions cfg.BabylonConfig.GasAdjustment = 20 - cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") cfg.UnbondingSigSubmissionInterval = 3 * time.Second return &cfg } -func defaultCovenantConfig(testDir string) *covcfg.Config { - cfg := covcfg.DefaultConfig() - cfg.CovenantDir = testDir - cfg.BabylonConfig.KeyDirectory = testDir +func defaultCovenantConfig(homeDir string) *covcfg.Config { + cfg := covcfg.DefaultConfigWithHomePath(homeDir) + cfg.BabylonConfig.KeyDirectory = homeDir return &cfg } -func defaultEOTSConfig(t *testing.T) *eotsconfig.Config { +func defaultEOTSConfig() *eotsconfig.Config { cfg := eotsconfig.DefaultConfig() - eotsDir, err := baseDir("zEOTSTest") - require.NoError(t, err) - - configFile := filepath.Join(eotsDir, "covd-test.conf") - dataDir := filepath.Join(eotsDir, "data") - logDir := filepath.Join(eotsDir, "log") - - cfg.EOTSDir = eotsDir - cfg.ConfigFile = configFile - cfg.LogDir = logDir - cfg.KeyDirectory = dataDir - cfg.DatabaseConfig.Path = filepath.Join(eotsDir, "db") - return &cfg } diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go index 900e5ce5..1c88b9ef 100644 --- a/keyring/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -1,12 +1,12 @@ package keyring_test import ( + "go.uber.org/zap" "math/rand" "os" + "path/filepath" "testing" - "go.uber.org/zap" - valstore "github.com/babylonchain/btc-validator/validator/store" "github.com/babylonchain/babylon/types" @@ -39,14 +39,11 @@ func FuzzCreatePoP(f *testing.F) { kc, err := valkr.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(cfg, zap.NewNop()) + em, err := eotsmanager.NewLocalEOTSManager(eotsHome, cfg, zap.NewNop()) defer func() { - err := os.RemoveAll(sdkCtx.KeyringDir) - require.NoError(t, err) - err = os.RemoveAll(cfg.KeyringBackend) - require.NoError(t, err) - err = os.RemoveAll(cfg.DatabaseConfig.Path) + err := os.RemoveAll(eotsHome) require.NoError(t, err) }() require.NoError(t, err) diff --git a/log/log.go b/log/log.go index 736c8557..f8ed33a2 100644 --- a/log/log.go +++ b/log/log.go @@ -2,7 +2,10 @@ package log import ( "fmt" + "github.com/babylonchain/btc-validator/util" "io" + "os" + "path/filepath" "strings" "time" @@ -54,3 +57,20 @@ func NewRootLogger(format string, level string, w io.Writer) (*zap.Logger, error lvl, )), nil } + +func NewRootLoggerWithFile(logFile string, level string) (*zap.Logger, error) { + if err := util.MakeDirectory(filepath.Dir(logFile)); err != nil { + return nil, err + } + f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, err + } + mw := io.MultiWriter(os.Stdout, f) + + logger, err := NewRootLogger("console", level, mw) + if err != nil { + return nil, err + } + return logger, nil +} diff --git a/testutil/datagen.go b/testutil/datagen.go index 4cd542f7..7cb5a75e 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -2,8 +2,9 @@ package testutil import ( "encoding/hex" + eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" + valcfg "github.com/babylonchain/btc-validator/validator/config" "math/rand" - "path/filepath" "testing" "time" @@ -14,13 +15,11 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/codec" - "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/btc-validator/config" "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/validator/service" ) @@ -138,30 +137,28 @@ func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp, p return storedVal } -func GenDBConfig(r *rand.Rand, t *testing.T) *valcfg.DatabaseConfig { +func GenDBConfig(r *rand.Rand, t *testing.T) *config.DatabaseConfig { bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - path := filepath.Join(t.TempDir(), bucketName) - dbcfg, err := valcfg.NewDatabaseConfig( + dbcfg, err := config.NewDatabaseConfig( "bbolt", - path, bucketName, ) require.NoError(t, err) return dbcfg } -func GenEOTSConfig(r *rand.Rand, t *testing.T) *config.Config { - bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - dir := t.TempDir() - path := filepath.Join(dir, bucketName) - dbCfg, err := config.NewDatabaseConfig("bbolt", path, bucketName) - require.NoError(t, err) - eotsCfg := &config.Config{ - KeyDirectory: dir, - KeyringBackend: keyring.BackendTest, - DatabaseConfig: dbCfg, - } - return eotsCfg +func GenEOTSConfig(r *rand.Rand, t *testing.T) *eotscfg.Config { + eotsCfg := eotscfg.DefaultConfig() + eotsCfg.DatabaseConfig = GenDBConfig(r, t) + + return &eotsCfg +} + +func GenValConfig(r *rand.Rand, t *testing.T, homeDir string) *valcfg.Config { + valCfg := valcfg.DefaultConfigWithHome(homeDir) + valCfg.DatabaseConfig = GenDBConfig(r, t) + + return &valCfg } func GenSdkContext(r *rand.Rand, t *testing.T) client.Context { diff --git a/util/path.go b/util/path.go new file mode 100644 index 00000000..ec7e497f --- /dev/null +++ b/util/path.go @@ -0,0 +1,64 @@ +package util + +import ( + "fmt" + "os" + "os/user" + "path/filepath" + "strings" +) + +// FileExists reports whether the named file or directory exists. +// This function is taken from https://github.com/btcsuite/btcd +func FileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + +func MakeDirectory(dir string) error { + err := os.MkdirAll(dir, 0700) + if err != nil { + // Show a nicer error message if it's because a symlink + // is linked to a directory that does not exist + // (probably because it's not mounted). + if e, ok := err.(*os.PathError); ok && os.IsExist(err) { + link, lerr := os.Readlink(e.Path) + if lerr == nil { + str := "is symlink %s -> %s mounted?" + err = fmt.Errorf(str, e.Path, link) + } + } + return fmt.Errorf("failed to create dir %s: %w", dir, err) + } + return nil +} + +// CleanAndExpandPath expands environment variables and leading ~ in the +// passed path, cleans the result, and returns it. +// This function is taken from https://github.com/btcsuite/btcd +func CleanAndExpandPath(path string) string { + if path == "" { + return "" + } + + // Expand initial ~ to OS specific home directory. + if strings.HasPrefix(path, "~") { + var homeDir string + u, err := user.Current() + if err == nil { + homeDir = u.HomeDir + } else { + homeDir = os.Getenv("HOME") + } + + path = strings.Replace(path, "~", homeDir, 1) + } + + // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, + // but the variables can still be expanded via POSIX-style $VARIABLE. + return filepath.Clean(os.ExpandEnv(path)) +} diff --git a/validator/cmd/valcli/admin.go b/validator/cmd/valcli/admin.go deleted file mode 100644 index 7c7f567a..00000000 --- a/validator/cmd/valcli/admin.go +++ /dev/null @@ -1,74 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/jessevdk/go-flags" - "github.com/urfave/cli" - - valcfg "github.com/babylonchain/btc-validator/validator/config" -) - -var adminCommands = []cli.Command{ - { - Name: "admin", - ShortName: "ad", - Usage: "Different utility and admin commands.", - Category: "Admin", - Subcommands: []cli.Command{ - dumpCfgCommand, - }, - }, -} - -const ( - configFileDirFlag = "config-file-dir" -) - -var ( - defaultConfigPath = valcfg.DefaultConfigFile -) - -var dumpCfgCommand = cli.Command{ - Name: "dump-config", - ShortName: "dc", - Usage: "Dump default configuration file.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: configFileDirFlag, - Usage: "Path to where the default config file will be dumped", - Value: defaultConfigPath, - }, - }, - Action: dumpCfg, -} - -func dumpCfg(c *cli.Context) error { - configPath := c.String(configFileDirFlag) - - if valcfg.FileExists(configPath) { - return cli.NewExitError( - fmt.Sprintf("config already exists under provided path: %s", configPath), - 1, - ) - } - - // ensure the directory exists - configDir := filepath.Dir(configPath) - if err := os.MkdirAll(configDir, 0700); err != nil { - return err - } - - defaultConfig := valcfg.DefaultConfig() - fileParser := flags.NewParser(&defaultConfig, flags.Default) - - err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) - - if err != nil { - return err - } - - return nil -} diff --git a/validator/cmd/valcli/daemoncmd.go b/validator/cmd/valcli/daemoncmd.go index f7bd73d5..a1cc6f71 100644 --- a/validator/cmd/valcli/daemoncmd.go +++ b/validator/cmd/valcli/daemoncmd.go @@ -15,23 +15,6 @@ import ( dc "github.com/babylonchain/btc-validator/validator/service/client" ) -var daemonCommands = []cli.Command{ - { - Name: "daemon", - ShortName: "dn", - Usage: "More advanced commands which require validator daemon to be running.", - Category: "Daemon commands", - Subcommands: []cli.Command{ - getDaemonInfoCmd, - createValDaemonCmd, - lsValDaemonCmd, - valInfoDaemonCmd, - registerValDaemonCmd, - addFinalitySigDaemonCmd, - }, - }, -} - const ( valdDaemonAddressFlag = "daemon-address" keyNameFlag = "key-name" diff --git a/validator/cmd/valcli/main.go b/validator/cmd/valcli/main.go index cc9cbd78..e101e79a 100644 --- a/validator/cmd/valcli/main.go +++ b/validator/cmd/valcli/main.go @@ -3,11 +3,10 @@ package main import ( "encoding/json" "fmt" + "github.com/babylonchain/btc-validator/config" "os" "github.com/urfave/cli" - - valcfg "github.com/babylonchain/btc-validator/validator/config" ) func fatal(err error) { @@ -27,7 +26,6 @@ func printRespJSON(resp interface{}) { const ( dbTypeFlag = "db-type" - dbPathFlag = "db-path" dbNameFlag = "db-name" ) @@ -39,22 +37,23 @@ func main() { cli.StringFlag{ Name: dbTypeFlag, Usage: "The type of the database", - Value: valcfg.DefaultBackend, - }, - cli.StringFlag{ - Name: dbPathFlag, - Usage: "The path of the database file", - Value: valcfg.DefaultDBPath, + Value: config.DefaultBackend, }, cli.StringFlag{ Name: dbNameFlag, Usage: "The name of the database bucket", - Value: valcfg.DefaultDBName, + Value: config.DefaultDBName, }, } - app.Commands = append(app.Commands, daemonCommands...) - app.Commands = append(app.Commands, adminCommands...) + app.Commands = append(app.Commands, + getDaemonInfoCmd, + createValDaemonCmd, + lsValDaemonCmd, + valInfoDaemonCmd, + registerValDaemonCmd, + addFinalitySigDaemonCmd, + ) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/validator/cmd/vald/flags.go b/validator/cmd/vald/flags.go new file mode 100644 index 00000000..e34735b4 --- /dev/null +++ b/validator/cmd/vald/flags.go @@ -0,0 +1,10 @@ +package main + +const ( + homeFlag = "home" + forceFlag = "force" + passphraseFlag = "passphrase" + valPkFlag = "validator-pk" + + defaultPassphrase = "" +) diff --git a/validator/cmd/vald/init.go b/validator/cmd/vald/init.go new file mode 100644 index 00000000..ec8e08c6 --- /dev/null +++ b/validator/cmd/vald/init.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "github.com/babylonchain/btc-validator/util" + valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + "path/filepath" +) + +var initCommand = cli.Command{ + Name: "init", + Usage: "Initialize a validator home directory", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to where the home directory will be initialized", + Value: valcfg.DefaultValdDir, + }, + cli.BoolFlag{ + Name: forceFlag, + Usage: "Override existing configuration", + Required: false, + }, + }, + Action: initHome, +} + +func initHome(c *cli.Context) error { + homePath, err := filepath.Abs(c.String(homeFlag)) + if err != nil { + return err + } + // Create home directory + homePath = util.CleanAndExpandPath(homePath) + force := c.Bool(forceFlag) + + if util.FileExists(homePath) && !force { + return fmt.Errorf("home path %s already exists", homePath) + } + + if err := util.MakeDirectory(homePath); err != nil { + return err + } + // Create log directory + logDir := valcfg.LogDir(homePath) + if err := util.MakeDirectory(logDir); err != nil { + return err + } + + defaultConfig := valcfg.DefaultConfigWithHome(homePath) + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(valcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} diff --git a/validator/cmd/vald/main.go b/validator/cmd/vald/main.go index 717d82cf..b2923474 100644 --- a/validator/cmd/vald/main.go +++ b/validator/cmd/vald/main.go @@ -16,7 +16,7 @@ func main() { app := cli.NewApp() app.Name = "vald" app.Usage = "BTC Validator Daemon (vald)." - app.Commands = append(app.Commands, startValidator) + app.Commands = append(app.Commands, startCommand, initCommand) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/validator/cmd/vald/start.go b/validator/cmd/vald/start.go index 22c2fbed..57ffe188 100644 --- a/validator/cmd/vald/start.go +++ b/validator/cmd/vald/start.go @@ -2,24 +2,18 @@ package main import ( "fmt" - "github.com/babylonchain/babylon/types" + "github.com/babylonchain/btc-validator/log" + "github.com/babylonchain/btc-validator/util" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" + "path/filepath" valcfg "github.com/babylonchain/btc-validator/validator/config" "github.com/babylonchain/btc-validator/validator/service" ) -const ( - passphraseFlag = "passphrase" - configFileFlag = "config" - valPkFlag = "validator-pk" - - defaultPassphrase = "" -) - -var startValidator = cli.Command{ +var startCommand = cli.Command{ Name: "start", Usage: "vald start", Description: "Start the validator daemon. Note that eotsd should be started beforehand", @@ -30,29 +24,38 @@ var startValidator = cli.Command{ Value: defaultPassphrase, }, cli.StringFlag{ - Name: configFileFlag, - Usage: "The path to the covenant config file", - Value: valcfg.DefaultConfigFile, + Name: homeFlag, + Usage: "The path to the validator home directory", + Value: valcfg.DefaultValdDir, }, cli.StringFlag{ Name: valPkFlag, Usage: "The public key of the validator to start", }, }, - Action: startValidatorFn, + Action: start, } -func startValidatorFn(ctx *cli.Context) error { +func start(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) passphrase := ctx.String(passphraseFlag) - configFilePath := ctx.String(configFileFlag) valPkStr := ctx.String(valPkFlag) - cfg, cfgLogger, err := valcfg.LoadConfig(configFilePath) + cfg, err := valcfg.LoadConfig(homePath) if err != nil { return fmt.Errorf("failed to load configuration: %w", err) } - valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger) + logger, err := log.NewRootLoggerWithFile(valcfg.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to initialize the logger") + } + + valApp, err := service.NewValidatorAppFromConfig(homePath, cfg, logger) if err != nil { return fmt.Errorf("failed to create validator app: %v", err) } @@ -80,7 +83,7 @@ func startValidatorFn(ctx *cli.Context) error { return err } - valServer := service.NewValidatorServer(cfg, cfgLogger, valApp, shutdownInterceptor) + valServer := service.NewValidatorServer(cfg, logger, valApp, shutdownInterceptor) return valServer.RunUntilShutdown() } diff --git a/validator/config/config.go b/validator/config/config.go index 16af999e..b2e1c3d4 100644 --- a/validator/config/config.go +++ b/validator/config/config.go @@ -2,20 +2,13 @@ package valcfg import ( "fmt" - "io" + "github.com/babylonchain/btc-validator/util" "net" - "os" - "os/user" "path/filepath" "strconv" - "strings" "time" - "go.uber.org/zap" - "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/log" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" @@ -24,7 +17,6 @@ import ( ) const ( - defaultDataDirname = "data" defaultChainName = "babylon" defaultLogLevel = "info" defaultLogDirname = "logs" @@ -44,6 +36,8 @@ const ( defaultFastSyncGap = 6 defaultMaxSubmissionRetries = 20 defaultBitcoinNetwork = "simnet" + defaultDataDirname = "data" + defaultDBPath = "bbolt-vald.db" ) var ( @@ -52,11 +46,7 @@ var ( // ~/Library/Application Support/Vald on MacOS DefaultValdDir = btcutil.AppDataDir("vald", false) - DefaultConfigFile = filepath.Join(DefaultValdDir, defaultConfigFileName) - - defaultDataDir = filepath.Join(DefaultValdDir, defaultDataDirname) - defaultLogDir = filepath.Join(DefaultValdDir, defaultLogDirname) - defaultActiveNetParams = chaincfg.SimNetParams + defaultBTCNetParams = chaincfg.SimNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) ) @@ -66,11 +56,6 @@ 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"` // ChainName and ChainID (if any) of the chain config identify a consumer chain ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` - ValdDir string `long:"validatorddir" description:"The base directory that contains validator's data, logs, configuration file, etc."` - ConfigFile string `long:"configfile" description:"Path to configuration file"` - DataDir string `long:"datadir" description:"The directory to store validator's data within"` - LogDir string `long:"logdir" description:"Directory to log output."` - DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` @@ -84,15 +69,13 @@ type Config struct { FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` - BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` + BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` - ActiveNetParams chaincfg.Params + BTCNetParams chaincfg.Params PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` - DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` - - EOTSManagerConfig *EOTSManagerConfig `group:"eotsmanagerconfig" namespace:"eotsmanagerconfig"` + DatabaseConfig *config.DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` @@ -101,26 +84,20 @@ type Config struct { RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` } -func DefaultConfig() Config { +func DefaultConfigWithHome(homePath string) Config { bbnCfg := config.DefaultBBNConfig() bbnCfg.Key = defaultValidatorKeyName - bbnCfg.KeyDirectory = DefaultValdDir - dbCfg := DefaultDatabaseConfig() + bbnCfg.KeyDirectory = homePath + dbCfg := config.DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() valCfg := DefaultValidatorConfig() - eotsMngrCfg := DefaultEOTSManagerConfig() cfg := Config{ - ValdDir: DefaultValdDir, ChainName: defaultChainName, - ConfigFile: DefaultConfigFile, - DataDir: defaultDataDir, LogLevel: defaultLogLevel, - LogDir: defaultLogDir, DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, ValidatorModeConfig: &valCfg, PollerConfig: &pollerCfg, - EOTSManagerConfig: &eotsMngrCfg, NumPubRand: defaultNumPubRand, NumPubRandMax: defaultNumPubRandMax, MinRandHeightGap: defaultMinRandHeightGap, @@ -133,33 +110,40 @@ func DefaultConfig() Config { FastSyncGap: defaultFastSyncGap, MaxSubmissionRetries: defaultMaxSubmissionRetries, BitcoinNetwork: defaultBitcoinNetwork, - ActiveNetParams: defaultActiveNetParams, + BTCNetParams: defaultBTCNetParams, EOTSManagerAddress: defaultEOTSManagerAddress, RpcListener: defaultRpcListener, } - _ = cfg.Validate() + if err := cfg.Validate(); err != nil { + panic(err) + } return cfg } -func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) { - dbCfg, err := eotscfg.NewDatabaseConfig( - appCfg.EOTSManagerConfig.DBBackend, - appCfg.EOTSManagerConfig.DBPath, - appCfg.EOTSManagerConfig.DBName, - ) - if err != nil { - return nil, err - } - return &eotscfg.Config{ - LogLevel: appCfg.LogLevel, - EOTSDir: appCfg.ValdDir, - ConfigFile: appCfg.ConfigFile, - KeyDirectory: appCfg.BabylonConfig.KeyDirectory, - KeyringBackend: appCfg.BabylonConfig.KeyringBackend, - DatabaseConfig: dbCfg, - }, nil +func DefaultConfig() Config { + return DefaultConfigWithHome(DefaultValdDir) +} + +func ConfigFile(homePath string) string { + return filepath.Join(homePath, defaultConfigFileName) +} + +func LogDir(homePath string) string { + return filepath.Join(homePath, defaultLogDirname) +} + +func LogFile(homePath string) string { + return filepath.Join(LogDir(homePath), defaultLogFilename) +} + +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 @@ -170,138 +154,56 @@ func NewEOTSManagerConfigFromAppConfig(appCfg *Config) (*eotscfg.Config, error) // 2. Pre-parse the command line to check for an alternative config file // 3. Load configuration file overwriting defaults with any specified options // 4. Parse CLI options and overwrite/add any specified options -func LoadConfig(filePath string) (*Config, *zap.Logger, error) { - // Pre-parse the command line options to pick up an alternative config - // file. - preCfg := DefaultConfig() - if _, err := flags.Parse(&preCfg); err != nil { - return nil, nil, err - } - - if !FileExists(filePath) { - return nil, nil, fmt.Errorf("specified config file does "+ - "not exist in %s", filePath) +func LoadConfig(homePath string) (*Config, error) { + // The home directory is required to have a configuration file with a specific name + // under it. + cfgFile := ConfigFile(homePath) + if !util.FileExists(cfgFile) { + return nil, fmt.Errorf("specified config file does "+ + "not exist in %s", cfgFile) } // Next, load any additional configuration options from the file. - var configFileError error - cfg := preCfg + var cfg Config fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(filePath) + err := flags.NewIniParser(fileParser).ParseFile(cfgFile) if err != nil { - // If it's a parsing related error, then we'll return - // immediately, otherwise we can proceed as possibly the config - // file doesn't exist which is OK. - if _, ok := err.(*flags.IniError); ok { - return nil, nil, err - } - - configFileError = err + return nil, err } // Make sure everything we just loaded makes sense. if err := cfg.Validate(); err != nil { - return nil, nil, err - } - - // At this point we know config is valid, create logger which also log to file - logFilePath := filepath.Join(cfg.LogDir, defaultLogFilename) - f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - return nil, nil, err - } - mw := io.MultiWriter(os.Stdout, f) - - cfgLogger, err := log.NewRootLogger("console", cfg.LogLevel, mw) - if err != nil { - return nil, nil, err - } - - // Warn about missing config file only after all other configuration is - // done. This prevents the warning on help messages and invalid - // options. Note this should go directly before the return. - if configFileError != nil { - if cfg.DumpCfg { - cfgLogger.Info("Writing configuration file", zap.String("path", filePath)) - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).WriteFile(filePath, flags.IniIncludeComments|flags.IniIncludeDefaults) - if err != nil { - cfgLogger.Error("Error writing configuration file", zap.Error(err)) - return nil, nil, err - } - } + return nil, err } - return &cfg, cfgLogger, nil + return &cfg, nil } // Validate checks the given configuration to be sane. This makes sure no // illegal values or combination of values are set. All file system paths are // normalized. The cleaned up config is returned on success. func (cfg *Config) Validate() error { - // If the provided stakerd directory is not the default, we'll modify the - // path to all the files and directories that will live within it. - valdDir := CleanAndExpandPath(cfg.ValdDir) - if valdDir != DefaultValdDir { - cfg.DataDir = filepath.Join(valdDir, defaultDataDirname) - cfg.LogDir = filepath.Join(valdDir, defaultLogDirname) + if cfg.EOTSManagerAddress == "" { + return fmt.Errorf("EOTS manager address not specified") } - - makeDirectory := func(dir string) error { - err := os.MkdirAll(dir, 0700) - if err != nil { - // Show a nicer error message if it's because a symlink - // is linked to a directory that does not exist - // (probably because it's not mounted). - if e, ok := err.(*os.PathError); ok && os.IsExist(err) { - link, lerr := os.Readlink(e.Path) - if lerr == nil { - str := "is symlink %s -> %s mounted?" - err = fmt.Errorf(str, e.Path, link) - } - } - - return fmt.Errorf("failed to create dir %s: %w", dir, err) - } - - return nil - } - - // As soon as we're done parsing configuration options, ensure all - // paths to directories and files are cleaned and expanded before - // attempting to use them later on. - cfg.DataDir = CleanAndExpandPath(cfg.DataDir) - cfg.LogDir = CleanAndExpandPath(cfg.LogDir) - // Multiple networks can't be selected simultaneously. Count number of // network flags passed; assign active network params // while we're at it. - switch cfg.BitcoinNetwork { + case "mainnet": + cfg.BTCNetParams = chaincfg.MainNetParams case "testnet": - cfg.ActiveNetParams = chaincfg.TestNet3Params + cfg.BTCNetParams = chaincfg.TestNet3Params case "regtest": - cfg.ActiveNetParams = chaincfg.RegressionNetParams + cfg.BTCNetParams = chaincfg.RegressionNetParams case "simnet": - cfg.ActiveNetParams = chaincfg.SimNetParams + cfg.BTCNetParams = chaincfg.SimNetParams case "signet": - cfg.ActiveNetParams = chaincfg.SigNetParams + cfg.BTCNetParams = chaincfg.SigNetParams default: return fmt.Errorf("invalid network: %v", cfg.BitcoinNetwork) } - // Create the vald directory and all other subdirectories if they - // don't already exist. This makes sure that directory trees are also - // created for files that point to outside the vald dir. - dirs := []string{ - valdDir, cfg.DataDir, cfg.LogDir, - } - for _, dir := range dirs { - if err := makeDirectory(dir); err != nil { - return err - } - } - _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) if err != nil { return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) @@ -310,40 +212,3 @@ func (cfg *Config) Validate() error { // All good, return the sanitized result. return nil } - -// FileExists reports whether the named file or directory exists. -// This function is taken from https://github.com/btcsuite/btcd -func FileExists(name string) bool { - if _, err := os.Stat(name); err != nil { - if os.IsNotExist(err) { - return false - } - } - return true -} - -// CleanAndExpandPath expands environment variables and leading ~ in the -// passed path, cleans the result, and returns it. -// This function is taken from https://github.com/btcsuite/btcd -func CleanAndExpandPath(path string) string { - if path == "" { - return "" - } - - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - var homeDir string - u, err := user.Current() - if err == nil { - homeDir = u.HomeDir - } else { - homeDir = os.Getenv("HOME") - } - - path = strings.Replace(path, "~", homeDir, 1) - } - - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but the variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) -} diff --git a/validator/config/dbcfg.go b/validator/config/dbcfg.go deleted file mode 100644 index 181fe994..00000000 --- a/validator/config/dbcfg.go +++ /dev/null @@ -1,44 +0,0 @@ -package valcfg - -import "fmt" - -const ( - DefaultBackend = "bbolt" - DefaultDBPath = "bbolt.db" - DefaultDBName = "default" -) - -type DatabaseConfig struct { - Backend string `long:"backend" description:"Possible database to choose as backend"` - Path string `long:"path" description:"The path that stores the database file"` - Name string `long:"name" description:"The name of the database"` -} - -func NewDatabaseConfig(backend string, path 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 path == "" { - return nil, fmt.Errorf("DB path should not be empty") - } - - if name == "" { - return nil, fmt.Errorf("bucket name should not be empty") - } - - return &DatabaseConfig{ - Backend: backend, - Path: path, - Name: name, - }, nil -} - -func DefaultDatabaseConfig() DatabaseConfig { - return DatabaseConfig{ - Backend: DefaultBackend, - Path: DefaultDBPath, - Name: DefaultDBName, - } -} diff --git a/validator/service/app.go b/validator/service/app.go index 8adb8c1e..88551aeb 100644 --- a/validator/service/app.go +++ b/validator/service/app.go @@ -3,6 +3,7 @@ package service import ( "encoding/hex" "fmt" + "github.com/babylonchain/btc-validator/util" "strings" "sync" @@ -54,46 +55,39 @@ type ValidatorApp struct { } func NewValidatorAppFromConfig( + homePath string, config *valcfg.Config, logger *zap.Logger, ) (*ValidatorApp, error) { - cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.ActiveNetParams, logger) + cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.BTCNetParams, logger) if err != nil { return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) } // if the EOTSManagerAddress is empty, run a local EOTS manager; // otherwise connect a remote one with a gRPC client - var em eotsmanager.EOTSManager - if config.EOTSManagerAddress == "" { - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(config) - if err != nil { - return nil, err - } - em, err = eotsmanager.NewLocalEOTSManager(eotsCfg, logger) - if err != nil { - return nil, fmt.Errorf("failed to create EOTS manager locally: %w", err) - } - - logger.Info("running EOTS manager locally") - } else { - em, err = client.NewEOTSManagerGRpcClient(config.EOTSManagerAddress) - if err != nil { - return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) - } - // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy - logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) + em, err := client.NewEOTSManagerGRpcClient(config.EOTSManagerAddress) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) } + // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) - return NewValidatorApp(config, cc, em, logger) + return NewValidatorApp(homePath, config, cc, em, logger) } func NewValidatorApp( + homePath string, config *valcfg.Config, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, logger *zap.Logger, ) (*ValidatorApp, error) { + valStore, err := initStore(homePath, config) + if err != nil { + return nil, fmt.Errorf("failed to load store: %w", err) + } + input := strings.NewReader("") kr, err := valkr.CreateKeyring( config.BabylonConfig.KeyDirectory, @@ -105,11 +99,6 @@ func NewValidatorApp( return nil, fmt.Errorf("failed to create keyring: %w", err) } - valStore, err := valstore.NewValidatorStore(config.DatabaseConfig) - if err != nil { - return nil, fmt.Errorf("failed to open the store for validators: %w", err) - } - vm, err := NewValidatorManager(valStore, config, cc, em, logger) if err != nil { return nil, fmt.Errorf("failed to create validator manager: %w", err) @@ -133,6 +122,15 @@ func NewValidatorApp( }, nil } +func initStore(homePath string, cfg *valcfg.Config) (*valstore.ValidatorStore, error) { + // Create the directory that will store the data + if err := util.MakeDirectory(valcfg.DataDir(homePath)); err != nil { + return nil, err + } + + return valstore.NewValidatorStore(valcfg.DBPath(homePath), cfg.DatabaseConfig.Name, cfg.DatabaseConfig.Backend) +} + func (app *ValidatorApp) GetConfig() *valcfg.Config { return app.config } diff --git a/validator/service/app_test.go b/validator/service/app_test.go index 1edb8f6f..4095b758 100644 --- a/validator/service/app_test.go +++ b/validator/service/app_test.go @@ -3,6 +3,7 @@ package service_test import ( "math/rand" "os" + "path/filepath" "testing" bbntypes "github.com/babylonchain/babylon/types" @@ -14,7 +15,6 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/validator/service" ) @@ -29,30 +29,34 @@ func FuzzRegisterValidator(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - // create validator app with db and mocked Babylon client - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) + 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) + require.NoError(t, err) defer func() { - err := os.RemoveAll(cfg.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) - require.NoError(t, err) - err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) + err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) }() + + // Create mocked babylon client randomStartingHeight := uint64(r.Int63n(100) + 1) - cfg.ValidatorModeConfig.AutoChainScanningMode = false - cfg.ValidatorModeConfig.StaticChainScanningStartHeight = randomStartingHeight currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) - require.NoError(t, err) - logger := zap.NewNop() - em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) - require.NoError(t, err) - app, err := service.NewValidatorApp(&cfg, mockClientController, em, logger) + + // Create randomized config + valHomeDir := filepath.Join(t.TempDir(), "val-home") + valCfg := testutil.GenValConfig(r, t, valHomeDir) + valCfg.ValidatorModeConfig.AutoChainScanningMode = false + valCfg.ValidatorModeConfig.StaticChainScanningStartHeight = randomStartingHeight + app, err := service.NewValidatorApp(valHomeDir, valCfg, mockClientController, em, logger) require.NoError(t, err) + defer func() { + err = os.RemoveAll(valHomeDir) + require.NoError(t, err) + }() err = app.Start() require.NoError(t, err) diff --git a/validator/service/validator_instance.go b/validator/service/validator_instance.go index 80f8e48c..4614d2e0 100644 --- a/validator/service/validator_instance.go +++ b/validator/service/validator_instance.go @@ -212,6 +212,10 @@ func (v *ValidatorInstance) finalitySigSubmissionLoop() { v.reportCriticalErr(err) continue } + if res == nil { + v.reportCriticalErr(fmt.Errorf("received an empty response when submitting finality sig")) + continue + } v.logger.Info( "successfully submitted a finality signature to the consumer chain", zap.String("pk", v.GetBtcPkHex()), diff --git a/validator/service/validator_instance_test.go b/validator/service/validator_instance_test.go index 96ceaee8..a3f436d3 100644 --- a/validator/service/validator_instance_test.go +++ b/validator/service/validator_instance_test.go @@ -3,6 +3,7 @@ package service_test import ( "math/rand" "os" + "path/filepath" "testing" "github.com/golang/mock/gomock" @@ -13,7 +14,6 @@ import ( "github.com/babylonchain/btc-validator/eotsmanager" "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/validator/service" ) @@ -97,19 +97,20 @@ func FuzzSubmitFinalitySig(f *testing.F) { } func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.ValidatorApp, *proto.StoreValidator, func()) { - // create validator app with config - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - cfg.BabylonConfig.KeyDirectory = t.TempDir() - cfg.NumPubRand = uint64(25) - cfg.ValidatorModeConfig.AutoChainScanningMode = false - cfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight logger := zap.NewNop() - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) + // create an EOTS manager + eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) require.NoError(t, err) - em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) - require.NoError(t, err) - app, err := service.NewValidatorApp(&cfg, cc, em, logger) + + // create validator app with randomized config + valHomeDir := filepath.Join(t.TempDir(), "val-home") + valCfg := testutil.GenValConfig(r, t, valHomeDir) + valCfg.NumPubRand = uint64(25) + valCfg.ValidatorModeConfig.AutoChainScanningMode = false + valCfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight + app, err := service.NewValidatorApp(valHomeDir, valCfg, cc, em, logger) require.NoError(t, err) err = app.Start() require.NoError(t, err) @@ -121,15 +122,12 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK(), passphrase) require.NoError(t, err) - config := app.GetConfig() cleanUp := func() { err = app.Stop() require.NoError(t, err) - err := os.RemoveAll(config.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(config.BabylonConfig.KeyDirectory) + err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) - err = os.RemoveAll(config.EOTSManagerConfig.DBPath) + err = os.RemoveAll(valHomeDir) require.NoError(t, err) } diff --git a/validator/service/validator_manager_test.go b/validator/service/validator_manager_test.go index e791a587..94831315 100644 --- a/validator/service/validator_manager_test.go +++ b/validator/service/validator_manager_test.go @@ -1,8 +1,11 @@ package service_test import ( + "github.com/babylonchain/btc-validator/util" + valcfg "github.com/babylonchain/btc-validator/validator/config" "math/rand" "os" + "path/filepath" "strings" "testing" "time" @@ -22,7 +25,6 @@ import ( "github.com/babylonchain/btc-validator/testutil" "github.com/babylonchain/btc-validator/testutil/mocks" "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/validator/service" valstore "github.com/babylonchain/btc-validator/validator/store" @@ -90,31 +92,35 @@ func waitForStatus(t *testing.T, valIns *service.ValidatorInstance, s proto.Vali } func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.ValidatorManager, *bbntypes.BIP340PubKey, func()) { - // create validator app with config - cfg := valcfg.DefaultConfig() - cfg.StatusUpdateInterval = 10 * time.Millisecond - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - cfg.BabylonConfig.KeyDirectory = t.TempDir() 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) + require.NoError(t, err) + // create validator app with randomized config + valHomeDir := filepath.Join(t.TempDir(), "val-home") + valCfg := testutil.GenValConfig(r, t, valHomeDir) + valCfg.StatusUpdateInterval = 10 * time.Millisecond input := strings.NewReader("") kr, err := keyring.CreateKeyring( - cfg.BabylonConfig.KeyDirectory, - cfg.BabylonConfig.ChainID, - cfg.BabylonConfig.KeyringBackend, + valCfg.BabylonConfig.KeyDirectory, + valCfg.BabylonConfig.ChainID, + valCfg.BabylonConfig.KeyringBackend, input, ) require.NoError(t, err) - - valStore, err := valstore.NewValidatorStore(cfg.DatabaseConfig) - require.NoError(t, err) - - eotsCfg, err := valcfg.NewEOTSManagerConfigFromAppConfig(&cfg) + err = util.MakeDirectory(valcfg.DataDir(valHomeDir)) require.NoError(t, err) - em, err := eotsmanager.NewLocalEOTSManager(eotsCfg, logger) + valStore, err := valstore.NewValidatorStore( + valcfg.DBPath(valHomeDir), + valCfg.DatabaseConfig.Name, + valCfg.DatabaseConfig.Backend, + ) require.NoError(t, err) - vm, err := service.NewValidatorManager(valStore, &cfg, cc, em, logger) + vm, err := service.NewValidatorManager(valStore, valCfg, cc, em, logger) require.NoError(t, err) // create registered validator @@ -142,11 +148,9 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c cleanUp := func() { err = vm.Stop() require.NoError(t, err) - err := os.RemoveAll(cfg.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) + err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) - err = os.RemoveAll(cfg.EOTSManagerConfig.DBPath) + err = os.RemoveAll(valHomeDir) require.NoError(t, err) } diff --git a/validator/store/valstore.go b/validator/store/valstore.go index cbc6c61a..ae1ece03 100644 --- a/validator/store/valstore.go +++ b/validator/store/valstore.go @@ -10,9 +10,8 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" gproto "google.golang.org/protobuf/proto" - "github.com/babylonchain/btc-validator/validator/proto" "github.com/babylonchain/btc-validator/store" - valcfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/btc-validator/validator/proto" ) const ( @@ -39,8 +38,8 @@ type ValidatorStore struct { s store.Store } -func NewValidatorStore(dbcfg *valcfg.DatabaseConfig) (*ValidatorStore, error) { - s, err := openStore(dbcfg) +func NewValidatorStore(dbPath string, dbName string, dbBackend string) (*ValidatorStore, error) { + s, err := openStore(dbPath, dbName, dbBackend) if err != nil { return nil, err } @@ -201,10 +200,10 @@ func (vs *ValidatorStore) Close() error { // openStore returns a Store instance with the given db type, path and name // currently, we only support bbolt -func openStore(dbcfg *valcfg.DatabaseConfig) (store.Store, error) { - switch dbcfg.Backend { +func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { + switch dbBackend { case "bbolt": - return store.NewBboltStore(dbcfg.Path, dbcfg.Name) + return store.NewBboltStore(dbPath, dbName) default: return nil, fmt.Errorf("unsupported database type") } diff --git a/validator/store/valstore_test.go b/validator/store/valstore_test.go index 39f4c8a2..6cde8a53 100644 --- a/validator/store/valstore_test.go +++ b/validator/store/valstore_test.go @@ -3,6 +3,7 @@ package store_test import ( "math/rand" "os" + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -17,12 +18,13 @@ func FuzzValidatorStore(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 := valstore.NewValidatorStore(dbcfg) + vs, err := valstore.NewValidatorStore(dbPath, dbcfg.Name, dbcfg.Backend) require.NoError(t, err) defer func() { - err := os.RemoveAll(dbcfg.Path) + err := os.RemoveAll(dbPath) require.NoError(t, err) }() From e46c83db7687fc88e9f77c94ebdc1b7f0283bf86 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 8 Dec 2023 15:37:08 +0800 Subject: [PATCH 32/66] chore: Add configurable limit on running multiple validators (#172) --- itest/e2e_test.go | 52 +++++++++++- itest/test_manager.go | 83 ++++++++++---------- validator/config/config.go | 13 +-- validator/config/eotsmanager.go | 21 ----- validator/config/poller.go | 17 ++-- validator/config/validator.go | 13 --- validator/service/app_test.go | 4 +- validator/service/validator_instance.go | 4 +- validator/service/validator_instance_test.go | 4 +- validator/service/validator_manager.go | 28 ++++--- 10 files changed, 133 insertions(+), 106 deletions(-) delete mode 100644 validator/config/eotsmanager.go delete mode 100644 validator/config/validator.go diff --git a/itest/e2e_test.go b/itest/e2e_test.go index ee0afd45..6f928e34 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/btc-validator/validator/service" ) var ( @@ -25,9 +26,11 @@ var ( // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization func TestValidatorLifeCycle(t *testing.T) { - tm, valIns := StartManagerWithValidator(t) + tm, valInsList := StartManagerWithValidator(t, 1) defer tm.Stop(t) + valIns := valInsList[0] + params := tm.GetParams(t) // check the public randomness is committed @@ -52,9 +55,11 @@ func TestValidatorLifeCycle(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, valIns := StartManagerWithValidator(t) + tm, valInsList := StartManagerWithValidator(t, 1) defer tm.Stop(t) + valIns := valInsList[0] + params := tm.GetParams(t) // check the public randomness is committed @@ -92,11 +97,48 @@ func TestDoubleSigning(t *testing.T) { t.Logf("the equivocation attack is successful") } +// TestMultipleValidators tests starting with multiple validators +func TestMultipleValidators(t *testing.T) { + n := 3 + tm, valInstances := StartManagerWithValidator(t, n) + defer tm.Stop(t) + + params := tm.GetParams(t) + + // submit BTC delegations for each validator + for _, valIns := range valInstances { + tm.Wg.Add(1) + go func(v *service.ValidatorInstance) { + defer tm.Wg.Done() + // check the public randomness is committed + tm.WaitForValPubRandCommitted(t, v) + + // send a BTC delegation + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{v.MustGetBtcPk()}, stakingTime, stakingAmount, params) + }(valIns) + } + tm.Wg.Wait() + + for _, valIns := range valInstances { + tm.Wg.Add(1) + go func(v *service.ValidatorInstance) { + defer tm.Wg.Done() + _ = tm.WaitForValNActiveDels(t, v.GetBtcPkBIP340(), 1) + }(valIns) + } + tm.Wg.Wait() + + // check there's a block finalized + _ = tm.WaitForNFinalizedBlocks(t, 1) +} + // TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm, valIns := StartManagerWithValidator(t) + tm, valInsList := StartManagerWithValidator(t, 1) defer tm.Stop(t) + valIns := valInsList[0] + params := tm.GetParams(t) // check the public randomness is committed @@ -138,9 +180,11 @@ func TestFastSync(t *testing.T) { } func TestCovenantLifeCycle(t *testing.T) { - tm, valIns := StartManagerWithValidator(t) + tm, valInsList := StartManagerWithValidator(t, 1) defer tm.Stop(t) + valIns := valInsList[0] + params := tm.GetParams(t) valPk := valIns.MustGetBtcPk() diff --git a/itest/test_manager.go b/itest/test_manager.go index eae4bf2d..a7a934a3 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -150,55 +150,58 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T) (*TestManager, *service.ValidatorInstance) { +func StartManagerWithValidator(t *testing.T, n int) (*TestManager, []*service.ValidatorInstance) { tm := StartManager(t) app := tm.Va - valName := valNamePrefix + strconv.Itoa(0) - moniker := monikerPrefix + strconv.Itoa(0) - commission := sdkmath.LegacyZeroDec() - desc, err := newDescription(moniker).Marshal() - require.NoError(t, err) - res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, desc, &commission) - require.NoError(t, err) - _, err = app.RegisterValidator(res.ValPk.MarshalHex()) - require.NoError(t, err) - err = app.StartHandlingValidator(res.ValPk, passphrase) - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(res.ValPk) - require.NoError(t, err) - require.True(t, valIns.IsRunning()) - require.NoError(t, err) - - // check validators on Babylon side - require.Eventually(t, func() bool { - vals, err := tm.BabylonClient.QueryValidators() - if err != nil { - t.Logf("failed to query validtors from Babylon %s", err.Error()) - return false - } - - if len(vals) != 1 { - return false - } - - for _, v := range vals { - if !strings.Contains(v.Description.Moniker, monikerPrefix) { + for i := 0; i < n; i++ { + valName := valNamePrefix + strconv.Itoa(i) + moniker := monikerPrefix + strconv.Itoa(i) + commission := sdkmath.LegacyZeroDec() + desc, err := newDescription(moniker).Marshal() + require.NoError(t, err) + res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, desc, &commission) + require.NoError(t, err) + _, err = app.RegisterValidator(res.ValPk.MarshalHex()) + require.NoError(t, err) + err = app.StartHandlingValidator(res.ValPk, passphrase) + require.NoError(t, err) + valIns, err := app.GetValidatorInstance(res.ValPk) + require.NoError(t, err) + require.True(t, valIns.IsRunning()) + require.NoError(t, err) + + // check validators on Babylon side + require.Eventually(t, func() bool { + vals, err := tm.BabylonClient.QueryValidators() + if err != nil { + t.Logf("failed to query validtors from Babylon %s", err.Error()) return false } - if !v.Commission.Equal(sdkmath.LegacyZeroDec()) { + + if len(vals) != i+1 { return false } - } - return true - }, eventuallyWaitTimeOut, eventuallyPollTime) + for _, v := range vals { + if !strings.Contains(v.Description.Moniker, monikerPrefix) { + return false + } + if !v.Commission.Equal(sdkmath.LegacyZeroDec()) { + return false + } + } + + return true + }, eventuallyWaitTimeOut, eventuallyPollTime) + } - require.Equal(t, 1, len(app.ListValidatorInstances())) + valInsList := app.ListValidatorInstances() + require.Equal(t, n, len(valInsList)) - t.Logf("the test manager is running with a validator") + t.Logf("the test manager is running with %v validator(s)", len(valInsList)) - return tm, valIns + return tm, valInsList } func (tm *TestManager) Stop(t *testing.T) { @@ -382,7 +385,7 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, t.Log("restarting the validator instance") - tm.ValConfig.ValidatorModeConfig.AutoChainScanningMode = true + tm.ValConfig.PollerConfig.AutoChainScanningMode = true err = valIns.Start() require.NoError(t, err) } @@ -559,7 +562,7 @@ func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { func defaultValidatorConfig(keyringDir, homeDir string) *valcfg.Config { cfg := valcfg.DefaultConfigWithHome(homeDir) - cfg.ValidatorModeConfig.AutoChainScanningMode = false + cfg.PollerConfig.AutoChainScanningMode = false // babylon configs for sending transactions cfg.BabylonConfig.KeyDirectory = keyringDir // need to use this one to send otherwise we will have account sequence mismatch diff --git a/validator/config/config.go b/validator/config/config.go index b2e1c3d4..8d695be1 100644 --- a/validator/config/config.go +++ b/validator/config/config.go @@ -2,17 +2,19 @@ package valcfg import ( "fmt" - "github.com/babylonchain/btc-validator/util" "net" "path/filepath" "strconv" "time" - "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/btc-validator/util" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" + "github.com/babylonchain/btc-validator/config" + eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" ) @@ -38,6 +40,7 @@ const ( defaultBitcoinNetwork = "simnet" defaultDataDirname = "data" defaultDBPath = "bbolt-vald.db" + defaultMaxNumValidators = 3 ) var ( @@ -68,6 +71,7 @@ type Config struct { FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` + MaxNumValidators uint32 `long:"maxnumvalidators" description:"The maximum number of validator instances running concurrently within the daemon"` BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` @@ -79,8 +83,6 @@ type Config struct { BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` - ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` } @@ -90,13 +92,11 @@ func DefaultConfigWithHome(homePath string) Config { bbnCfg.KeyDirectory = homePath dbCfg := config.DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() - valCfg := DefaultValidatorConfig() cfg := Config{ ChainName: defaultChainName, LogLevel: defaultLogLevel, DatabaseConfig: &dbCfg, BabylonConfig: &bbnCfg, - ValidatorModeConfig: &valCfg, PollerConfig: &pollerCfg, NumPubRand: defaultNumPubRand, NumPubRandMax: defaultNumPubRandMax, @@ -113,6 +113,7 @@ func DefaultConfigWithHome(homePath string) Config { BTCNetParams: defaultBTCNetParams, EOTSManagerAddress: defaultEOTSManagerAddress, RpcListener: defaultRpcListener, + MaxNumValidators: defaultMaxNumValidators, } if err := cfg.Validate(); err != nil { diff --git a/validator/config/eotsmanager.go b/validator/config/eotsmanager.go deleted file mode 100644 index a73ca77e..00000000 --- a/validator/config/eotsmanager.go +++ /dev/null @@ -1,21 +0,0 @@ -package valcfg - -const ( - DefaultEOTSManagerDBBackend = "bbolt" - DefaultEOTSManagerDBPath = "bbolt-eots.db" - DefaultEOTSManagerDBName = "eots-default" -) - -type EOTSManagerConfig struct { - DBBackend string `long:"dbbackend" description:"Possible database to choose as backend"` - DBPath string `long:"dbpath" description:"The path that stores the database file"` - DBName string `long:"dbname" description:"The name of the database"` -} - -func DefaultEOTSManagerConfig() EOTSManagerConfig { - return EOTSManagerConfig{ - DBBackend: DefaultEOTSManagerDBBackend, - DBPath: DefaultEOTSManagerDBPath, - DBName: DefaultEOTSManagerDBName, - } -} diff --git a/validator/config/poller.go b/validator/config/poller.go index ecefaf31..b0d29ea8 100644 --- a/validator/config/poller.go +++ b/validator/config/poller.go @@ -3,18 +3,23 @@ package valcfg import "time" var ( - defaultBufferSize = uint32(1000) - defaultPollingInterval = 5 * time.Second + defaultBufferSize = uint32(1000) + defaultPollingInterval = 5 * time.Second + defaultStaticStartHeight = uint64(1) ) type ChainPollerConfig struct { - BufferSize uint32 `long:"buffersize" description:"The maximum number of Babylon blocks that can be stored in the buffer"` - PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of Babylon blocks"` + BufferSize uint32 `long:"buffersize" description:"The maximum number of Babylon blocks that can be stored in the buffer"` + PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of Babylon blocks"` + StaticChainScanningStartHeight uint64 `long:"staticchainscanningstartheight" description:"The static height from which we start polling the chain"` + AutoChainScanningMode bool `long:"autochainscanningmode" description:"Automatically discover the height from which to start polling the chain"` } func DefaultChainPollerConfig() ChainPollerConfig { return ChainPollerConfig{ - BufferSize: defaultBufferSize, - PollInterval: defaultPollingInterval, + BufferSize: defaultBufferSize, + PollInterval: defaultPollingInterval, + StaticChainScanningStartHeight: defaultStaticStartHeight, + AutoChainScanningMode: true, } } diff --git a/validator/config/validator.go b/validator/config/validator.go deleted file mode 100644 index c9470af7..00000000 --- a/validator/config/validator.go +++ /dev/null @@ -1,13 +0,0 @@ -package valcfg - -type ValidatorConfig struct { - StaticChainScanningStartHeight uint64 `long:"staticchainscanningstartheight" description:"The static height from which we start polling the chain"` - AutoChainScanningMode bool `long:"autochainscanningmode" description:"Automatically discover the height from which to start polling the chain"` -} - -func DefaultValidatorConfig() ValidatorConfig { - return ValidatorConfig{ - StaticChainScanningStartHeight: 1, - AutoChainScanningMode: true, - } -} diff --git a/validator/service/app_test.go b/validator/service/app_test.go index 4095b758..1dee92ed 100644 --- a/validator/service/app_test.go +++ b/validator/service/app_test.go @@ -49,8 +49,8 @@ func FuzzRegisterValidator(f *testing.F) { // Create randomized config valHomeDir := filepath.Join(t.TempDir(), "val-home") valCfg := testutil.GenValConfig(r, t, valHomeDir) - valCfg.ValidatorModeConfig.AutoChainScanningMode = false - valCfg.ValidatorModeConfig.StaticChainScanningStartHeight = randomStartingHeight + valCfg.PollerConfig.AutoChainScanningMode = false + valCfg.PollerConfig.StaticChainScanningStartHeight = randomStartingHeight app, err := service.NewValidatorApp(valHomeDir, valCfg, mockClientController, em, logger) require.NoError(t, err) defer func() { diff --git a/validator/service/validator_instance.go b/validator/service/validator_instance.go index 4614d2e0..7ec9322d 100644 --- a/validator/service/validator_instance.go +++ b/validator/service/validator_instance.go @@ -754,8 +754,8 @@ func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *type } func (v *ValidatorInstance) getPollerStartingHeight() (uint64, error) { - if !v.cfg.ValidatorModeConfig.AutoChainScanningMode { - return v.cfg.ValidatorModeConfig.StaticChainScanningStartHeight, nil + if !v.cfg.PollerConfig.AutoChainScanningMode { + return v.cfg.PollerConfig.StaticChainScanningStartHeight, nil } // Set initial block to the maximum of diff --git a/validator/service/validator_instance_test.go b/validator/service/validator_instance_test.go index a3f436d3..1e92f2fc 100644 --- a/validator/service/validator_instance_test.go +++ b/validator/service/validator_instance_test.go @@ -108,8 +108,8 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli valHomeDir := filepath.Join(t.TempDir(), "val-home") valCfg := testutil.GenValConfig(r, t, valHomeDir) valCfg.NumPubRand = uint64(25) - valCfg.ValidatorModeConfig.AutoChainScanningMode = false - valCfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight + valCfg.PollerConfig.AutoChainScanningMode = false + valCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight app, err := service.NewValidatorApp(valHomeDir, valCfg, cc, em, logger) require.NoError(t, err) err = app.Start() diff --git a/validator/service/validator_manager.go b/validator/service/validator_manager.go index b6507cbd..34ed331f 100644 --- a/validator/service/validator_manager.go +++ b/validator/service/validator_manager.go @@ -195,18 +195,19 @@ func (vm *ValidatorManager) setValidatorSlashed(vi *ValidatorInstance) { } func (vm *ValidatorManager) StartValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { - // currently we expect that only a single validator started at a time - // we can remove the constraint when we want to run multiple validators - // in the same daemon - if vm.isStarted.Swap(true) { - return fmt.Errorf("a validator instance is already started") - } + if !vm.isStarted.Load() { + vm.isStarted.Store(true) - vm.wg.Add(1) - go vm.monitorCriticalErr() + vm.wg.Add(1) + go vm.monitorCriticalErr() - vm.wg.Add(1) - go vm.monitorStatusUpdate() + vm.wg.Add(1) + go vm.monitorStatusUpdate() + } + + if vm.numOfRunningValidators() >= int(vm.config.MaxNumValidators) { + return fmt.Errorf("reaching maximum number of running validators %v", vm.config.MaxNumValidators) + } if err := vm.addValidatorInstance(valPk, passphrase); err != nil { return err @@ -282,6 +283,13 @@ func (vm *ValidatorManager) removeValidatorInstance(valPk *bbntypes.BIP340PubKey return nil } +func (vm *ValidatorManager) numOfRunningValidators() int { + vm.mu.Lock() + defer vm.mu.Unlock() + + return len(vm.vals) +} + // addValidatorInstance creates a validator instance, starts it and adds it into the validator manager func (vm *ValidatorManager) addValidatorInstance( pk *bbntypes.BIP340PubKey, From b964419686089fa896490fc9e50e38a459e5f2b8 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Wed, 13 Dec 2023 11:08:08 +0400 Subject: [PATCH 33/66] docs: Combine docs into less pages, update overview, and finality renaming (#178) --- README.md | 146 +++++++++++++------------ docs/eots.md | 111 +++++++++++++++++++ docs/eotsd/eotsd-config.md | 56 ---------- docs/eotsd/eotsd-startup-guide.md | 38 ------- docs/finality-provider.md | 173 ++++++++++++++++++++++++++++++ docs/finality-toolset.png | Bin 0 -> 75814 bytes docs/interacting-with-daemons.md | 67 ------------ docs/vald/vald-config.md | 80 -------------- docs/vald/vald-startup-guide.md | 36 ------- 9 files changed, 356 insertions(+), 351 deletions(-) create mode 100644 docs/eots.md delete mode 100644 docs/eotsd/eotsd-config.md delete mode 100644 docs/eotsd/eotsd-startup-guide.md create mode 100644 docs/finality-provider.md create mode 100644 docs/finality-toolset.png delete mode 100644 docs/interacting-with-daemons.md delete mode 100644 docs/vald/vald-config.md delete mode 100644 docs/vald/vald-startup-guide.md diff --git a/README.md b/README.md index 766ff02a..2b33473b 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,36 @@ -# BTC-Validator +# Finality Provider -## 1. Overview - -BTC-Validator is a standalone program crafted for the creation and management of BTC -validators. The program includes a CLI functionality for the creation, management, -and storage of validator keys, as well as the creation and registration of validators -on the consumer chain. - -Once a validator is registered on the chain, BTC-Validator consistently polls for new -blocks. It actively engages with the blockchain by sending finality signatures and -committing public randomness at regular intervals. - -The program consists of two essential components: the **EOTS manager Daemon** and the -**Validator Daemon**. - -#### 1. EOTS Manager Daemon - -The EOTS Daemon is responsible for managing EOTS keys, producing EOTS randomness and -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). -The BTC validator will commit a unique EOTS randomness at each future height it needs -to vote. If the BTC validator votes for two blocks using the same committed EOTS -randomness, then its secret key will be extracted and all of its BTC delegations will -be slashed on Bitcoin, ensuring slashable safety. +A toolset crafted for the creation and +management of Finality Providers. -1. **EOTS Key Management:** - - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs - for the validator using the - [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) - standard. - - Persists generated key pairs in the - internal [bolt db](https://github.com/etcd-io/bbolt) storage. - -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 validator and corresponding secret - randomness for a given chain at a specified height. - - Signs Schnorr signatures using the private key of the validator. - -#### 2. Validator Daemon - -The Validator Daemon is responsible for committing public randomness and submitting -finality signatures. +## 1. Overview -1. **Finality Signatures:** - - Sends the finality signature to the consumer chain (Babylon) for each - registered validator and for each block there's an EOTS randomness commitment. +Finality providers are responsible for voting +at a finality round on top of [CometBFT](https://github.com/cometbft/cometbft). +Similar to any native PoS validator, +a finality provider can receive voting power delegations from BTC stakers, and +can earn commission from the staking rewards denominated in Babylon tokens. + +The finality provider toolset does not have +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. +- *Extractable One-Time Signature (EOTS) manager*: + A daemon responsible for securely maintaining the finality provider’s + private key and producing extractable one time signatures from it. +- *Finality Provider*: A daemon managing the finality provider. + It connects to the EOTS manager to generate EOTS public randomness and + finality votes for Babylon blocks, which it submits to Babylon through + the node connection. + +The following graphic demonstrates the interconnections between the above programs: + +![Finality Provider Interconnections](./docs/finality-toolset.png) -2. **EOTS Randomness Commitment:** - - Ensures the generation of EOTS randomness commitment on the Babylon ledger for - each block the BTC validator intends to vote for. ## 2. Installation @@ -72,14 +46,14 @@ the [official Go installation guide](https://golang.org/doc/install). To get started, clone the repository to your local machine from Github: ```bash -$ git clone git@github.com:babylonchain/btc-validator.git +$ git clone git@github.com:babylonchain/finality-provider.git ``` You can choose a specific version from -the [official releases page](https://github.com/babylonchain/btc-validator/releases) +the [official releases page](https://github.com/babylonchain/finality-provider/releases) ```bash -$ cd btc-validator # cd into the project directory +$ cd finality-provider # cd into the project directory $ git checkout ``` @@ -87,7 +61,7 @@ $ git checkout ```bash # cd into the project directory -$ cd btc-validator +$ cd finality-provider # installs the compiled binaries to your # $GOPATH/bin directory allowing access @@ -98,14 +72,13 @@ $ make install The above will produce the following binaries: - `eotsd`: The daemon program for the EOTS manager. -- `vald`: The daemon program for the btc-validator. -- `valcli`: The CLI tool for interacting with the btc-validator daemon. -- `covd`: The daemon program for the covenant emulator. +- `fpd`: The daemon program for the finality-provider. +- `fpcli`: The CLI tool for interacting with the finality-provider daemon. To build locally, ```bash -$ cd btc-validator # cd into the project directory +$ cd finality-provider # cd into the project directory $ make build ``` @@ -113,24 +86,49 @@ The above will lead to a build directory having the following structure: ```bash $ ls build - ├── covd ├── eotsd - ├── valcli - └── vald + ├── fpcli + └── fpd ``` -## 3. EOTS Daemon Configuration +## 3. Setting up a finality provider + +#### 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). -Follow the [eots configuration guide](docs/eotsd/eotsd-config.md). +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). -## 4. Starting the EOTS Daemon +#### 3.2. Setting up the EOTS Manager -Follow the [eots startup guide](docs/eotsd/eotsd-startup-guide.md). +After a node and a keyring have been set up, +the operator can set up and run the +Extractable One Time Signature (EOTS) manager daemon. +A complete overview of the EOTS manager, its operation, and +its configuration options can be found in the +[EOTS Manager page](docs/eots.md) -## 5. Validator Daemon Configuration +#### 3.3. Setting up a Finality Provider -Follow the [vald configuration guide](docs/vald/vald-config.md). +The last step is to set up and run +the finality daemon. +A complete overview of the finality daemon, its operation, and +its configuration options can be found in the +[Finality page](docs/finality-provider.md). -## 6. Starting the Validator Daemon +## 4. Delegations & Rewards -Follow the [vald startup guide](docs/vald/vald-startup-guide.md). +A finality provider receives BTC delegations through delegators +interacting with Babylon and choosing it as the recipient of their delegations. +To perform a self-delegation, +the operator can either visit the staking web app we provide, +or run the Babylon [BTC Staker program](https://github.com/babylonchain/btc-staker) once. +The BTC staker connects to a Bitcoin wallet and Babylon to perform delegations. diff --git a/docs/eots.md b/docs/eots.md new file mode 100644 index 00000000..880206c3 --- /dev/null +++ b/docs/eots.md @@ -0,0 +1,111 @@ +# EOTS Manager + +## 1. Overview + +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. + +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. +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 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. + +```bash +$ eotsd init --home /path/to/eotsd/home/ +``` + +After initialization, the home directory will have the following structure + +```bash +$ ls /path/to/eotsd/home/ + ├── eotsd.conf # Eotsd-specific configuration file. + ├── logs # Eotsd logs +``` + +If the `--home` flag is not specified, then the default home location will +be used. For different operating systems, those are: + +- **MacOS** `~/Library/Application Support/Eotsd` +- **Linux** `~/.Eotsd` +- **Windows** `C:\Users\\AppData\Local\Eotsd` + +Below are some of the important parameters in the `eotsd.conf` file. + +```bash +# Default address to listen for RPC connections +RpcListener = localhost:15813 + +# Type of keyring to use, +# supported backends - (os|file|kwallet|pass|test|memory) +# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring +KeyringBackend = file + +# Possible database to choose as backend +Backend = bbolt + +# Path to the database +Path = bbolt-eots.db + +# Name of the database +Name = default +``` + +To see the complete list of configuration options, check the `eotsd.conf` file. + +## 3. Starting the EOTS Daemon + +You can start the EOTS daemon using the following command: + +```bash +$ eotsd --home /path/to/eotsd/home +``` + +This will start the rpc server at the address specified in the configuration under +the `RpcListener` field. It can also be overridden with custom address using +the `--rpclistener` flag. + +```bash +$ eotsd --rpclistener 'localhost:8081' + +time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" +time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager 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. + +**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. diff --git a/docs/eotsd/eotsd-config.md b/docs/eotsd/eotsd-config.md deleted file mode 100644 index 497ab9f3..00000000 --- a/docs/eotsd/eotsd-config.md +++ /dev/null @@ -1,56 +0,0 @@ -## EOTS daemon (`eotsd`) configuration: - -The `eotsd` tool serves as a control plane for the EOTS Daemon. Below, -instructions are provided for configuring the `eotsd` daemon. - -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/ -``` - -After initialization, the home directory will have the following structure - -```bash -$ ls /path/to/eotsd-home/ - ├── eotsd.conf # Eotsd-specific configuration file. - ├── logs # Eotsd logs -``` - -If the `--home` flag is not specified, then the default home location will -be used. For different operating systems, those are: - -- **MacOS** `~/Library/Application Support/Eotsd` -- **Linux** `~/.Eotsd` -- **Windows** `C:\Users\\AppData\Local\Eotsd` - -Below are some of the important parameters in the `eotsd.conf` file. - -```bash -# Path to EOTSD configuration file -ConfigFile = /Users//Library/Application Support/Eotsd/eotsd.conf - -# Default address to listen for RPC connections -RpcListener = localhost:15813 - -# Directory to store EOTS manager keys -KeyDirectory = /Users//Library/Application Support/Eotsd/data - -# Type of keyring to use, -# supported backends - (os|file|kwallet|pass|test|memory) -# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring -KeyringBackend = file - -# Possible database to choose as backend -Backend = bbolt - -# Path to the database -Path = bbolt-eots.db - -# Name of the database -Name = default -``` - -To see the complete list of configuration options, check the `eotsd.conf` file. diff --git a/docs/eotsd/eotsd-startup-guide.md b/docs/eotsd/eotsd-startup-guide.md deleted file mode 100644 index a8144754..00000000 --- a/docs/eotsd/eotsd-startup-guide.md +++ /dev/null @@ -1,38 +0,0 @@ -## Prerequisites - -1. **Install Binaries:** - Follow the instructions in - the [installation section](../../README.md#2-installation) to install the required - binaries. - -2. **EOTS Daemon Configuration:** - Follow the instructions in the [EOTS Daemon Configuration](eotsd-config.md) guide - to configure the EOTS daemon. - -## Starting the EOTS Daemon - -You can start the EOTS daemon using the following command: - -```bash -$ eotsd --home /path/to/eotsd/home -``` - -This will start the rpc server at the address specified in the configuration under -the `RpcListener` field. It can also be overridden with custom address using -the `--rpclistener` flag. - -```bash -$ eotsd --rpclistener 'localhost:8081' - -time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" -time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager 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. - -**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 `vald.conf` to reference the address of the machine -where `eotsd` is running. diff --git a/docs/finality-provider.md b/docs/finality-provider.md new file mode 100644 index 00000000..8a12a13b --- /dev/null +++ b/docs/finality-provider.md @@ -0,0 +1,173 @@ +# Finality Provider + +## 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. + +## 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. + +```bash +$ fpd init --home /path/to/fpd/home/ +``` + +After initialization, the home directory will have the following structure + +```bash +$ ls /path/to/fpd/home/ + ├── fpd.conf # Fpd-specific configuration file. + ├── logs # Fpd logs +``` + +If the `--home` flag is not specified, then the default home directory +will be used. For different operating systems, those are: + +- **MacOS** `~/Library/Application Support/Fpd` +- **Linux** `~/.Fpd` +- **Windows** `C:\Users\\AppData\Local\Fpd` + +Below are some important parameters of the `fpd.conf` file. + +**Note**: +The finality provider daemon requires the existence of a keyring that contains +an account with Babylon token funds to pay for transactions. +The configuration below requires to point to the path where this keyring is stored +and specify the account name under the `KeyDirectory` and `Key` config values respectively. + +```bash +# Address of the EOTS Daemon +EOTSManagerAddress = 127.0.0.1:15813 + +# Babylon specific parameters + +# Babylon chain ID +ChainID = chain-test + +# Babylon node RPC endpoint +RPCAddr = http://localhost:26657 + +# Babylon node gRPC endpoint +GRPCAddr = https://localhost:9090 + +# Name of the key in the keyring to use for signing transactions +Key = + +# Type of keyring to use, +# supported backends - (os|file|kwallet|pass|test|memory) +# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring +KeyringBackend = test + +# Directory where keys will be retrieved from and stored +KeyDirectory = /path/to/fpd/home +``` + +To see the complete list of configuration options, check the `fpd.conf` file. + +## 3. Starting the Finality Provider Daemon + +You can start the finality provider daemon using the following command: + +```bash +$ fpd --home /path/to/fpd/home +``` + +This will start the RPC server at the address specified in the configuration under +the `RawRPCListeners` field. A custom address can also be specified using +the `--rpclisten` flag. + +```bash +$ fpd --rpclisten 'localhost:8082' + +time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" +time="2023-11-26T16:37:00-05:00" level=info msg="Starting Finality Provider App" +time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" +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 on 127.0.0.1:8082" +time="2023-11-26T16:37:00-05:00" level=info msg="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. + +## 4. Create and Register a Finality Provider + +A finality provider named `my-finality-provider` can be created in the internal +storage ([bolt db](https://github.com/etcd-io/bbolt)) +through the `fpcli create-finality-provider` command. +This finality provider is associated with a BTC public key which +serves as its unique identifier and +a Babylon account to which staking rewards will be directed. + +```bash +$ fpcli create-finality-provider --key-name my-finality-provider \ + --chain-id chain-test --passphrase mypassphrase +{ + "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" +} +``` + +The finality provider can be registered with Babylon through +the `register-finality-provider` command. +The output contains the hash of the Babylon +finality provider registration transaction. + +```bash +$ fpcli register-finality-provider \ + --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba +{ + "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" +} +``` + +To verify that your finality provider has been created, +we can check the finality providers that are managed by the daemon and their status. +These can be listed through the `fpcli list-finality-providers` command. +The `status` field can receive the following values: + +- `1`: The finality provider is active and has received no delegations yet +- `2`: The finality provider is active and has staked BTC tokens +- `3`: The finality provider is inactive (i.e. had staked BTC tokens in the past but not + anymore OR has been slashed) + +The `last_committed_height` field is the Babylon height up to which the finality provider +has committed EOTS randomness + +```bash +$ fpcli list-finality-providers +{ + "finality-providers": [ + ... + { + "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", + "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", + "last_committed_height": 265, + "status": 1 + } + ] +} +``` diff --git a/docs/finality-toolset.png b/docs/finality-toolset.png new file mode 100644 index 0000000000000000000000000000000000000000..c165ba2159ecc3fdfd42f7e6f520147c0090e05c GIT binary patch literal 75814 zcmbq*byU?`*X|~ikl2)Tt8__shbSm1A|2A5(ny1pA|e7xml7%hBArSLh|-93i*((& z;e2m=pZ9xdzc?rLN9ucte@ahslf zk3v>`l(5u5Omv51lO~ zSu`!(oIG63Ezh2Sy6K;X$h%sax?5UEUFW^d&&78g{*mDMUw=Zq|OKbs<4f zJ^?;qQ9%*jf8B8Q$N#=w+sVV+8nqRve=qRg-<@46!Gn^nz0J8$&OZDjm47|>Tx91L z{)bxr-&JK{{x3B-d$`)4nSg~kkEOk(gQcT8N=bbGD9OTH%-zP_-tylnlC^jLZxw;< ziP@VvT1m2ab6HqEF!iu^XOU8}aWu8Jaev65>}u+4ZDVe%d#^{~vn<*Z9{aQMP#Ia40MEHg*0FD}>9$&aB7DRoltQUP|87(bH6d=YM|< zPH?7*{}T84SKwUWW<39LM)>eAceZo{A9e+2-ThU17lB|v+)$9!_D)+Ff2gNzd5E>K z?)Kn^0#d+*%|*6l(Ah>yUJb3A(^|_|@lYcDaYHqgxBmRJ=~g`<~En+TUC<0?<&2^oRdVXpv|MH zip}`Ci2bjRB)4(hHBM6u^4CLkGIy1x?j$GS}ti#XI5hH`GvV>>}BXbNlbM1bFZ;4wBTY+l8EyLL!I6` zQoG@|&C|@v?CJF*U$NLqN=g<+YlPdz0_oc(0;NCK)^=qQoZl#j7k*7ax1cE6!$x{K z`;@!o_Ddn16hku;11od>@H;tvLf^WYF*HsO$g@}!GVk`%;i;dCg$i4qB#V8)U2J8n zmRc(#PEprWh*UASs7NSYA-09*!%daz`ezNj{GjTLT#nK6| zPCJ^8XWE!|f8TJ^`kq5%^XU%{LRqH7Cb@UGLpmI_brd~4Kh}0S>!YEe^;rw- za5q1w@+Ba`Go)&5y-FdzDSLF($)m&BZ1ef+e1=ag9inVy)M<0INXMIRP4rgaFPt86 zn=E(R7qvH?^^5F}P8}IOjqI&69BS-~-)4H*MS2Atae|wQ-EegKB&I|d(|qgu+rH&( zvP!HHEJlPPD^gCTxL>Y#NG`iSrTzmImq0YSA~v>mnvUkYRTFZ@pw5r7v^Fu4?$}YT zr`-IA@Y0zUG`PwKLer9qidfm$8bjix!ndW5wdY^Ae2`E=Alq_zi;7ak#XoTCfB3uI zD)?5vadecrJM|%gm-7NUC#T#=m|vRYp)fZoDTTNk-k0hu)&$Meb;E(L7S$XcVzhCu zM1lh_RW3NxbTKB2 zbz{8`O?YQDL`oPl`+jA~!nbPvkqU>Hxr_{*9%Ujq8Emw4^@y$cEtjJf91Gf>wskB5 zM)O{}m7kU5^F8TU2-Y^M)Z~#t)+xR`uIHWHGu=PmZ+7mu`~5xfty&wgv)goxI`=RV zc@kGKOH0eW$zNAfPR6=$-EJ1eFm%ygZR5sQ)R>x^3tz7BXx`Z19iyiVUXzubTkgc7 znKjlTd#f8`S7H;U`&K{e_PWW|_H!QNwmGi*o2y@+{dng<9XCf)jQp%U8q8Gco&h%A zegC7`o*|Lm$GuAi^rS6}7Ce9}M7NP1y)WY2Wv zn9!tcU|?!>R>yK!dA}^@TG6M8p&_znNBT!)rt)Zr7l%7DlTlH7mWQ4OpS{0q7_gzu z+)7&dbQ>Jf<`0)XhkCYtjqc+}tU`UIYO@6T)9QeI|mBu@49$k?7r$lA8Z(!m#sOsOy)S$JXW2C2*9I+~B_)~sc{)($aJZv-|M=vo&F3g2dPYV@%Hht-z4fDq zRe3rbqont5=e=NO#JFhEOgL%Yb-b&CeXHoJdI{#0@TWX=2UN*{HCZFC$j&?{@jZxH z?MYEl%9bo~a^Tim(}0MIm@rceDn$(>DMh4lfPQ?$HTBO$&4#7dAl+=<_!hBeVMHu3 zHjYLy@hW##tl=5sJHCO8rV0PUpDuD|a=?V8Djb&uND@yxod4Q4%wED5!PG|Zbo3%# zL+O2?Y_0aVk6a&vUp&g_-<=4V^vr2)9cuk-(5~-uC0F5vdPG0THM#tOp9T8o0k&Awb&6zUSpPGoBpJem4cStWd93MF|EfaeC3JPN> zBx9TI?Wc?RQ!!>vf8L(ARmoLqv5nsVsgzc#;k3s2)) zSBwgrU-rdz= zO2ogxw%No{YIe8HX^xUs$A5t*(C_Q-FW$3Z^V4&4-=`{4GMIA}j3y{)#9e6exBlF5 z-XvzYYG7bEHQI#baHO9tA3?BT)1TF}Oy!!Py8Qj^rvDPI!ehD+`9KRD>TpO>NAqth zU53+{iAX6H65bo0?I&^xB^n$})uVt72C3u8EZp{!8`#Y*iW<)C8_rkiPHaOipy$n# zkv})Nt90?B<7l|C*J{(m@nNFZ+?!TIo17$PHxI@3xRa{#+w`G$G?CPY+lsr6<6Sqy zsIuBVI*d$p_DZ)G9Ih#^eR(=`k)^1}tSc0&+(Dj7LQ-=1*zZgNOv=rDp{baRm~F?# z0@2aYZ^F^?3|$YlS3`174?oLhaOH-o=Qp2VV3q$aF5Reay?IAZ51Z|(0F~P8Rgt#U z*zQ1d)>=QxpAqp4pkU5>A8F*UF)v*F)gO_~=ep-?Fk0tdYxNeJ5!si^f0-pPI&pU_ z;@2;;hAM@^=$OnR_7gE5(wJnwsP=1;U5+H@N)b!5kt4XRqvN+fbp1DtxRJwdXqNTV z@^Xmaq~AEhmKXr6oznnB^Lli{>oRA*zms8e4K40<-`svnpK$I<-5O`jt7htLsSldE zf57bdfTky{V(hIZwZHFf+vjSxZhpfeixCeMRf)r+OCpIcJNK`h+5K;KiqwQ=4i1jy zr@a!FYK@#8DjS+V4^3h}+5OV)?BVhD?tCa@NG`6{SPc2Tzy)3liwANP@xt0wCZC>z zjON*5`g4_eKJR_CYunY>wZdj}c4{$y#5yfC_&iL$b1`m-&33+7Qb! z3yY$6=er}+^Z9AY{!UMd=y}XN*25#f30BH39N4-QVmRr&OzVz~*Yrv`Uap}}!))^> ze#76BIsZR6pDygSL6q9YRR@dsG zh+O^*+KfHyt@U0DBVXP&xO?~R%Gd$FfuSKDRuQ)Ut;+9h0{^nl#t7p|-^x?5oVUHz!*?ZW_<+l_UXFK)EHnbkc1aue} zJK!+()ftM9`RF%vFH4SP*wv6zQlBVaWJ#pIFO_u87 zh<;Q~I2M23sjg5xofyn~bcdFLjwp(Rh3WxAQ6YhwXa#5Ihg;U&yV538eRq;{h92?c>nONz=-6cp{1)e(iVJw}26o3A3st!asS_rNpK6 z0>$dRcXY_==_Mi$+hUbnTwG#3ONrzVaw#)djCjr3WQxH^bZ%~aYe6bN@(A?kEE%G3 zx2&;cTm8vk`G~&x?`T7gmG<39U*aiG9~6$ZY*>x7sex6!9pFEY3N-kDMpPhRF3!Yv zV;B|_T)F~=Ll>|i`(bmdc$+^biItnXjg}}8euZnl#Uh>!p*9skkdu>taF~gRnrUO4 zeINGYaM_ba(i@>nNGr2bcgueA1De~U4@t9pL}T^~tk65Jlc+WCJ7`590X%ky`(E~% z@Crw=cmO<7qqsUvII5PScBWdDN?WY3)2Qg>X>Y<@d$mT3c1cI$LUb-v^izVlpT zqGp(42Zzm_otKP^jI4*=UHyc0Vfyr%!gMju<>`gsNf+y0$D_$mR%-!VQboQv%JM%Z z<|>-Hy5W*9d{KdVkgYF4^Vg;_Js(eNx##%lWuC%;-lu2c>*(KjN+?Rhh*@_-Ev%?0 zS)3y$G>esj^g0sCm*E3SfZWaNaSe-~CARqAc(|y{Z0Ucn4laG3Gu2U7n?fN-_g4R7 zsBWqakSELZu7nH#&d8H7Y-hnL;pSh-l`{3u0e76QI6<)JIN|- z)u?T0hlZW>n#YFJ-;H>>b_4esqfqL@Bg7Ajh)_<)%43gyBoq+fJzZ^8zMa2~y*AXT z{h}hPyEL7MJYFk*%eGd#y}22Kr0uwKgXU7jO*ROt6Sq^_uZo>J%x{#^+@|^%SEQXA zenog{=@Iqil9bf!jOa%IP=3`OdLv#Yb=`^04~azIu>X!nUwcaTp#DYV<%x+3pJYKf z?6JQ0EZqt z$9aqp1U^4>>k16yrt=q}g5vS=q}Tp#z5D)f$B*~UT(NIEY39Iz#iPa-Dg zHjn{Fl>e-F7FV;BZrZJ*N7@#D_(006j92Lsi$s5#by}*6aWgkb#PdjG!uv3Ni8~bY zb-(pSbCEXY?$Xed=@)4n#*Ll86O6lWF9k?@7mUo`U@Ldu7ly*s>+LHtNf-17Ev@%U zF38+_K~NJo8X{YX|7QF69PQFv0GAc%mEN_l7*6qgSBTGuDYY+9of>0e@RoU_A8S4P zZaiHD;jLSp#-Rm`8BJuz^Fw!Sci-qg(PXliLM#tAASt-?KVvdtU>R&ToQHu9qbiAr z)SOR#2|VoVa;~b;+m=G#kQ8G+ooW>R>ym=0{FI&bvfU-qe;Xd^qX(|;0(t3{eDl<8GG;Nmu@GOs0K$=k<7Pz{*-? zsBvyoLT!Da*fRI-Q3i}xP|HQK3sVSj>1^8cqvMp;>K_N))4}5Wd`ZO@gO%gDXK6vW zI&p`qF?;CZ`uqvH6z+wcx7I&|@7@H2vb$ti@U!U;jh3)FfTNF`vFE`f50ck_mJS&d zRMTBQ-(Rj|P1Xc+J*k{PhxocIoJ6cgfkt!Ck9?wHgRR8b!^IbVt<5gcPukf;t#(4o zA2^rQp|K;cn~;zY!gq$WGPfeL% zVqwipHHPePM?`jH!VA#L#Ak$?@d#VxR9_<|CX6Vqv$h<3OM7yu;W?q~Qf#B@TX{nB z;V5Lo?t9z)k?@(dwKz|QBL>dgYi-Td`RYGQSedZ?ESJ`28P^9aOw@{du1`3uyGC~0 zP+{9VSS~eR=*#?3)vW0cWZ+SRLNK|w`DB5re!X^WU`#~$=% z#G+wbWMF2-h#;VCQl|H}Sbq}Pfs-cbdwF_#+IungIlFu7<;#~x%GsHi+S^ffa1!>2 zy%~)}N2mYGWc>lPgBm&mUZ%3)^Y1F=m0xD%n(ax%Ir}wq$W})yg_E`R_wy)u$Z=Ol zmXLx<`}_MA}q`}S?c5SK{fsrl^ioI+1_K|#TY z^Dkh&DgvH*X5H z)u!6ri5T}(M@agVJ7cY04SEtrd zu%MQbk^=bofFcz+l<;gw{NlH-C1M^7XxOzSvg`M#*-419Y#qiwk!j_tSNO!*P%vv~ zWm#k9`MJacx#a`p^$vG%WWg76SguTVzn-Bw6i6;EQL~pq5eAaWQb!ek@bN4E*#EpE z{6=u7$*Ef{v_LjNVX)<)xA%`4OeR;e%*;&h)r#SbKb<`H4RE~&)Pzk33p9jE9xp7p zy1Bjg!uhQLYeU=Ea4z*ExPhu*##+d&UAS6WpN5w__3^UBo*JnOKl~w*4p3lhe{0CV zJliaisyyKMU^?AvqOt1*KNojz^>jG(54l@vaiP&}KdjcTr)6ZZrU=?y4kw_E#-j5^ zi(co{OXx_Zx^nEU?{wNcN2*Ja{Q`}4yhJ>6Ey8ROSLe=7F(5s0z zlSsV=Uh)g*RVO_M;{|cx>QPVg@h0_BwzF8#0cDIYI{ssb-XjmMet}9Yzn20 z?7JS`2gQ8A6F!!clPmLDH+oDjO}9K;TI$?0vKFMEpe^YrdJFUQv(jx#C|+p}W(b#s ziO{RIiDZ^a{fx=wWMt4j;h~TGE$gJBV8nEFb;Xl?(#m_|wWXl6Fq4(bOsp^yKR*dX zoM%0oV9-D1P?hLRy!5Y%VWZ-Wb=n?DMy4Wql*fL;^1v|3xS|;a4hS6eyLW{5C#41} znUMlbeI862hYj+P9ER-8zwCBLF1qjku{`qlThO|C39T8cQOM!QUXM&;W^QICWN=XX zGZ=2T=nW-(u9sp_9YUc@w@n->IfM_)gB)Ul>}VitK8n|}WV=p2rR z8?0MgK|zd75uRP5Uz>NJ>l@3#yTvf|{qr0xOWqr$enfC{P=~1JcgbB9z*k`=PFM@`Qj0~9wWWuSziTOz7-F}Lb&&QM|-@L-tR~M|~OjB}mb5-(? zh0OBjrLS!h*gPdZ{bgJoowq%l5W4s?0_&PSKVrv0^RC3m7(pWv#cHad?IO_%HPd^9 zVLEnA8N>Y(zV{K!RNN_o>X5+xsphYIwU=+|lm~7XgjH5LM4w?Irgs?X`OJ?PSt;C3 z{k?tH3>Mr!v4@Z}_tX%xsQ)&bXn(~p*RNb;Tr{(WkC%E8&l_*gjleI#w{Jw&HaVhf!!ZThCZPgMo`T?OA0JmY>Q>!M8nJM zD;&sA^#6^GXztA|YNLh{wa)*rp}D#F-v|Z;wLom&t)eL)m<)3Ev08o2jyE$Lxjkf* zuOUEj-4AnTZ4Awcr!-Zv{hOfR8x7T{Cr^l%@6$ccX2l&FAGdQ~eWr;C3_`<(7j|*4 zkMo#_3Y*Iz4vFDSBc0o+=msQcE9WNG7Ww^*D2=%#X6n zszPI9iUg7kE*avOaL?Gs;b+EJrs2rbxjTaqgs&VKU-kG5u4Mnfa9b(er* zqCSh&dw<`%McwzEZf1BAu`#zXL97yx4R>b+= zFq|>BE!~mRzx#M2L?4S%Q`Jx8&~TwUI4XAyi35hY(j39(Y|YAT_z6=-XZi4ZQBDy% z0gV{u>FZ?;O--|HNqKDWmA^|rF>XuqReaBEt9F~;a9C0;C<;@jYc?UT^7VdA`FswE z!YUdhkXdQeJAzI&wm12@MiK1(FCIOT^xYluW{Uy3ay;Y_60op-tL%VvK%NftIENo4?LiJcx;$SCc&=xycy4Shd&-?8e66 z`(D$94)M*KK4RKBT)Ri?YmAtfc>FqIUQ40mGY`Itl_hGLEq`=h8GDANqf;DEyD7@$ zfB#orz_Cd0IoF*k0R)6|C=#1qh?L9Uzu54Rrl#hjZEB%GF$LgD8*6=j&Cbt2lh4+_ zE-G=6a-W=gs+!!WW!vAW1v*i%Jf=OHK7%Kw^1v zLh!Mjhtrw9n3P*HF@GmWNJwl1l4SGlVsz5~y?`gHG$>EVyzA`wwsP`95Q{lo`?U0_ z!k;Xj$Fv;i-#^_Cil)6P?J)A#L)w8iaD8p=qOmbOE7gVEtGOaxClcC2&i?y|f@?RU z@oq*uc8SCMUb;_UDCSYL|B_?(4H)6CL;B%+4^vDpnW;?W&d*d2@t)yp(F>knI|suU zgelEo?9z4Agvrkq6As2x#d;}Tq^AV6)4#C56SO6|jNPo;n715;WM$)OEgX2*(Jcw$ zp+qMcc&MWjd(*|%Gf>MpbI7`E>p2%TF5Vlh1ZcTtM5db_SA4q@_)4mlhyvNraIT#+ zbQDcg!F(WolKHjUyx3}T_V9AKZMQy+2o#}fL~K_xy!~85 z){y4~&|nIxn$Km$HF~+7^{~%QhkjS>re1VROyXWojYmMTZgK0IsuwA{6Euh*rRvxQnp@X3eeh zQpg5Hvwg3)Nj~N}pr-pt4NqA|rqo=XBNPzh*qqa71w8b zA=t%S>3!!vI>ZGXdasUFG`~(5#iL(%E072fFk4jA`^p2`SkL_O7E&7E;i-1)C&L*- z;VNn{d`&O43(_nPY%LRL0}AW*?es_E_4bXl)6-;21zc=bUE^q*BO_H*bachN zb#-)(pw?gdjQLMhud%6x6vQb`_79uO$SWaSZoVaaa>Q@sb3BRvXYBji`{uLnN;l>k zk13=*@w9cql8E(VFAfRRX)}C1E@Z_OpyJBG{9K#LY|~?()^UQtBS}yAR(F(PoX%@p znhGurDiib8EgoXBU$`?S#hNqGd*#eoT?O#e3T^<`m$EsiHP=}B{m})0V)0VZjX*$J11v%;(YZHl_-Q0>F(9_IFI_JtNHT8+|&lIwh+but^SRai6 z8DhwUc=#MmW_*&F#gE)*T=4>QA#L^I zESn{2ndRdMLdLw(ogRCcOP@me_uXUJNm4}8vuCD1IyCk?hSz+$MGB*{Sb?9WM8`l! zBKukoD&%CcHJq2bg=a=~Rx??@>fqdZPQ<;$pjyVfnKM{$`~}z4MeQv;mkC^QNkDF!VNtoM?uo4-%~u zX=8__E_;rvyLYdOl#{bvg;|Y_jTx;nlj;1S`i837^5Wu4Qt8t4P^aCkS2;6*ETzY= zLQy&F&!;`&8|%*LF1k_A;z)3|zNHmJ(6zl>?Egb8(|k^d9@frv@H0{!oGt-CU%!!Ny{4V*+AwO$ufrs0JV)Ev&D zsk-vBhP>AC(*@;|gZB^Co2zE}IyRiUqGM_f6wm1>Q3UiFuK?Xw;&6Xuv>HR7{5e$* zE)m%2k7tR&CAE*rXP-OVt?dc7SW0=gvro>;^o!1*%DEAlGB{Oxi4l3-86ovzmr?vY zWJNwkN$hH9P+$bX9^>|XD35hRrdq0sA18H)yImy8Zl5Y=$)8@C3^YDATb5M?9ei|{ z3{L2C_B&d%g3*WSZ-(ZDoo#ztNV%!xmrinj+ApDqNNOFmGmQ-H@d;#JQ^O8MHJD?h zPw^%uCIlzal~i$bp6UG=y8f4z7YRMz_)8Zq%mrnYCulMqb`VMIvF;M(+?kWT!P#=Y5hF~$z4up|CdYbB<0qAF14$a7KTX4+% zK6af^IXW=wsn45!0IM$A9yeVfOx)+x;GlP~Jq*d4gM2~nhT3C!<1i%l!Z*s|`eP~p z4Gx;Z=P{Pq6dLm8&K(YWQXrX!4-J3DRb5PH(M(NVNo$plZ+-2yOP6wdf`#H^%9&e* z(4xE0#y~@1z{z278f8P%_<5bUadG7J3s3s*Fp&-+Ywh^8B?+gVaBf7sn{$cvI z;z8g48r@niwi`wqc}++FVR^6k@GPbgiE;og{9s^UfZQ(St15SLlGyHY`|;7d{n=AF zy@{eq+*3RO+)I}dpQXpXSy{1dCcps)HJ@D)yhEDX=(zyX59_-YT{9`7%$HF;5x<@D zeplktnOh{TKI7;Zn?QK243(D$@gKOLg|Z&zVq<%eYa0FBqseqwp@2V z>h$xU>z`{sQ>2_PYzPI3e4@?v+NXZzziL~1D?I~qXRn7o$xvYB3we^+CIKV~&d+Db zczGh=dGwi5c+xxjIQpM%s0kE~k3*4FbE$R-2Sb`Pl7GcVD(o)7*jvBtV_KS69vQxF zEeWF_y(2e#A#RoOPX25vKQxDh_6e})}o`p+nmzYCHx@dCgk% zCR8}1&W+ku1T*sAXypfMbk;*fSAC2ECFLNa zPbG{xk5>$*zA~)K4wc2(_x|wC3rD?EamH+&IC4c5yD<>!XQFQNX&B2l+x=d&pWz9! zfre@d_)0oD1x2{fi9f0dJ!;RQMHNt6TDOd;V#9;6&$O<=+|YLp<$xE*9eWCcB56(Z zfk(ly)WTVB-gHgmqAW8pWJ->giOJSAC+P=JqX8%TR`wI0DWy-3_rNZyXKU-Vnfu{imUgI7> zi(`<6;g2XN^gzdph)58Jjg2iu;-PEBa4aQ%+r=SdV)pVtK4Bc4Brd|)#YGmVUm_$j z2+H->H=lE3d7t+Gn+hQ)kv=42}d>B&i{R4b4_l2MzKYrlW zD_&zd$TzC>xhF9{J9`0o|BvY;sVc`@WAKaN?)yOh!rj39V20ySYR-zXT|FC6b(`yw zm61UJ1sd}AulxOE6$OGOeQVdvUy68i5-H*?&^SOl6LL=1OJPE}NZfX)nzo1Ta&S)e zFK_F8w5Pm?M-c?w0F$5Zz{0jaazBrxDx`L-YWyV%eVEUiZPb0XqI3z71%>A;P>rXP zMAFh4PX8#-$lmyNlV`dwQ(i?)?d@RflZ=cwkjHDg;gS@7tGL$H=%|i|e^-7E{HlKU z?m8a5R9d>Nf`Yn?idOw~6#e1y=l2avOw5#sy1d+6(;sD~WF=oZIvQ4fzAtxQ)C8l@ z5t(0IjlJ>o+H_%lh8!rF4j? zU+3?;wJR$t`=icZ9QqPdGcyQb8~Q9GBq{r`0|C1{-%nGjDbPg+s-RYS;c1_l6c|!T*e3c zpTtjDZnr(XEp;z5>{Vo%vbs7!Q&SVWdp=+RMn=ZQI33W3{Fysw$BvB|_-!;|>6MwF z^}Lcco=%I2xzrX%8}s9b-rv>HVRbU%#M!H4-#epD?SB^sTz1F3wwj3(Nxt;|>gc_>C2;oi5HuqrmxA4HM|R{u#~Ix9ZP^7E zYim|e{Pg0YP5W1fO(l>KAT%IQ6g;$u+#}=SlvGut_w`Osj>|n)_4oGnexOE_i!P!3 zLIEFoPS`h-IUCbN-O50Zs`H||p#_UiHO-a=3sa;6>-P1Woq3^L#FCbl7S{y_tN=t3 z3AV659YN1))kAZ%(MCl71_f{$(}LD8P=Oh^|fdY-zy zM&=Br5wN#5Wp{>o$M#%R4^?`xncVRoASi#hk5z#O( zKvGy(h>ee5fqJL~&e;}}f>2MB_wf-^ild1-I`TsVy?jZX%xxGAT0485&RLurjC4i` z;8Ts`rF#TpYlggLQPI+%{k?Z{Y z-R-}A{YpqkFljG}jO++S8D?V0^cYE2-c@O7dS>M~1s|VJ`+B!-;XQfsr0OUxvZLqB zazt5CYZ3!kM?^^(_2GlSR(U}IE4aIS@z4m$aOR;N13SYh_%im?cda_&rWf?WV8r4v zt@vdS*qnJ{VxrzBceb&yu@yZ^qQtE;Ee?jROxDvwxNd9;yTp+`^NlvE?KWh5F)=Dg zVsqxuq=P6L20dt$Q@E<1$tRV;&h0j$`CB^p-k8U*p}{Bl!44HRK942su2<5Nes92F zQFpz1_3G>{=re+cq?RqsWw@`7kPYPDo=)cA}f>NsoE+=8fvS{zv<$b~<0Y+Y+0Y^BG7%rl_bW=%fkeYC19qg_<&4XX33Z1`>TUeN!-fsi# zGN)b;OxfKPa~gT){VnIl*iKSM9K-=W&lSC-CfI<@+3T;J zy}HeM}=t46W|7*#7&sg@U5u&$InTp!Q32PkVgq zDYUg1goG|PM-W!Zdnoj9KnoH2?H!$+7zk{}grua#b*B1)Hk22*fTzjo>FI?9(#`za z2T}>nw_u0TkoW&3f_qLYC~UW!p}eIq@VFJ8|8x{>ZPL2EUzfyn6%~H(oq38z$kZ4K z(;*y8Xz|}2j{q>(@AsG%M!dHHLW3Prk%ImFylrE{hDsmM!TjHz)PDZ55?t`OcZASh zSy-^n$;nCipUA)R2g3B#vsJqfL4Zwkxbbh>=M)ei1$W!{`}YGXJH(yYGSN>w)H}Z) z?Qfx+B<19JJ-7(Uj{N-mRt&%!&7tiNVPB{ng!%F5lP8bhoiH_wkok`&kFpnFAW-&F zQ@A+xw5m!3+-V3jEr<`Vq!9PyRK0l<4e=jQ9v-bRa~2pPsV;!iLaW-)YaC@Gc$C*$ zAZLnxgixZOq?A=whD1#L+m(8rf%1&bm8VhYxOSsH;F#C{z#SD$fK&1;Na%3M&CfUg z-I3VQ+lytQhgCQIQB0Fd#xw0m&t&r$+&8UIYTB=2dRokhQSLIlIf? z?5@OSP<>YT)2B~Ez!=?Fp6eDXLP`gWwPNtXA9{w<8`I5#pLY6{>BErdfk&HI(5S|S zLC_B7c!OD7j?r>+tboH+VZhV)m6HMDh$*NF^xj$EAf_^W*QOnBD0t*lc%h*f2*IIB zCu2_i57;47GhH~rNT#mdSmbL-aQ z+RpbcAqeSIUnyfp9T5piL9(3AEB3`chlGVVa08ilCqm2U%ZZm9(ViSu;R zg_hRVpEVLSpI{aONla|E4W|R_wbh!%oTm^0r^jCI3w>xPNMGB@Xgdf)XW%3>bf|6I zhKvi5Cowtsfz)Mk@`%t-OmSUHddLiWtCf?y)_n{hiNOUyz-v{`)99f{>w&y(oszP5 zf_C3cn#1v{7V}>6LgYgPL6h(WzZFCw{feSK50tGO?ajn54CKcT@U$}(#hEK*qog_u zbK*oqsN&5GwKZN-xiCU(MMXtaDtPqh5t5Sfo@JTb?=Fa<xFIGaBqV$gDmT2| z3~g;}$c%n;up>=TVRQJyKV&UnJ^GPr;wOS z!yu4A0A3X;ZT`OW&Bpcbg2o%Ya`cIb3Gao>h^}^W9;3&AR)58bugL%kE_0n#wXm|1 zhYl}{{)50k(Wl^rLBM2qHy4MGodslLgH_q z{Kn2s8y3AELPrM*%b-V((BY`UYsgrLAjk1fjl;v_FvFt^wS`NsJIAscIzq3QO)#9pSHm7 z?osmRl~%oU2$ZJn;82Bf%bBIQ;zB~x7RSNCA-mWJl_Vo4CmtkX&o^H^PxfXAIq$t| z`86C(#$oGM`ua74n+ZCFn2(%1oaF+g7dtz^(d%R}Tt40_-E{fT!q z?>*G@s`GGKBLOB;pt=zy^hA{xi35wHl{}#AP~l0x_us}~Fs>X7^^HOGH;G+~u__nn zA$XRgcI*HK?aNZUbSqtqOj9)n;&?{_qh6(>VHn|GwM2kztq+-lO!w>@*0yiwWtLyK zaG}b5kr>27fS}+rQ^>VbtJxwYBSR~o`5=%3gNP_k0YK3DD)1x1!DV7vR%!d2&AG<~oc;I;X7#oO0+wA_qoG$tx4 zxUy3C9CjrDUQb9szA>(!uq~Kc0KwQwV1E=_TU&b;_l(dG@&bDr2P&@_n<`vKyr zZdtgC8HNn%kO5@@^&vTo_CX2l8`jtIK>%jHr0%ZnE5zbIpFfitKRA&40uro;qZ@Y* zCLod2)G;u>WC8>RSbsq}`_*^x0Jk}f>u4Mu9T9k)@)z-`+;yHui4;G6jQ1HvgaBod z^khiJ0I6fr_gc1Uxuk~IZ_oMVp!4$EN_5`PD-a_QK}}6^G*W&Pi05+&Zf6CFf&~hJ zf%~JXYdA4V!T$gcLieg3SE2)|(A-`c+SuGgLjbU1xN-#(DqGKzH;dpzdUbxHs6)n# z^5Iiq)xlD`Vzan!DR-i@;%XK5Fn8Z)Qj?MC=}5#FgVgC zKRQq=#nZ)>7}l5pp9MLwOeh@k2MSR#IRZVw8}F4-s>k%}8o z1BQ5Pr-WC{&CcG#Q$N^V#sazmSOFRd?}VFf9X994s0a;E+b1TVD1hC2FRH-#Z?0ti zE6vN|VvdW1ba)69b^sC$JjnTI&&BU#e}3WTd#ex$76t|c97zy)_~!~SF>#sqrWp{0 z)lGuH^HT`fQ;jPp4K_9U^d}O5(uG0aNOx*gXNL0x%WOIld{(BI=c!U4SA#0)naUb9oClgA7!w zb5I7VgS2PBlv`ttwEwDyyK_yL)01bM0}|EMLkFQ{xu75iR~&- z6w&)z^DpB8T$oNbg`KlG+V>&UiFmG1kSf}gF@8`$o!K~h0-$`+7+BPmYu8fi3Gwk2 zZEe{BgP>Rxjn%WN2mAobfhL=3l>lo!58Ap40FXDV#(m>#-4_8uOa;hay*bvd({1n^9xD z`@DV?>=nczAZYvKv7FlSy`ui)fCKKG0uGwnI6FaR9L#WS6%8=Vhu@X zZ=iOPz74T3<}z24ao}+nXa@M;)ZWEyAI|$9@t_262G$hC^$`qRiGaKs0ytE*cnBQ< z#03#C@gp!7@w>W#0RaI(Fg8up`q~`@pr*kAzS4-gVgih>`3m)_|G6vLUV#u4515fg zI)Db~6Ck?ZI0pdN4n`|;=MEBO_CQ&R>!@mrYiMXdM5}&?wAa3t>cMF5F^VX%gS9s#OH??b_=tre632Y%A9zyw(SGD5t(SLd_*Pe38 zL_fUKh^DBG42v{-tVPX$7GkcF^|AftN{Y~;!s?ZahZ9%FcQd@#s+X6(NV2$lWm)i! z=P1UiW?4Tbq0k^EiemkhBo~HGbV=dCi{;~x%8a}mnL8h3cCEN{yZDC!5Q$d9C#$qH zxAgT>Uoh7MhW}Q6_;6qH`9c~jwAKiA=)bYGwY>2I2GJd3G_YMxbBNv`<**qQcr^9& zI@;+2yR2UMx4{(s=n5eY4kJ5zG)xd?X%==NGm*Q=&z`kDrsM~3hxjo%`ZOg)#oD?6 zUL$?FNq;H}lV?!Bu>fy4J_9IHtHhwXsmf&r#rDVUfaQTyZ`{6}Ur-Pk9)2+`Ee%!1 zLg-T>iKsi?xewW(u(&w8s*2*$rAw&D{Xx5^7SgTKaCb+?)bB4(p-4`B`EqfxUK+~Y zTQ7yWS&2A8t#7icg`(E)L$v72M27{5H776c*Wx11hg(TdhY)}tK8Ra6p(s)Vl5fN? zOY7dfFDQ%{CtOfkIv>MR$H2%K3|fVVrUrcspV|!I3CzsQI=Z`c;+$-4v&zd8^YX4) z-ZwYT{?qSs-@t%I+;at5WqgqHA!mUs{D5Kh`}2iGTSv!ZIA1oh{fTxeHY2R+uNge9 z)_3<0RH2Dao_u={2=4t5P{Q8vdSK~i5-x??nM1ZXmo8~hHR<2GM?_Ap3{~z6=H*my zmXqcBlS@Hl9J(nq%tr&arNJP%2WkFmMAc`JoCcs|274n#cR_6?T&sHR37O4eI1u3xY&%+QA%1Z=jjn}wly zN|w28l)9qgh2auIj1lhcYCyT&-Q6N0BD}7@JA{TS-oH18GYJS7ImsN@1Ps>K*B2BK zfd%N>;r(P|V=#mobZ6Lyy7Apeme`?M!ZX<*YojvPznmTzpT+>>A|fGahE((HSUH|< zcA-BT2#+!du_$snJw2V0`SNWsXlX(524Rr_`i((A{e120yjSU%{vvxh4JswKjVak& zuN%vlk*2nBZ{NOsg5cv7a2L`pO1Tatc(%ECv$H+aPV@nLnP1G=+1Z1Vzevkr59EAP zKpEUGK1(Yr6tL^)>6vQ?#t4mwpk5ue7J#bY39SE5yYxvSBy4^~c7;yNbl4iD+N*oe zCE(C~vp}Y!aeTOoI$Rh82S_MZ`8m5O!9SCela&tfx($YGJ!*!9{_@$3|K2vjYuDG) zGqJOaNl&NU+1Y_mFf%n31U4ogjtBq4kWq`P(a5YYloPa=UlA654hRpF3WF>1Z*>Ps zjimuRJv>;j}F=j%u?(=FTrEA=tB;e0qA+ zduq|2r3i?Hh=Rg;F0%Eh%3Iy12?-65W}wA+2~l2NuC1+&Bqz5Typ+R2B^@9!TxvWI z8~uFrrxQq1_bLIbJ3cAygLhlXO1FPZ`?|QgqQg*Jtk=ZD{DFBK#>d+$uf)JJ#b%)b z1Msxf$@72sdK0jo(>Cls`z~Y6J`EMJ6bX@~h$LCE6bdP6wIxc6k!*#Lic(Q3MT;fb zS_mnUkQOaOrJ|Hbi~4`=%*^vV@Bet;<9KF{$N1InyWID6o!5Du*L5e1dNX$1xUk5` z5M(KL4RtU$+;l0bm{P%z7L}KNmcap^sM`qOCPQ0!UG0Ta*B$75p$O2Y__!2wzM3#V#SKJ z366d+Tvtpp{-A(*8D>79U%&iGA&47P3kvM+MX-sthd7zT0~PVWHB?npgyYX$!|2uO zD|Zs6*bPS2Qnt)}0K`FnZO6kQ&c6+C&?$QVp2Yfh0@|fjq;=>S5qu+YfKW2J$A(yo z9JLiI`mrFYqW?(Bd*nVinf`%`k&)uXvhz-OdUm+3`{H!D-bSgxjuo%RvD4fg4F=Mx z?X0Y2-+j@FA~z|;wxUooGc(H_d+%k%w@sTi(FH$nlF1_P-lb|YG+QH3+*)nz9^AL0 zjEqcnZf;H9j&za!NnjTvB9L+d;72@seV@!~u9l=Ae?Y9Ztc*@8hfpM%h`=#%%Zm%+ z16tk`Hs44x%(b+%d}E=dsY$1Fe7nRqZ+uGwoQCP>=vJM>cR0@&4(5SZ)~V7BQ?6y z8FhYH7(TamgrT#n=Y*f1t;ZVNJ>8{`?9PTAidK13L$rNEnw*v|@54)mi~q~te=&|E z!@boVF0G8P3moHT*KW#`DX$~fY3a=C0_|r^`w% z+KU!#qP_z#Z?v|yF6pej!^Xy#cgZi^R`PTp+wN5GH1cw4dhu&&x#ZJ|M#5L(JH^_h zzNT11Yd6I>s##KQuFq!wJ&!)-&Dr0Pi|0*-gome^svWy_Z4#|TCG4M1Z(@&k=+<9K zX10!>%0pKFwyj%t7dcJn6*$6+#JJA9@^>;uUIMWg{CCvDqYt6&ExX|UqemS*7tRCy ze9Vd(o<8GicX*$^{rhh(dm;1a`0$qODGt|f+*mp6V}5?VyJH*G9VOk#Bdgb}@m-{R zn(GVFHM?7rDo+I^Joq*5D{U)kYHG4?+sKpQA$5Xl?h|C#CGPG$U_*_XepEwv9X@iT zs{lch(r4@s4wiZS`n9ZKDQwj#Z|^=*QjbZ2Z$5Q0wX!Oya%!2bt*w3c%l&SG9hg3S zdhvkG{JW{C>0($IuA~5}U$~G;Jv~uP5=^C3?UW!XR~lTSgR}b}r9=20-jl3Z;XDr~0^4Xmuj@9!j8xh&>X*jJT?g5ACK^z_6MUU_--y;ot&M~@$`tZ%nM zUq2OfIGxqFm<8Y5+^qV2--;QI==9N7t}OLQGPtwLosBJO&tblYA}(EePwyfG<3tvd z%!ZlP1$TE{Dn^tIYg+rW*xS$)>_k)nP0`9Av6{TPOm*Y)P@UnBllK*gp%JatIpb*YhY#W@NU+&n zSy}U5A4WO-G{;6V+sJ4HN#oO(+obmVVHHU?t>$MD-2^^?=QuGFS)-z2*NTlB|KJ1c z{=lT*o@gAPnf8EAz7&Mx@HPue!*Z{7104@57uS~tY)0H8%PiH?t51yTHZE=*Vp6yD z*LPl?p0Bgxv43q`#!Irnj<<=ztxyLEZKNiN1mt~#1bUBZz^(p_3w_s(441u`Xz|0Sp_Cc_6&*3wl z!Ze44hX?X07WA4ur0FlW_U$a@KTAqX*pz`|>lJPCU=fCYj9H{u zJ8_HOq52OVIu}{i2|r_7LfkTxFyCx~qQxBb1usdgeLg95$ER#X7BGwo^>pt+gK|sk zLQXdnm}-Z<+y=cw<5F>PF+cIPtSkk3qGfjG#5m3Q4mxJ$=Jm9{ihsIDO3IBH6P{K$ zOZxU3wh-xExJ;Ckg|zyRXQ;Vw;r*8{U*^3V$X}V+KCqq-L=kQnfstaZ3q#`Lhk<8; zWTu3yW+Ph{%%HyBygdO>Bsg>8ISo=gDmN%FK%S@LJhh#F3N$u%!Y+JS62PzNHcf=# z-Ho4P#Ts?%Et`{*(^Q}CRKlXm&dC9}96ETg6HCtsE+_TH$=6h88Kz2k@eaOx#h^HY zbYy^=4voqXew(TDm8MJ~FBP634KCMFeF*DC?%4pQCkYH(m;OAOwC%gM?lA?+VEgPH32PKD>5FRzMNXmWt_C+{5=eEPb)bt#YC~OJF zF`m|o?Cgs}Ugmc<95G;k_u^Sw2YYod+o^&sI{f3eh|8Bx8ILY>s2ghk{nMTcRnG<$ zS^v~(N%Nh;mI}n`kXHTe+c(flT#^*x;QSlbg(A&RSd!tlBh588WF_nh4}AEl&h;K; zBz_R-apQVG^!PhAY{39`|KZUAhuz(a37>v(-;)14Uv+rpC1cniOUKuOrbG_(w<{kV z-&CVzJm`2YN%c*eMzSjxb~vRG^e%@I`>kxgs=KFWKX4X$P~M~sFZvxjc1$1=l4x+0 zXRo4yR#a~nMzIV)k&uGyb1)3Oe*F}0z^9?XjR}Jc2prol#I*KGV_C zdY`$i4(H{w%F4)W`?h@jP&N+UDmrM zn(v*x4t`|qp1pf_Mtn=NJ=IxNLQDLMgGDS(i#IpiMM?W~Qu@xDk5tEu>FP|>+VSzZ zG+eJX0LpvT=0e9t%YzOIBJ-PsvmYe%w0ur_0 zR27wpAVvymA!)+F<~Mh%1!9~kHVTo|$UDx@u>{dV-CuZz-nw-LLTkLi-N*2#X)Qm7 zx4e(H8;VR(P4W8j)vE_!D0hv)*chvM)K`p>d%`mbD)x4;XEW)fLb1z zo++ei6C2^j`{6B*QEFf>4`j3-C4E~9yCbp&w&g#``&_OdIDo;Umxr95K7;aRfuJ7( zz0KnC-p%ou7!ne)Y}G2^GJA6>o5dopc?#s>^GSN*rpLX4wq51%8&R{&*4o?*XfO^~ z7`)8Om+L-rxpGOEu11<3B_FG#jlR!uL9>tAAT}b~8j!);jx1<)NO}5ng8WKW3gQ_A7R(_jXb=+hnm}!#(gU z@hI@>Rf?mhjkmu`&T5(sd<@cXUlw25-L=Qy5DS=*?4PbJt53ws-Ooef5|QlT!w#nP z@ub(~J`cM}&$T_dun(LSEFZZ@u}LQ2DJ(4egRaS942DCw53SaE>9wkJ=Xm?ngk zTywQOy>9K=T%}x)-vkCiC{3P>qL-_?e&^1(J1yPEX?ivPY+Sx_r3MZ}-;}nJNo2z- zH*Q$jI#o#Z=qI_Zeo)NJ*ROsQH3BH{=}rVP@s3lnrZdB;qF&y{swzWhFM;?*~mNoYEoJP$@hj6)_yIQ1bp7OXn?=!@+JlCx~f z`1Tz-D4M+*(^eu64-`BIJc^bLA+`Mk4m0lMY8g?uPnop>G+n-C zjrrBkdGoW(t9)E7Ln7-GXpxV9`D9ir8Dy;Gm)TIUWop87Lc5~LQz@>bU82Am&5c!> zT3VRNwii9<64dqlv8mIizr>7J+_GX!zZ*AhU!C7>qZxu%(C+4ax5C@#Au`vKpGR=V%pr05XfJs?yPy(=SEEo7GfZ>9ww3 zuU@mE(0M-;UfhewV;JY^VrrLlmR|H%>_WEBfJsXICo2t(^9C;i7I|*xNpW!oQA)c% zf0TZ7;&+9Zok2mJiW>KK?p&>EYBE>jX8Kz38ta$=tHgu#=OMJDJwsxw|Q) z_eLY5v>|7D6>XE&6l?oo_cVr>zRgX`08{xRx!=-!o zI$cANwWTf+%@({S*v!~4979MF|&hfNC?%6->@@p*5s*b z)Nf$L;e2c}PTO|+AosAWih2MM#p>*cm0!_}W`3!_0orDqVKSJsr{Q!Qaz8fLeAuA4 z$bRDF#q|a$2{h%)9M1AFh+6e%bz?)ru4%Fa1mpWUix(eDF>7w9iTdfV;@XVE z-5qp@_4VjnZg%|#Hu(Q&Y@D>CWDzRurbi3rS(jE;F2+xr(cTaGjGs%BB3W+x{nw+X z{uTcIE78$!p#dy%uZL-;*b}AX7N33lca^p1?9|_!oSckXkZZUvs^hC^6XEeIzkpyQ zzKFz@-E@757&Gy_=2%_Og0ol&&Ip~3r->gzlWgqUeidvt>p1m;H~*=A-~1l!xJ-F1 zmzgb1J3Ok&y-%G&S$;wWTXHG0seDy}-P^3shonb;g&i0uGaMqjYFhoHoSZX2lGrfU zY1=<^K5ziHR`#fVtJh7o%vF*==s|j!n7hi*FrB(ghvf~t@Gyy9x9OvOV5V8l^(`J5 z>A#zn+4qKs5~zy{39I$~El?g`IhE5NN=mvpHynT3QRY=IaD3fOdYI0O&MTqHr>P%q zWDnfhUfi{%s^#Y_@QfPFv;gc>Y$UpKsE$Bm_l8Aue2odN6EL8 zBPJ#7M*;J#=zk}lgtu+y&JS=fm)FGhWR?oQ@kLolXe;NuA*$!#!GoJW7dEGvz9BB8 z;nvI500ZetFcgu-iLTdC)=*5XPjHmt-bQ@@QyiSS+Wl zKjr!4hp%4r(9+WCKYs1SMfNxM)?dw7HWVm?%jnEZhuaxSK9z6ZzD*2Yaf$Hz4xmTc z3d-7LV*}&w49VWp-oDYw!E!mtMGtTBnpmrOmoiy~;=OyWGPw8bSrd zvY1gtDUAp)v*F_i7(maieF(>xe)|j@nBp_pJojh4%!7OYDJV&dqgkk)jhA2v?dsn@ zzcIG+=oP4?YZtbnkJ_Q+BL-2SU=>yg1uBY2<%{+nsi_NL0RcewGBacHH7?lL*wC|1 z%y?OH`nBePXEWC;x7HPhV24u5WL)Pycwdv4`|8zPrjXfI=G{w4=`w$Q@_gli7sJDk z07+RpfOg5as~1$s+oX4@u0`ymstWTpc;ADAi`56FS^T)O-q`qnukV|7Q;Pcyl^;Le z1d0gRKJaCk+jqUys}*c3*J50Bvzypu+XUB{b30O>fJz*-SFp!{{acG(xThuwjL-Usop;p_K&&{|hHRG{>*Y)C;*+fVw}u3o*5wzYoK~j7~-Rz@QJ5qqP&ee&{=`HoM zVDD^qyT!yzhI+wetWWcqTw9Tq{`9vl(v=6v#p@V;(79VT&{o@X zD=+2H+JiRV`mmNS5D)7?yGbLp84-oq%H?VtS|dJwI*PPK0|azK)nCQwe0Ndx9}YTm zH*bm2rwqW^HCxMb6G9|D|JGmCXZ7jn66in2xkX8EUJx$m>0Y?C1dRlGkeG_)iDYkb zOt*9O&E=Oe@c_8}!Z@>c@4lJQOjUCY97FXbnns`)l$T$)pZ81gTQTS!o8sz!U{0Xi z3Gr4A9b6o|Y_$0U+L573%f4q}Dwz>pl!CB4Y+L^PJ?Uz-ChTWH_;4fFEOI8kGK;wy z6&-zov@I%VmL2q;qS1x>YcaIr8dy3;`kS2)qt;U=i5uHswX&q=Y#x#aRqdSmuld@8 z+K7%m+*ePC3CJBHgKm5OND+82cC6cuCc;uNS?KB6X&$tcMPt^(LJSkRkcH-t9EyH7Z<~~((!SHZ%uS=Lp8yp%P9E)y#@{tDGjlO&G8Aa!mf6?f*R*+vok&(xoot>2>8#^+3^DQcs z1W9&&ne_9#yr;*8P8TbyU%!5s(Oh`oG>S3+;$3;>C8XJVqqYfeZKPqsvvYIyi*8I| zI{{3y{kYX>PR%n!Hzqi9lxtOdqfl{|85kUcw4x4_gY%}RfyJBz0BD~`h`w^|+VW>_ z*z?4G=K3n^{J4Y#D^z^G@2rYVR|;+@((obHH$&M)&=F}^&xD^6{S9&hVH|{Q{Nu~J zy|h13Sqaz!*Mu)*dFjMg&GOUe2>;bxn^NuflpxBGvV5}d-p64wP5d8 zZ4lA}$U{+1Q#}ivioZZai8?D1Hw zg~3H!$EK2}XGE0R@-l?la1NxkI8Y%gYgJe-_- zUt|KOzgjP*Zvgz5CtJ^dPsu=WZ`?*Yu9UJ+|zHyRty!#oc3 zYTvOVrolfKhrVa+k(b|Ywbie8INk-hs)tax%I#+Kxp&LfX zwYp|qI1_WqDMk@DotX8rOs5IR`Iej~&@$7?LNqQ~k~!Dt?&M)EM6T(h?Xcw+VoPj}tlu}2_lhRh=0 z$R=pxeEj(FjOpP(g}ZeH_O11JyZ!H06AXi*{0-G!+zSMn6!TOpHDXBN8`j}WKwI(7y zb~O!Kt1#mO1!KmCm_?RT@+8;m-rI0)S=g!1bcavOd7P>127jy3GC3yw%Wc0~{$ci! z)bNzQD1iwH2`SkaL3&)*WwKkux;wkJeR%vEJnX5)LC6!xAE{Z-w^~p}IyJs2q|}31 z>peTH=j}U%M|-LIov+e#beu_}*}jazTf9>Nh!NLPgwzFcekv8VJDW$1b7>QpBlQOH z25f-GVv-SXXuhV|6O_=MzVOgNX5H0aW}?do>Y6RR$e$jAd*q|%W-&;hH@5VBlbvl^ zGh=y{`8vfH&!0=IuYF=^uez#x7w6aAM=TgOZX8@eLdsV-)C&(*uUL^OJ9^U?jU?se z#?7vluGw#<$HsiG)T2FOS=f&X!xpm|eFzu{P?G!`1IKz}#QnK+U^UiNZKeTM2o~g1 zB(x_;4W0}8P%Qd8HSfWHFDUg}2*b~p?b*0mWmEVz3v)s<1jS2J-*>|RMQJhSS#IAu zv~Ry)$KvV*Xt6?O`nBXR4IFFerNT`gMQLg~m$vW5dF_I791Qf72B8?b{+5TNR%hUlimN zr8bgiQ{x62q<`6r$_MOmm;K0%R3Dtxv=7S(Jdx*?IjbVqz5^U#q59KPe$|-6J}h3L z*bC?*xDu;^yP6avP#V9F8|O~de+Jd}#^BA%mwPOI@hG~7e#qGTxGJ83WOK@If!%(Y ztBn4Sa&^|WqW0{$2Tz_H#d_*({KP9p)Bi|;HH!&8@EUssjSii7QNT<;THT@dtLFzMqsNLI5Pg-r9`$04RCSZLaZh7zm093vVIJJ&U&-KU4g~`~8Ox z4@iaVnz=z4UtqdU(j!SAyOl(+q47!pc=h6{s;IF!IWgwm%jQXp(^|lyXd@h`Z%*Ba z&FUU=sp0!)Eo#CxY&Y5CqeqQ0y%vEinmV-rcG71?`qnrIz}ky1_Oc+bM;tVWn&Q*( zMK0e?+Fdm>UC{WOHc3r(uI$md(i^i?4 z)i+__bs{lXlci40jYgWHP@&!I%(RKp50d^6Tv;#4e60y_MEedZe#cPhjqd~n1)Vfi zsFhSi1g&^&s1~~DOxr{rwP(itj$8#O^>W&@F`f(0m|U~3t5kMxA(%lHw9%LSQmf=@ zUjT>fJF^uW3#N_0s_XT6wZ8sU#t`G7H`%`NFX?y27dI-pDHX(+uksz^_c}#UFZ}mm zt9bY%SmqQAoV-rCR#j|WK*$K@0(`7G@G*{NE`c85d1q^NFxt8`dgNo5-HTdl%?IkG zB_)qwAiE_ZA=61Ok%)~1ZAF5fJT*YYow-s$RzS@MID8-Y{Kax3nyk7HRe7~( z#A>)%nkjC-T9EnT#Ywj1QR{@CUW6xTrFPEXbKy%GNWq%&m5=@SZ0+%w@d^h-$^p>;`HokDKd6#I|kbNN+{$--d56U@0|8+A1ulL}YShc?BXi@_+u zNXkCprK}B06va7o8#6<6^p3p!`0+6~i!C;Qy!(fo-27X|@b*l&`=u>Z$+|cPX}if~ z_B9_)6NsoqpPp81=eKx1(4KDh4aj#CJVLFTJ7sBERb*&Cc!JxHpL;(@O%2ZG!C`8JVQfjv%YvZ7(E)ll=-mlch4 z)ed!%X$>fR|Ia_)%+RY(Oce zmtv3*#C_nrqs(WZqv!de-;PA`#AQ*-OiwgDv>kx)^T)?4RqKcV4?9E6n6;v)p{us%cbr5{7pG^&Pdw%s*ad{kakBg<%Qk( zw3pvUH%v$PbW;hUr!1jpEDGacM=c*ccImaQRn_Trd@YS^q~@|$SFGdfWpTj4`yW8w z-H0|i*!phui4hj&w6ekq2tJ1vMG1l?a(NGDZv(q7G&IcbpU&HO{PZc@pKD=L$rL}8 z(A&55>x&&IbMc-wZEzjs^0DL4Z>plV&pPf~|AdyGRl!x7lEGOOdh{DZT&CWDE`>{` z3Y;Q<-m|L;wh}ye{~2Hv_~EaO%KdvBbZpGUYS=jRV~ z*GM8Evflkvg!hzEhsqE#s^5na-Br90fqcB^iw!Yq#04g-Y$eERj|T&Ae6KSuxexSw^$z z=%m~G@4$T_A^OJL-P78|If9Sb(g-6=Iyu|vwimt#NSD<#)YHsq+2F6Fq|^&ibno7~ zwW?+3SzHJ4aqw3XG;dKOKE>xWe2ZsbufPhsQtLo2YFIal@mBAbWIJRa7HJx!_fx4W ziY#04CnC)oT`RK22`?{Kji5cIQ6jsZlNq=@D)R<3%tFs+=x4)!#K?~svjC$7<`u`c z=3S&!bRt#?nhOv&jdp7Y9F0b16{S*+ABu{aAaX)<^m7!%J51>pw9J?kYO%2)Iswf~ zTKsyc&6wJ{MnCqmu(TAMK)a6JZ0Sl8bKQug3UA!mSu9Lfux!E}4AG2cFmQ_15PapIUR{L(lWlEq7CmRwV?XE) z-$KQ27a$N#LR0Ys3AaI$yVA@l9Na7r;Ye9z5DS&XESa{>GFo2GX~_3TW+M1=AO|hU z3^MFax;CG(GU>$-{KU{A|F4FVRsx6S|JV%sYwuwtlx|yTXmpg* z@yEoML3*TO=|b}X#x)a7r7qP|YwGGY15Hr5j`bLpjYFCP&IGH+gM?@Db~>Lr%j*7uKk1bs$l5+a;X zykZl6_E@uK4fMwXq)|FD-&;F14i@aJim<@o7x>Bx*#Sw^vFDJ-7=6PcB8m?VcYF&T z3JMD=^H-$l28;&pxa64i-{z^;(6qnIQwxwq@pE1{cg`7k6b;3=<~B=3TnU8Iu0FCI zUClgLp}Q`b3*yA?TX;rwM}eGR&qj_MDK3}OUAuJd%*a6xAD@Nj5)|yI)ez08aZ*y1 zQCF^HnEt=|Wj+@q^eSqWYVe0@qDpk3V$NvBLr`pYH-dp&8)xSU{{3_R{yTehC>bSCB~Q~urf64dN>ir$v4J!9P8HVF z5hM09&PO>*LHB@^o!3s$Wj#_xhM$;YWfhsCc;7X68gdp;Xz=GoOcwa%P$p~8ew`NVwKSDl_!Y9$fCZ z;vG#;xXYF-No23Phr7D;%1?UUsz5SxqK3u?fw5(B_P{R+7OS~7be3Q{#F#h6n5PZ- z<{_t~bP6*9V>agTEa56)aSyVBXusc3`NgGI%dFOJpAE_hO*P%bXoWf>a+zPe7wy6) z71~5!y^5UN*L2{3JbjvIV3MHNUz(cX4wa?b{q1?>l1YnRPTNzn$=3nMP5+F9pO%l5 zU3lUwk8!q>Eb8j&R=v(pfAYeIr6w`1xX9I|3r~aw0XKjg^&lnA&XU*8Uge(elaIqB zK(k*tsj$y!=F>3UF&tmS)SRWEQSvSyZ$k)DO+13l6~r2j(bSoKi<9YxOvK>DRF2@9 zYx8HQpbJT>s;<-1(8rJUXNPXtSB;Mf3xrgw>f(|Emp*A*(Su#HkeY7qjJPw<=g~@C zU8!*${;%Xv#tT0_i<%GjycMt>6r9sDMiqlF=%kEuAk)euEU%&o$UZ_wmeUxX3b5WtL zCsL%yw29yNu&d~a!s$nhEIKUfDRe#msUVJ~WT&Q1fB`}NZ+y@h$wQC90#CY82Q1jA zpnD4l;YHOcG46>m2H&OLJ4?@9HYSI}d$_~~P^E=`<2d$xQ&VZOOaQL=Da8b~ri6XOO;rqVX z#6;+0zvMFq@7|$B&8#nG`)pL2Bd4O`1LrhJL&oKVaK81@IYk1bEJwJIn>zJ0H#$(J z59YI`1w~R5H+3fdg`km9ZHWerv1y!=P!ZjbbV@Xb{cNyd|0jdx-4Oi`YVD8+K8U$^ zUiU`*<3r;IfM3oTpG=-!b@yf2S55|}k5`R`*J;zH(FabyQRvte)N3QTAg7i(r_FyW zx|j@nrxhi8|Emp+^4R%0%1~#|o@vwv3JWdZeR{M8hw8bb<>iBLW;v7IyOrcXGCGuxiJUN^AJD z*-w(Z-rcLH+_BhCWgd15kn+$1?_Nb2f5pqG?&l3qwN3Il*9Ud_q>R?E@)t{`UAFup zpXNfr>Gqbf_4dum%p85#wUhDgY??4X%PtmNJ>)QJo8F7Ec&`#EtZc$n`ZhpoC+{AG zd+gZUW{*Nz&|2MaP)eS~DjgATu_!|1v-Lmg;Mq@;8A`J|@R;R%@)21wMV zmX$521Hz7vL^W8uh8EB6kQbyq0RV_h#sRbg?nqZnhWDo_%=+b|g)^o?!KTc3a1 zMwt2;Iyi8sk-7O32#Iuvg$0WjYeZ#D+WL03ak8i9w&t{R`VI!!aWLi z?57{-uzSZpbAp#qCuM}ZnBO^L$AZE>U;pmTVsggX9Iw--A2ZL85>A;aWrp4_hIQ4o z=x7=a0<|jcGDAcg4i=xq-tRe^#kfa{yqkZqJI8nqkW8gMLL@lO3xkAY=aV91(zYSZ zzXcOvz8`1#s4_J5!Fn<&JEpq*E}=Phj_yF1j#Gs{D{W^m?M61;ffflN$fl$mhMJN09QXX{_!fA;hw16Z z>4ayuidG-uhTv+MrJ0{KaU_Ra(+!CI=dsY6aM`(qKft;6Kg#xTgn)Ilk*48X$kSS*<4f(s@y-!i~$R|74R-Gq>U%dD`)8p_Y zS(&TJyYy1sSF5_`CRp(Bp+ie#%l^B4ouB%}h;n5Q)JHhz4D-i^1yl-N^n%wSHVgAs zAk-ebSO15zI5fYAus~cDXM0sTb{B5Js=Hr%imDyouE~+;x|Gz^jf5Ha00~euHtrD< zC%zz0SMUDyaLENlf2F3RNXyE)VrR#5;PxH-El7z1rxpjmKw94oRe}HdN5(w~fE7xl zToY!~xPaF9!4vFdBJH4a`#63tkeIthkOd})f2f&S$A8!owbPyy$ix2TZ`^-3VDvAN z$RzliTC0CQR4etO?!!GM-wG*`hvjJrKf0OPifuMYLw0V}$bXogxyN}>m4@rq4Q0l} zABu`gbNcg2Fs0BMW8${xP{I6vAJs6e2LHT(|0}`raos=Elgr2I3sss~R4pqb*J@f= zT)sLE*b13LGD(x-o)7+e&v8e%8&t6oJ{WE^xBX)Rt1*(I6`{tstU?bv@`&W!I|9vy4;enq5=XQvi7d=bfw8P~i-|gjN z>u%(Jw|{3pV2fp&hk<>c_m=m49RIlY$o8FkdChLSDbZr&2?yVAP0dofOV8GIdHeKkdgIsTL-xC$H~34rYk;%oQMz8RV)F6tii*GCzZ$?cdGe2M zt(V%=vN`4U8?USuiB=ehGA%iVQjG2ccimB#D6N0&-!&b$Z`i4L&Jj|eqYEA~#OkQK zyD_yG#^Tmby8h>rzYTMVm+RJl?0P!Q%hLfPn<-GyBW@{-k@opFGVI6Jv=xCY^wDD6 zyVS0BbpyM1WLwj2E4r|m2g1mUIJ<8}SCWS%rKd+dQ$z#{CR)v@?nzH6giiP@-!v0E z`GR5rSkVL^24%q3gHvVcohjQPoG{Q3S$EQ56^9QW4(U{expwIET^397zFpCe5DDHn zt~%seDFc_q{4i(!{!%h|={Wioecz8TFK2%I@gP5@E?$o9vhm)Z9m>3LH`Q@VJ*SzXh9A=6gfCvS5{z zKam&dbLx+nab~jlN?UTV9Dca*9c-PLVIQ>$i;xl)f3*!b#*2Y*H!?i!){-$bW(E_zKaHS!N$Nsw?eZ z<3tOX?_vg1P zzU*B^#S`YUEk^IV&C>Ei%!G}}K?o%LN>85b$*6i^C2+QT(v)U0NkTv3dt@~zOLPz& zJlF{wXS=$8CSw!ur9BUtFWC%=@@0ABHqATNo=4&AHSe4?&7jP(4;w z5$`R(X)c3¦ z*%n$_cr^&cB?{v%UZJj$n2njp&)C%WNScZH7e$s4*z@{f$)eBV_b{@JN3$P3zo@u4 zxbjI_nlW35(WdU46uS*lXn;ofSv0_C`#P(b7nd$vZ~iawu0rxsQ65qf*fGew54lwxFxx1$3mGS6jHfLxXZ*%6Enh=%Q1&J9Uwng$wqT(l1yGYWRc1*0xcohY=aB5uHO562HA#hq0npgfhrE$O9D{O%WoR|*6OFhd z_nA?X2m`OG9QN*&u+J3c8!q$PFi~`~=JA?F+Bz|BLJWey_6FYlZRk*8(-mbErI>Aa z4I|-C;i^6OBhlZjzV@XK!;7pDPy_?8uU#i{KsK8_U~f$q;Qh0L_?wb34mw0C_Njo^ z__RPE{vXUGpmn+4*4#6k@#Td4{!c9YTe+U!DcyLCDbSo=@24(f0qk%dv8t}?w7^QB&lSwAFqM&}}~GmYllswe}q zWkI7q=iTZP9rcQ?gWOG}Ztm_jtN)Udmp`gAv)+XWOP_(j|e_+>^Ah=tewExZa^{@tip4B!aMLa)RCML4|j~-y5E@RpNs(MxV7Z=li zUFvrI`u4r(pjP?e%x3>K&C_H$m@Zisxa(6y@{~vD0F3RE!$njImBaiL#$jsj+NF$R z&6)N&(a;3(y8oG_g4B?ZCejp!lSK;`b_GyNU^D!F?B$=8$)B~P=4)s$jbkJW@jgua zz{zI1`|X8Hv2I<8F-|hG`|Uqzsq4^#zN7S+7>U6Prn+%Y`0d>(hQi?*7Y-$w|4a~4 zh^B2?KH1lZw#!updk)Y4F$Y5F+JebJAN=6=PN5S9W6yh0ENC(W9d+_rgymWCD z{#*Q|w<=EOw&$dr(AyCqA&<(;Umg4W{Ctwb+|>zi#R|-j7WOE5LKLOCOLgxk_+#8u zm=j@sVa(h*ep@QayULr)a>pceQ$_RGBgk*VxHm={H^O>$gIpEkjIb|u^s6JlO6-Kc zD0uJ}F;eK58bKNF(pOwRdn31QmA1yVJ2lhqjs?3(u;k{{B6Le2sBFDy8b(;)EokF&;xj-!!N`rKww%HBL`>6R>o- zwqkGhL%prx1kL#vg(Qk3=3T&Ev%ez~!gI7HN=%-`K`xZOu- zh`5f~gJTNJ8!{r;nGX?r&pWb1j|Mb-kaHU{?W*3%nYImEDP3PlKB~LcecR`nXOYcY z$DLjErtZS7c_DOUOx3k~^<9HgYzF>R!m5O&s2d}JVYP9}APxZ?A(D%ZBQU5KD(yRNEf|u3J|h3Z@7D5^@WERe^l#`>p#fWv^Ux70-_4hMi`xA0?*HcX=H7+b7p$~ z~}=VovUNQ`2)KL07GAJx{Ts&ynuG! z%-Fy|R&Oxj!;uAFxbQ$mu}j91f66EA`+x|c#A6L12T|8XEl*p2Ek_K2q@g9rLb*@h zz7H@Z`hIALDaCuWnTf16gI)$_)Z>~DxLK94jn%s?~biC^TTsC#Z5K~2zNpN z6{J57c3e?nfFbz~KWKQDKgm{NWRdKxN}LaMA> zt=(3EZbd;@lAv{{LTC+SyvqT0+wEPSQ_0v>^5ZcZ@R0Oqxo3&&1@_V}(4K;r?1#}w z%(jA2HfZp_F3ocgBhH!RBpNMHK{b~4O^i2tLEx&7b!wc#D^6mS>hGLZ#^Pt(i4b=r zh_fTck3YtA5){~ijoUi^=e67JjM4~-8UEO+-*3O&W8%^ic9SN>HqGzr#`pVl*b^8l zV#oE|ka2sDLDEo#Q#PIW>n{q8c>T{bX$emXzkU9&Jr^{i?B)8%E;>hs}{PnK5Se)JQWQ-j2 z6O%X?N1k^Ain3(-NCk6k#_*B* zXhU)7f4CHNLNo*}l^13^(ZftivHq)~TSl*cb|M0ibB=}VuLyn!LGV>hAsIpR%aGfB zV+tj+SH0Ln$&firo=X-JC-8rm#6|Y%@vqUyWq0DMthx&;2`EQvRmJlp7?k&>;j)0H z-@|}ir8kogn2!3FPI%BRJU(772884jSEY%Sht7dz-oJmR!=DQQO`F{E|KHz#>uQxI z=W(DAFZcd^*Nz=VqY`#t!I_gKCAu-`tP z2C3!!htP1j7!=&-FVtSfT#2d2HgB+??qMj3?}w)U`k+w17|4HHzB#-^QC z+|P2nQGOx9G~gc~Fyy2x@_Q&+d3ikOo`ot5lK>8yDuoUW2wmH+awyO0P)SyA2OU5x z7LGqCSC++cbO_ve_JufImzx73F17o$SR=IPufX84G(k-4Kt%bG<@9qEYR;cI7A6Fj z$eznPzx%r&JL%)oI$#<;vTuamvp37KZU^kR@jIa%uj!Yv?s!tH z1HOi++MOZ;0lI|Mfd*|`_jODA{+gb^z_8)ha@;T-QR#?N+$bmyR->GX>YnmW!%gZQ zmMbxV=SU!9(eL53770LtV7wmr2w9~aH!D5{u=f4r-*4VK0y%?!T`09Iln1Z7y>kO4 ziMGM1uz)OQ^C*<2B!DztTnSQ#=u@E}&-+$4ro9-W zuZNjTm?6p`EC;#64*ki*Q>B|#hkvC%0U?%m=9CZ7k;AB(KSqtZm{Y0QSt6g8{AJ&z z{lAt?CSMsuskR_8_^oe0T+pK0ejU*i@a?y_;=n?G53U!=HlwA zviIhd919UNU|KMNh-s8GR?_$f%;mMb5sdh zYj15oK!XvD85{>A^!lF34j7DuJ!HiS(KEz)q({kvQCA4L^hWJmaF&*}BbXiDGqQ^- zV>Q6vEnU0zDcfuTgH}-mXnq0UcWN-5l+*hhw%d{A)=@v1IG1k&7B&|9)IxgVKtq@l)div)`KMt^PS)p8T%!~ zxBZk8bh_Jw->P7xRM*z(`nC>?!_+MfF$oATyq16b-waT<$mjGTS(acjMOYirbjE(_ z^r>H8@MJJuLy$y5XBUXV!eXqSip?K1Isp9?7_l;WAfWA)w3uX_RXF7Sq^X#v}`Q zktuEyxlQ7qFbZ))YvcD049d7TUeX@8L9fGH&YOcv+DuF9jE0Xvh!&!=4k!imU_C28 zG@M-R%+{kvC7|^QB_}VZ7}n5my`6xwKzO-nE?|&@CK@57SA4}Z4r$`-HWO%l37EGl z=z)TNg4oHsTsLCa+Ey1i#nRLtuo`+ea~fg*yUp)sHSdSTZKr_t>?%1t^4J6h$Bi86 zf`ojUC$6G9QnZC)&_znm+%i1Yo^Few;UnozgS+YQmPrh{v01NPZH4`j5Dj>6SeXv= zQ!xTAqQKRIiUU1TDtf{iyNcyom_>huU{WmxL-Ae&Xobq(`B{K#+AZYY*h9w%Z<5|JF9plYL(eT9ZsK1+9SGi z!QLVskhh)V&REZ#>!L2B_4x;(R5V4vQ)l{528JQSEGX=pG19EjpD=Tc1#r;#iFu4Roh}TJ=bKeoN+qM#AXdckJq>SZdj=JCB1!OgxT?K zUAlzTNzL}NTQ>c>L3RG^i1_9SF>kEgTMSC?zEK^}zkiKr`}yX7iBoBu$&(WBT)P=? zMd!f;4hUJJud(|dFM!#^hfsrbYl*p82UGuoN7_MPFipn(^=o(aHHw-veEcA{Zgm_w*uCNcnnLPoE&Q15>jV%(}?>^TrDkkB6gX1MMZm9iguP2I3d@p>cv`fZmhY5_ z)>&!?L%)Y`H4wiNu7OcU)UcP3or|2BOP$E9X4mqAc5g+-Hi zq$F*QxFCPe@hh_xY8YjUS-VpBb6Fk#ryw=`+L?13zrWS>d38#CW!Ft~xLjItvfIO3 zOZL1kNN#YQJzMIB?Sb*Czwhl;JH)Z-z2L5;bN7*dMS~@!nL1GfPYLDq z*OY?YLCLROk_ulV{X|yujm7Qr;HI0E} zhD}8SdZ;Lm9lJ<-^+0zG=6j~Y6w$-=mPuj8=rBDGUl7x~@P#EB#GUl=g5#Wy>BWRN zPh}Q$xN_m4+yB3sZrO?z9h$CHr2xiH)22)Bdt~n8smjV;f_%ej4vvP!6@xH=0>Txy zs^FxlT&`_!iu(dW^`9%+fu!z;BU1NSOxV*Ar zX!;pHzjd3}09Pb194!fr&WpTpGVn&Mrg_G-%{qw%gM+`f`w-E0o){`jFWyB5Eu5JG z`3-TLPf+bHr65i#YxBLU7n82|7~oNiHUL-I+$C_+jlmS5d2#W*#=UcF@E7?BpoU)9 zrm?U}XetP0w>}J;+xTLphiqv4{)Fbf%|A}5hW%w<*Yj!JIQfVEr}TbI9ogJ_{FJoi zeOoul>qpEJ5Tlu*R~^e!SvP{|^wASq_S_*DZMc@>Gtw0%vHH2XWE*irR;b|u_-Cld zi#yhWax=RgVLte!mo{cBaM5Z{y)|^D=awFfP}t2haX2^T9d{_cQTATUbBEP7LD(sO zbpa-vU5`^!-LE>f;0||2CW5s;dHVFl@zd57?k?N%hrYh07`T#1V$YO`G5<_dAV|Id zsW6Rc4$EJ7D?KhC_CmoiB;~`AFY~6qa6BnnGHB}c-u>NOtqWpTxn938>CL;Nt2U(Q zPK~`|95qg?^o+K{9BP+-)2xgb{#e8$QWO0f!lZ%{v4j!()V5-91Djd9e-d7_g9Hgu zoEYyX8r}ev!n_0B_v*p3&+Il0G+=>oVVjyLGelv5%%3zhK=nYd6O3(z-;0 z(bZ@j(byU3@xO;S_sT)lu68~19JPJ&FnfP1DEygsjhO_(10*I;sjB)R4ci#vb0ek( z(iT^KgZLmE;a8AhL^Pr0Inx0*HIw@aHrV{d!BYhYr<8qSkTXZC-L#V=I-zkz76hL? zV7lemchx=b4h-N1#lQ<^4sGGc&{U9=o9~)8EuF{eduiN?Gl?3fS=eq(OF&$hxp}5h z=NXM{b{^hoGqRNqvb`|sh)VvvsH{Spc~VCo2FiA@8g2`F4?8f2V}DgFLjwcbLhg|x zDsR_ltHWpV6$>%!f*K^UEtH{#wwA8gHMV~@_(D)TyXBQp#o*0XR)aY|err%^G!Gq` zuk*(TM^A6>OYU3SwQWmn`BHUN6$L2g*t=nqw9$J%ouUi25mgN2=_PqOa0P>rN|=sT zobJ@TBhJBA#isnji3QrNzKZHd`7K?x-MMi_Y4o#w*0WrW&bq16yY%7D?vL(vv8s{O zZBw2|3?KfIJXY<$*SIHw>4)ShjH1 zfnQamTDI^c@Jg;Bo2s~Nlw|`-K;8PCpfRxo3!?y zFIKlK^bjW0;>-*#wM z7<*Klq=Chdv0MvQuRfjB%z*Zrqb6p&zTUjh3rm#v4#oYP%8YQ?#= zOGhp3n|dnOvZX10S(_1EH9EM>b`M{SZIuSyHdXpj7*{8*I-_J=RO#efpGqoreXc9ctGRu7c8{*I51R)$ z-MO1EKD4B0-X8;gW(|!h>$2M{v0V@UL5=Cd2K5*gYZ=>O;gnx_IiuIb%;$PWEnQD! zecTmfBd0yF=l$|&+B?R#Fdepo-7FKsj1tGw;nEd{;@W&psX7;Oxq6$;VHZ6^XC3cH z0a`rl@UD+zN3UJpH!`PhqVi?|fp&lAT)HFFeYeqr7ZDkM;$7-7B|isRe&c z%PRBN-}9GMH+}0DBTKtCeG6T$IJt6$ddU3~rRN$GLk?H0EVF-?J>|ri!T)0P|G54=t9)xjN844MG zFl7DB`i`IG`~LYb^IpsbmEV_LIv=}I>(sO6LQ_AlW05@<@ko3(blBeSfc(nFirR>% zEYHZEk?t=fHVo?Vmwu1mRK}@V$*!<7oxF3a%~r{Cuf3HNSLFD{7u?+Llsw^nO5YuDsL_28{}F z&!;QN9|@5AIZ;bXvF$)*TsU1zBb3MI?R}ql+u(9;?D#>4UYH$zvE^|5nI&Cbnx41~ zRM;Jz<2=^){vO}7=0TP*+cH9)KfcxGzNX5#gDaEN%gwL5n)>yhu&UGRXSZ&tIIHw_ z+T+xvPhHOwU!-fD!pn@duZ&85oBuib{fGq(ci$z;Id#czRBuVq9`0)zjn_T(N!7Zy zQJJq3I;FgBUk6q7e(|F?iVA`#NQmT{knV025u`;r1f{z} z+5l+~kS-;qyHmOmkS^(N>AGuwe)FCA-FxTG=s(QiaL(S(ex9{nwV>>P(m@~8u|O5H za@_17kW6DptKoltU7;AO zhNX7psq6H}c~GgL>fd6yx#Hd~o!1>r|kOBY+0*U*QxuV0J1IZE80tSHiK@JjVT4TWD4@yk6&;|hF2m%+< zKL0=EN}zvV156UICwP2ZeQ3g6RC4PShhB= z9~1u!yulx-fGIifn(KNT;?qRD250vuzP|MvIwAWa5okr9y^&^Lw9QUjTX z3?loh&i#60Bs;98_2BY&HkA$oaQ%EvOYr#xLJK+sk{2Yt4d^ML9hC|g#g!OQ^{MI^( zR@F!t7yrI!>gD}UUd$vZ0Q71t7~Jnld33z*;%Y{`?dSiRUnsPR*whXC}63 zGo$L%gMUkAjB$tb+U>Uz3Mcq%OCF|Eu?@<#FIWkDsWMGJZ-8z1tNV+04XsyfRJ~>q z_3u83-3D&Kf=6rM#-;VqGnXDYNrgP+A5(pYQW0^*Ulh969^PfWta6z*y)q{yb9TVrzA$jkc=>8h@(rcosO6EYX1t(fjH$a za&sSAyKV%kWV8j;6z})@l61=wh;b3=O>f@)_DjH}<3=8ZsomS#f4IK4e$8a9-H-Js zODIn>7d?r-{#0;1e5x;R`9-nhzn{(rtxvY0&hv+*K4sgGoJ|R0iL+| z=Tul&7)o)N0{2q5o*gI#Fi*0;+{-yg?nY28V1<$A1LzPKrbi7)6?HnZtLFY_GWa$v zdJFI=9}qCYN%gW+!|19tso(%Y9l-^%*PORTGe z$0@a!frE9PCV%)ag+|USnr<6V?a%ph;AT)%3{#RJ5!44yFw*b>8HB`n=ySxv{zeTr zapAEN;?joi-2#eQseJm0OoqQ`fss4Rs^QE$LC8lJTxxVJi99r7{6&PdXC;vI+k7o& zc>iy`FyxlHmE15@C7#vF-Hgsw7`T_uSU6(wE^l0nHSfz^S5o~chg+g=gALxqb4h95 zjk;5NJJbu6lFYK)Mze+U`o3C7bD8W)Tk;Hs{_?XGvR>lo%2a3$5`d_$O*qU8)-i7= z$TA(nI4WBZbTFyL0FwkAq$j}P1AUS{8zCFvJ+MyQO&vfEAU@}95=0>cu(F)fn}H)0 z6f|blqxd|Mq6xMdf&cazD>LY*ScgX!q}+t}%u=l> zT0W-&jtNym@kacIJOai7<;N~16D^)nF@CCPMCY^pRl_u%uT2fgI>p`zx)ZNer*(G9 z^@Ro#-4*ub)@90PJF;A9kISB$N?Hzl!SxuPF%X)dL7o6w;rRAtu@j~xLNUq|j zDC8~uPhiw*?fKmCa5^F!G|sne7$gR+)IUCli==6(CvAx3#i>DO>dR`E;*r%>FFxO& z6XgC%pC)}PqYC*=*}K=!+(k`Fam>(GL$<| zu?Bby7%`ILm}K*E=c0#cjx=+(i~=gm!)cao+wixZ?k&t()~jo$>;KnMzj$#HG0UUN zlp-a(*MbYy8i1HVV=(%roeU64fHqJ7=7RkKVp;%Y_|mFJ@nmWHx(#+m6r#kRIF>R+ zHyLFKGE_!(bIfo>)tCGuP24QTGQ;aM4HxswaOp>uPqi%A2qCE15a19LWmQ!K*EXt( z!cI9H2NzjncDa)C6_LD=RI#d@u|G3S;{}4h0|{30<{P z&r$r7F_UGVE~0vq%=C!)U*F8i_N>bMvv|8d#b@i80p5X-RZx%nZmF7Ud2P^o+l*{o z&%j{4HQAw3x>zo-WDupYa0f~*3`-tKy6}gSp1cY<*aviIyZh$_|>E{^KF+gP(K?MZz zLVl240p<*@gHRwI;Wo0xZeCBm2gqiaT1E*eej(5V;j5u1F9DAgC})6GT!eKC4Al=h z41nA~R|m*zGEGgni3b!HDiWB26VIY_{c5V5N|@fKcQ!dV^Xk|+*A!$F!I}hx3S``d zyB^Ob`4Nbf>KA+!{vV(F-!)48s&$Ih@C4wgUzRY0DZM+v%1-zZ1!bgO_ zAp`vj9`n1tcJctaLxcldfK(9L$`R&WPJvD4JM3!+;s&x#WFXP@&hH=w2VB3=6?PdI)r|*08;3sdDX398!Y9}Wv!G_fMYF)ZI=37E722ftDe{h;d59(l zc+UyyA`A-63J@yqg`6X66#zj*mJKiymOugim`VA*Pbbr5OABhc`bPy>f_g5E_v6jM zS+2Z7+N9rbxuj)8IoL^j@a0*o1#B>6FZ-8++lPC&cWWdQiHXN>XToP_EW=Xhz$69( zJwpIo1mbzsp_-t|3GC_srGj1v#Ep9g2hVdX8)QBSuLd>F$`RCaX#BKuWD_gBSyx6h zbM%|D!#^Ec6rAHCFwlDWfi(Jnl{w4iC7_1O%lrKFThwU)XXyGiZ!2S1z zFJq~Dy3~>BO8XJXjJs_qfvW;K`7JetDL0EBOjwhuFh&``D41btzGv>{>MH%B6SeV< z1-I5|PG^s!3ptJVdWziKqhXpeGwzG2=ly?cs1+c<7YY*P~@0i3}c(8U4 z7>I8rJU*hsF?_V$I2g8)#+De?D)EGAL;GKRi9I&5D&4>b1Hv9sghv_1=d?O*BevcJ z*%*&=rI?>8qC$cjpElzG-7#Wc1(DEl{tBJyU!{mxW+TRZ24?X~mPtHM4NFRioFz*I z;RohBGYZA&Wix61&c?f5Pou=JtQ#ZpHtryrClr`MF2b%kW*SCNAjY@hJ=`|MfXli* z{eHL^tAFxH^!nlef(v3`5K$CllMeIOgUSd}kt$y1ilL7RK=MW1BpQUffOi!{tCb5y zG=IryFufwyipBW0N_*SPRU|Uj9ea*`SHu|=G3#F2ZGEy|_!M8xZ-K?^gGT| zW((Ij9Q#?Fp9YXer464BqamB8=zE)T=A*AV1uLvxrdBPZjb$m>|5o26rwDnw=;hwTw9semFvhU&U3q5pe zBvQNM@OggIEi{M4{7T&$JFgGx_LTuwMO;t~_EzV!z+hz=EPLU9vI85Hjx>jeAsh}{ zWCRS5+JpV#erO#Ep8L3vHWUo(0d&ewIEt^suFWD zn!le^>Zh(i+pP1$PI(rd%R?|6LlFfVr|-1I#e`C5?K(PzmEjE$o;VHbsD2)?(o(y>vu3hFIiq`kTpSZrW-w;l z;$Qj5_}sa;uCcl(RbN+4QB3vmnR9D?>9R8TM*6q(ck{uj>e0dQ z!p`s~NIMtUDh3Su4HyZ7C@#Qa>WuPWNf~pYCef9S* z3Jr&bW0=&?14cy9XoHyMGbm-iLJW;2qCJP34A0KWR|`bI3pR!)pm78FAV7cMc7YEN z0n?{tWrJJ`kO|2MH-wBQwBV_B-jRo}0}$N;3;lO)PLXzPSSONhSH3JPVt-NEPgUmE z3^mVW23wPyZ<@UKdp7lt4TQb!R%VT#2*msdoO{fuMl*KRIcp_k()~?_VPqg;X#}Yi zIH3_C({>3MRUxAdh-;9HL8@fH*^Mi>0*H_fs8LTqct^5qkZ!cPIu6kYth2*sf#8b- zkifBnm>hZ?l=E+K1@&hEP}~BO)dJ=hDd10UKtw4L&(%CyVMV12Hy=dxbPNoX3=9Fl zoM+iWQH9L8{6FJ_K?FA}&`x~s4ibk8zlMoO&;SiZ=X?t{GZsC-A;j#Q)WKb{~X#I?oKAWRKOizKqO}G_w)`o zK&~|pA6pm^fFd(?P>|Fnm|7$ZNt-dy6_I(KyaRlB_0=9ShzF#uNF*dJZD!vgD2b6` zshJ(Tv*2O9xeF1l*^``{oRHis0a(gV@|Ch&%m({?F ziSQA*_lh8)tc+KBOZfjwLYA76^2hrw#J2K*^o|FDBJWsPZ3z~*4P@*Fnx#_9dYkA2 z5ZaT)(Z!J}R;oYTSU~-bQanDwsBF(wWvIR(D$U;nAMgzX15^Wo0i2*HAPDD#rdl9p z*2(tf(jZ`Gw?S*+lsKu0c{M5uXs1S@CG^-R$fKF z1Wb_td9-8sDA_3Fd$<-1gGCk|eiT4`wCh&t-uzEQhH6%T_kAW!>iIT53?};k4u}?t zABv0u0z}ZzfX)(*-1{q4Fr6aV>xv(O3BE;7PR6>rx<16gnPZ#IaJm4Nd<>vtc%9iz z8rZSHYUs-Nej>1hhuFHymxW>?7g(7M6$v})HG1(HrTeu?hKrTRC5ZrHN>@3yazb2b zcJf$Xd%y@TZ%*W+w+f!QFwGvsw;x@15N5swuVRz|>pBY|O>K9Wa7MAEjlMFK}U>@(F{BO-Ja)-~K$HHijj(@~(N6+o+`?A#!9k zWnM}xC!WI%;yWan04(iLT0u)b`pyd!-7u>m0}zOOCTW+aniuxI>>4% zjC%(_-8gAVeXx5o@5NkSmpISPDXOfYwl^Hln68nE-L1n={A%_*j*bCi?5Wy|%RDTb zN9Wb%`ooS}freWt>LU_Lw{G0PUn5<6@>C3K&2b%0y3VgLv43J^yUtybgyffJ-1g-S z?6zwmZ2}Le@iJ&0IL|Noyu$6&>AJ7%`-ck$D=LK!6e0INeEWt6*%Qj!?@d$Y6YTr4 zzOoHCPMg~fPpl56WB$#@owtR)7-(1sO#N0TD_1=`WOF?`G7l09j0df4~G}TG0pzC4kug{9a0PC(xaBwW_Rx z&lL$tfrhonX08dN9kL2#NbaNMX_jS|8p*JMdp;2ScE|}MA1#xfH(ilniTQm5)4P6&Fex%un>GYqN-v{ZT zX)QmsO&o7*tVrDVr5!Y|pyMiU{1?jB; zmPBG1LEP2y;RY&OtSll8g%cW4h=X-R36xbl@sC0K4*Fj`fWpSMoZta~vj!=D&;FSr zp`K7TF=+GJ&Wj@%dx&xjd?N^IHfK|4ImvUhGphh%a46sJnRtXx0F1BgJnaa{j1iC< z>;(_YZy*s9AP2a@$`E`2AP(n%&c2@;#QY$&V}=*(g4#SB#&3Z}70EdVCGefMFf2Vu zyyHo;34! zmB1|_Q}#Q8cogE?LRuEa5u4#u;w3gM=?4yB!Ct;GW?XLK;WR0~;70uomtmO$54bV- zst_gxDl4d5t6z}Hg@j>AAMhzVTc=_mPZlsO2qtGlbnu|H z1R+0=d&typ=P6q>VD64x-@v0B3nVj=CjuKNqU1wSQ32=Qau;I(H4jhumj;|!Y2DOd+Z?s6-D*;FpL&oJwE8!~km!jqLpg@XH_x3UJkT_#y156C5tc z*shf-;Albn*8wWE6HtktLgpw6lnD-yOD1+69ESD2u%qF;1(SlP{>gn>;Vp(y;QNN5T3*idHjfAS$_nux*ugk^luwMCXc2b^d}4-*2wo4c}{!CxTx5<;$15Op{Re zwOds{#QN*CK3?wNV{mlO;WL2N3xyJRgu`B-gBeD^E8i zlF)Ar>l!qa1LCUNaSRcYwsS(MwGB-#}d3EGI==9G3i}p#Y1H!Y|mpp*JrCTUt(sH&YEW z{L!xUeVQT}?-*D8_V^1$eaI{4m~u3344!1Si_&Kc!l zRknv1AUOowYIGH{pjORxFbp_iP2eQ96f-a6;d>L#mStR(qc+Dx_jAv2fJ#Eu++Ta< z%OT#@bRhR3ddMbF4wHJOvmv`zsB9HhN~dMSynj2oVDgCJi+>xTKd9-oqqgnBDm;Z< zHb(VC9Wkb@n#WR}P`s&mDD1$eiE>2{kj?**Ho(%I!05+1R|$5C$kL6Wz$fqKANbTb zzmt>68GjKV*5enJWPMO!*{V~_FZMoJgm3}(;;~-h_@IJfp(7*8k7>8J^3wYx_RA{~ zHAdVhn&Q-9pYPm$BB97Bu-i{bT++nUqLwQC2?_sc>gRAc?v44Wd!9KZGcXf3$}S)( zNY1s>O{dL6Ol$1fv3ER^ZgR}BgJnWws}}TQc#&Q_(d*-=(tY78XFIRU^tPhNVYfNG z6qeeKgSu@SoB7YjFFp2dZ_?ITTjs~~mR7!_l=8ZkjPxg+^NJM^(zRI7kQx4rD&}`~ zP@qQ~8_vELxL|!9jZ0pumTHdo`Qt%J-?w%Jx4qjO%hl1t#}}?VMbW`Wj;5~`^R&9R z?~bDWURzQ#bzGTF(jWOlwMpWPk21G%w2+Xjb_c$oy-Vf!YP4APcIssWm#zA{VcOjd z$yb}1cD{i+4qpEI#i73z>KH|7tGVyhp!JceiL&3N=yDlg;MJG=xV3oKX_o6_Eytld zN~s@u=}$U~_K=U=x8-RcAFPD$O$&vSouf&GUNHY{O-#Ifd$ZQc-A6o#{m1PuF@(A8 zA@g1Rk`m0RMcu%EQf>7`Ev-Hy%(tF@6T zQ&6kz;h-0B@Y_n2cq{064@JLQTvH)QERfi`>Ca%Dc)wvuSj9Wx_NxP;SjFhqPNL=m_~Inqji48E_l3}>#)D3HukBBaTs+LZ5;e{PO$i+&eer%r{-K%%PnT29m9J;v0r;&=25rpP<-59;qs6M2NiAb zAZMKL`W3GfcdVbl_05#Nh7U@*?tNFC&Z(1I30Lbf$WK}XuQvI4H*1q|o z#oUrqOx;i8d0jHt<0s3gTsk=lWUMLA9(->%1~u)3F5liSH@<`YmoER_xw;>{7;d;V zr#3E7Yg~5lsKnwqlQ>)5yRwB${=KHaLY>aCbuX2a=;e0Onz#LlXh z&J*iiA{4ReaDGMjJ$lac;RGJ=a3_~ zlU1tfpF-zwvQm=fb%5WOK*Hg5LMEviHTtQTvar5Pu&T@Cdn(abx|SIFj;DRKI^85D z?@RXRAPgt;GNYhiX0-)zE_w3=mMDRQAg=exSn*tXcYz~Kl?%RhnCfzz9XTLH!7^RhbSre z+}7;EAF-w$KM3?7sKfubbW^87+KWlN(EXkLEx}uJpSSIP2qv!f1sp3@cl&gkwHlU1 z32t|EQ95sF7JKPD+Y6)OK644lW!mSprd)|mrk^S+Q5D>Y3@oBPD)uN|;m^c%nBF)@ zFKC}U96oc=@zhN@nkf?4JtWT48f>8-`b~WM%{n7Gj!E*wW`}M|8|%snev%=7*oyAc zMVFP))wA+r(M6YptKsY4j@Jsp3|f=a`d8Z8N7MuF{7GtWZECZg_7X;pDF{Y?$<+B0bgl zq~juXbb|RLy=^+vr`+FSEz=g=O z-3&<}QP^~|svAGJINN?B)W4E{F?`^@W}lPNJkE2W2k*X7<6xlTz(*Y6rV8<48hN>v zqj4$&a~7-9RR0}6?j5#$vm!{2`rT0m8PWPxgGTPcC{(XDaBNEljd(W~H&7o?ys-h}G)LF)8lndiOWYq%O5Sgd^6c73Z=dywo@FInlYh&XNT{cWE+azR`nFL;xg|>@ zxo|6dZj6&-{Q&<*oGi6$0{Vx;4xHj>)|`JAo9Qw(%hikrEujrGe`^l8dC5-*ZyokW zHG?2H$ivXNgDK*U_^6|uT0#Cum6-|p+{(W_cWXJB1ECN?uF5u1EdY4$+@sc?A!$tH z`yqRN^;X*C*~;jwL4Pmr$9$ziL(WNwd#wrI#1~&Y_akv9gM9;M;(!THrA>k;E|DdX zl;u&~;&m|gp`NddQ7jjJET-2}th?#g`5s9c5wQA>u1=kbJ+-~JPT22@p7On!be)a4SxNfw_JHR86mKg$2mRBf!zE0{qmB!m zZ|X2UJTo<3{}{DBGrAuoMdIdh2ZdJj$}a|o%A?$^It^Rs=|!daI!PuStBfzJ<$Wuj zNQH?1MYgOrV)R7gx_8TK*XL}i{d3~kMlx$@U z^95wSd*?oz4b~j3X!lXxg5CG>p#SCd1t&@=#GJ8KeqH_1{Ic@h&9=&ut~k8IRhjsR zH3H!E6v^vLJ7s^L6`MDe(Mik-e*K2AHW9h#6KFo=d9^I}Z?ZmTibLtS?7cU$mmh*V zg>7Nzq-&prK!X74u*Fe={XfwHvCiV?{2kAy{|Y&e(KW?yZCxEX2Rums3d6+=dXi;q zrKJ-wtD?0q%=r$&Cb98V=B9p=3HuWY#nf_}cWCbl9}TVPIM2g^Hn=K8vDry_G~o3# zQ4enhRs!3A0bMj*7?~C{18;v!OX(DT#`aw3>D&_OAqm>Vxgcf5(f7W*^! zF1pV%`rad6u7K=^ocrOLZ?vpTdk0d>Wa3B!T{G%5S@yE9UMQk(jU@iInl^PgU`D~) zo^CGUo&CG$yMwwd=0YoanKnrLQc={iP!RGT#6MgzyqMTfnM5N;&i$Js^%Mft;ri@J z?bXfaA5?!GSsGl|erlSnP%5+}ZuNcOVr2CVKPb<=tdMQK0H!x_il&+LTfv^ea$Mtp z|0qJ`b?(g64^$`)bB+n)Ba%twGu}~`F1l$XQF&vR{R@;mwX_qfb~qI3(>YQKE^yY! zTg*S(l66b0IeC&lfdQYJ<=Q1NtwD6#g+;$_Q#v2}(6B*frP2bQUc8aSX^kZ8SbgaA zxIB9#Nr`cS(aPay;nKx3lCw#wgtJX0jB;yxT3Ka${q7clQMNtbs0#UgA(7Kg$)ylO z<~Ko{{ldf&MzObaCr104SqWFX_G>sfl8q#+%$@A=A^}`zStj&mCsB*x=Gee^UCva%23h! z-|rVu*ddP|^g0&l>+doAdxa-(y%PMNBnHkU8n&w{YhxW=yP^?+Y*jk{>;5zyrf4L2 z^^Y8j&C{r5F8&|Ft`A2tSy5ipINN3$(8jIXjBk-7U42_Q_a>$}5foA`@j)HBYWmn9 zyVR(gp?ogTYVuErMbJm%R&d!pKmp(raSR1D@ z@{A{S&CSf%n*Y%yTFx^tE&k)xts;j&1C8*1MGouY?>jvL&~usPAEkS}_+L6mS>e!{ z*lQX&rJDAuIhTa}3Q0P7sjLx4$qZ4cxjs@9bpfZeB{|-6VIJ75V8_4lMC+c{xm;O( zw`Ot60bj0~bwm3Tv&>DbSnMV*i^_9Tihu{C`$8e)URY+a&%BHGE3C3I{TQNcn#I3` zZ-py(3gLdpeIg2FJ(_{3yhqmnMVY||WyFT9h$*;el-n6V>cQ`S?M#aj(sQpom_*_# zBUq&087`6gu4hR7QTF*=xzr6e@*gk6Z&BADDF`jO)Lzfj@SU#ZO856`HH3VVBtL2y znUHzmi9^EEH}&-{#l?zqCZ-l_aaf-ySo#hsPa1C&tndW}bm-_D2pA0;2KgTfl_v^l zoL1S|wggvUe7KM!?wlCJ`eQAEppiYM8Od-|A%TZ?@jlf^GuV| zpE~^zJ+8sivd7~0i55pkl~w<|cy1zmC=ya9f~xk8;(VtnqKBN|_k2b?Jm;vxdcTq) zrRH`TB2JrcLKB4cD+lrLuoUsdzXxnIrHx6R z0YkH%a!}W{C45ufPCz}DYn#eoZaqJ`P5lL`jxcsF78LqWA@M;fujZJqA5zQ+^%z)U zEnT{)<)i?Ol^hRO z_y!Era;0CfT|G~+B(F}nOj#SytL2xE4>~VA>-(L8m^BAIMvS4!eU|sUAU~x4l6csH zVrw}1*BUi+Kn9+?{VS(t@A*iR;^cE`w(q{TNHKB}aFpnnj=}bHRKLR`es|a+WAdE5 z*nIv_T}cVK!kSa>aiP6h=-`t(tC;=U)15jbQ}DG!&*iD!%i1lc;%Me4Zfg(ay$;G~ zDfG5~f4rJ>R^byhTV<>Ex}dMlkEq#K(}=?ruaP#2>fR?&l!p{T@GZ>y(qtRFE;%yClz$ER)~>>|XUEE1y z#Bzizfenz2Pif)4^ib-4>3^cPQd;j+%QN_Z|FN-p- zi>d}3Nzbz))I&*rg++X>k|XYs+WOtp{F#)fy8Ff6ug_!hNsTJ%e(WM-N;#@A54CO! zaw+=Qb4Na=$aw1uIvG3jA1Y3jxcHS8Ja%eV0o=^^N*g@hN2~r-mRcwYK0fLX$Zs~n zGGrH_@C&QvhvduAEYkc>H^r)*7N+F1K9jyK`Db4F0w$*vPHtTs_W!3t`+u|m1zt;e z6*COS?wXpKUnw6_vUOd>I|(ETfnE&>=R(L`U~|nXs4Cv|Mx@ZiXwvAJ#S(75VtAz- z`IY4jI%Eip{qQ4_j(*@IcJijaHqZM}cBeSp51mlcA3wa0gmRLovb9I%UsPgXpu`$J zlocoz${ZJj%mKui{S|~9RY(RJFd`OHt8UKUM8n{)zgvCKos<~nbcpspG@VcO$UQ6VQhf5z1-5{?uuE@ zc=%tF1ec-`K;;KQyC`=)e}vh9tgxmj;_kW?qGG4q4L^=F+2nY{+@hk6-Z7Z)HX=!=8pG)#OXnT$Sqh~@ymbA z-+y%KX0Bj^#A2XD77r4@st-Aw%AtyPanvEg2`tjnD|_HL2QRaxp&*h*b`mIc^&Os? zISd%zLOS5r8dUua3b8wa_nz6y$0c~&4muT7r_2%Itw#+yr`3K>?0$%yFowIkyZ#)w zDHwmaS8XnzRkK|k2sWpmNmOu*A}MB&aBsTMWBSsr@!R&sDa&eVMcwCHq1HYgPSvkzADtzji^L2a<9wg&*4K_8gwYBP-O%pK-)sj(R zG8ub{RGF)yI@VMarYEPEjI!WGJhrc)?#Y`x;grRBD-pLK8xgqu^G#D)F0sy+f1hpa zlD+iI5b3o7M9RRZH|;9d`*3~bddaWlXrDaUL-ILctTs_u>U{q5zvl#EC*dV_Puysy z?>&9raJ6XdFsc^NuL!LYtYVWDDw(`>lJwbJF z6l2ag56_4B*Zma#G0`QRfFo7mAsu!?KSHh;sC0hsk4(N&E+b39Br#tP<2-)sSXt4b zRS`9fn~(N=t2uP=YLE7kAQioKHJqi|_S!t(Usd>>@}XonqvOK8>(ZeQNLBVUD4N6tH*g@OUX25a71|r;xEho!~Xl13#q6g*#0?7pK4eQt*j%rD-*&1XJg^a~!?6=jf7IByZjdtKsJH$VF|!n|2)MA9h}^~1;e7KJ9o zMQZd&LO4yHt622G<>c}UXRa!EtRecBb&LWXhYeIO>7ZqHw93rMDE>_$6;T~fWx=Hp zIPI9i@#ykZUYh?_i|sydjq??U^XgNRW3n5;09z@3*ba8bsKLfkWR;RQOU}U2=rr~Q zFi>`oDzxZwFlHFIaf_ zs;(!4sC=51jfkpGv#$^Ru+bH_IGGrq-O4#Z>};<`MmWp@eappEz!|L zpA&^u6g9~Er{-&4;u^;SR{t@rNYdllx9c5*#4=FdWDF-dv&L|~kRO;4#v|o>`f{Z&QYWIS z(CSc@L_-6QT>4jRv@biw4f~oSlXveTbry;>rynTe51TlMs%gv4%?OVT4Y5~P$-N9s z8fN*v#lVuW+UQC0__2wiV$3AXyP&|FBXb*YhnBiM8qt?zZ>#vPR##L(n|rCFuPx5? zmYOa5veOn@nQZPq_vxj5>O4HT10icc$MAVnw7WZ#qe?jv%2r>Wg%^n3>Z;0tlgwTiN;r6-?l^plwKERCR6HtKXwhM&es>V1IZ@?Ut&ze#5=3ed~ISK zuaFewod5C)JoBozR#_g6lyX_X1XPRha41)^FJkM*Mj@tp8K8#{QyhxeFd-Zp4+nv3^hKfDcFvC zuc~XWRMWLsYbfo~blDU1;x30hcbk>o0ASH$G3sqV@+@CN*RV&hEri1OlmiHx8|M#TDIH84Ux(#yB)s1t9n|r7tfd*Za{AS3 zdhP6}M*JS3dfseox7A8ZjkWzn;9-wJQFGt9dD&mV4y>n#IJgRYDrBSsHW& z!lxn|J`MR((0nOeEK$67M;m+|aff#&SssT7Q>Ct#&z!QNk;i<=k|R#}g4I6Ol=zf& zqQ*CIH0a6s3cgN3H#B3+D-Ra`sp-x$&^;|vM;AON`BTXD+tE&y$#}AmV$pKf^Ycni zzwt_C&P%tw*(F>W_U-r~VcuEs2}af%-zT?#7_nJaOTbL8(N4SAdgr82Ig`kyh{u#D zi0dRz4ofQlV#a@qUbTfVN~)cn7aAMxokym2URddrMW{9PesZJMM#mw1jz#nX4xz`z z#s+^o9F9r9jHwrV#zAo*9x2hEQo;N7hwhwevJ>}0~iO-9bl8Q6;rs{1JK+=m%)51ztr*)A@h z2_1*lEGtU_rby!6Sob-Of+tGn;1S#IuHsp)X7_ih_Lr`kaFxgbig+Zj@nqXdGQ^6aZ_ek-e)8%JVv=JzmSJU>2cu-%HHTK%G2%a*)iw- z#K>~Ti(cNsWWHzJTGpw}oYyG_=A3NeDk72Ul~|l6%B)MY-amt1y)Eon&URkY^_+7d z84(;`aq+#{BWyc)uc=TM8q(kJw5CCHjz6PDd$a14W`86P^}oHon#YC5|E*X}NH^pO zu3n#8&F7P$Jq3JWGuA<-%9Gb~^L_uq(801Yk@fPYo!_MQQRdr%3;s7RmV!oXptKQ8?qHABfiW7PS1T%XRk7=5+i2ns zh`0GOUWotRw)Vsn+W#ss&8J|X>#QXrs}V*Fb*NIV>kBD z@O;Dv2-5V73%S}eidf8gD)YGq2}!)ZC*ko!qFuAa{)g7M<)!m*3zbb=o z$H}5+J^lUku^Ah|>H3nC{Rj0v9!#dqS$cMtZCbH$QyZ znxva(m^CL3*|dP80L`qNi}rG|U|`D$MRWF8Eg6-WnMSr{u>Nzulk~aTa|;s79k1UT z{25XHrLjjSDAmK#XKK2q77Awu*QX1O5(kx&vn4nCNH?yXj`RO{#lsPo{yCfNm6FEF zw@-zRIKq0=0lz+M+k8D-2wi1S^N~J`4K%ATmtX6M;O)C`2Q|W6kFe5tv(tQK|3UB8 z#JP|Wy?swolFqhzPlt@(V;BF?4Q*A%a$MR%fb|J*K60`?nB3cE|HjgN!>{4UHJKfy zC74ul`N6E4aMWq)xwDC%KSi#BZnC8}#35%{YFU_?8nB+b z8nHi^ScKMGyCJ+!HCRB1&&X+{Rx|Tr3sn^hbz{i=LS>5?%V28>MBH#!)U zsLQJlWxE*0>Vr3v)n1*PJ7JVtrk?ClI0uJ`($zfC^WjVN*lAOB(rO$$9Ply_^bG2G zfk{7BKP`M#W=$RvG^En@S8DMm!*UumTvTtTo$Z4dX6E7P`uviOFXoJvlB`al1nWG+ zz-+}lWFQdbeWF?~T=bLfCZV|*S%t0`*Dba9dp)K6g?9wMW=JctwY0pIHm{=`YNz}Lx4Gg(u@NzflPf8*^$(0-ul8Pvnaggti-QqTVt+^u( zt!kZ~Y^3OhY|wVSGJ7og)^bh%ZKR4R=%0ki;}umqq?pcIZ&wZ@sdXKuOM*)dR~3^p zrII(vD_qx7;}r@nH+*fDW-mu)Sa;3~m_b?0^HRyQfPutGDt*7&uWHk-KPVvgh3Ge# zIG}Vp-c%5vDCLZ(%zTYB?C0yPciU!&cG!ER5_FgOx7c$Ai-VQO=y8H!{tQ795_l3r z>Q1YTm2;S$TQC9bML$v3y>Zy*ejM`bON@HKBuaGp3yD)9)oS7psFBZin$e6^dEQIK z`Nh>Vnf&+E4J>1|el2g3pRR`vhh?yzn6$cvKr@hXYJHTD+LLcNOs{9==YQy$XU2i! z)*6}Sb@lkR7LVFbwdIc9C+C^zAKV^WJ4P>~@NsaOV<#W~B5;en5i$Q6jb7w^p{r<3 z&$dg`^_fZb=u$~9t!eQQCf~W8$%>nRT^X|%=3vh81L(^B(KjlWgrOOhOC`4G@Wee2 ztqLqNWYJW&BDFsneDaFpJcXu2*5QruaWJlsl76q0RB5#v$K2()zUeHPk{%+=-<*-ra!>?4<6K+1O?pW7EJgk99E38yZR2^xDO&EyZs_w?H%fT8_R^VfXR z^wf!>^zD+`7xc3e$|EDvI>246$#Q)X%k@gX*KrM1*7i?9irGJ?S}MlcT3 z%`_wfgQqVicgXZ&Z!_+B?|Lj$e2Y>s;#kCepqV-pP->2g(`;X5biS~3Zg^)g5H6B4 z^43hl7Q@nz9j=p;f~ZqfAsN5e%SW@9>I3y2BB8MprN83h0)(kPpO_aMY^;9&IpIiy zTJ-wcYd_aV_b)oB%jAeq?PIAu26SdGHL{9J#Ct8fXivJgQaB6T2h%q5`MEXXP~QSr zHCdDj$Y~)kET-?y=Ba$^D#Bt`HSAEo+BAC;wf=Wu{XJBJ=C`&}KfOu}*3Q-4`_|dh zhuyQEtjP|oWySnx7UUm4%P%Ru8#XBJ58HT|!`;70cSyJ$Vn)sDK(f_w0Qq~|BGKiG z*3+*8O>)|!JTZ)u+^Ct%R$mp|#dW?H?@^8e^C)=yGDWUS2a}`Oy^{L%LH~1eJFEbx z9*?AzV$DwVUDC%;loS|feES*ya*BMy8~c~-=gy}=)Xc;}`r1NssCRCDy*#i>I6W2V zFEciB4QP|NN2dMGUvBLo>4%G8Vmg-bkNtqm9u2lW?S%)UC5Uj%B>~Qy$fWo>hpf>R zl|Y{kOcsasa#O0l6v|{v^-$8of1NMT?*E}vRrENH^I-L|(viYNF&C-z!t8M&*{r{| zjf!x4I8&ox6oXE|;8>pVf7N!DQBi&2qaH#^De07uR62f?AR$UOA|WXaf*_!vw16WZ zAt@cw2t$X`E!`p^3eupIfbxHj_ug;!(_QP%@`DO<=FC1j-u>>qpGSC>h5hI;`SOE} zr8%);_k@zA$Oa#7V|)AR&)1|4YNxv+UtkKtH^0kGaL%oFk}=_Mh)D68VBW&QQAYRI zF4It<5wn4_w8wKThNqXOwsGFH=I!wt-`(jf`Q<&WO6i7NQO zL!C1&OwJar-lAx`pvG{kedMRse>jW0+$;wRL%(GNVEyMt=#AKXXl>)hCD+ zevGT}W%2Ld2ID;w%8~p~ZW}Ec%!*5}{THbaUZf$;5D^nO7Va)V2IitEV^w@wZb=Emh0q3YFO_5*wBW7ph`5 zsrs+I_4pZ=yv>B;cRg{Wt$ppRuNVc})TW>AU3mNUfN*kL-_xuc;#b(8XEl^-^5bl@ zSk@Xs+c%SX`Pi?2{USR2;!86a^wX(QYbfngR;&vLvHMkIeerkH4e z;GE#SeP^1)ld`(6Bs|%UMI(3i!((g)k|SNKV=-2e_b$>rjY{OaQuHMq1Tsf*Hd7rN z75VvLVvAzOAEf)&LM5A^Qvg|WQb@$OaMyuE4V|sS8Z?Ey@eO(GMXNfMz8B7`EweQ<;&o-mqnm^}+ zrA6_#6KMtL7Z%~@oa059MU`Y7nEzEB$jedj{e3H=9CLa*|@(Mi{mR@kuhGg^&s!b%bT5YA$X!zRa~O5zEttnStGoOaBRwc{9`-F;@*u^j^o-koq7iuTggIl(}Tzp=c}f``+= z(@r{nOp^V*8N&&M@TU{HI=LUT*^!HWgKZPfPcSg#w8bRLZ7Oqt{Z2TRMhV!q5S+x}#HY}l|;4rxd> z*pJ1nDXA1a^dWOuFylHxLs3&^EgwPh7(@=fdcsxCqFY&YsjpM-Erop%~zK z{_&;BHmgd#q}1YA|!_aG;D2y@dqCoYtuJuPe-x-s=bldC3|kjLY&;2>mBzY)}L+Z`JplIM{~Pt!>;Z{{-YQ}B}KqeA$iPt|mnYS^aF6zz|O zDA)&BQh0kfP4oKJthMXH{OV@x$qForTXd6b!a?}8DYe+|4efzBHiob0FY7v()r@+T zI20C8i$FRW`Zi*|+@dFB+2T?~L>Pr@S46LII2b}F5nyy7y(THi(59Vk(*k!fJ)7Z% zU&xfTu|0RzjiI7M3E1q*l6{UU@Am7=Y&3OV_Z5fG23hU*pSrIfcNFyEck0k4ncdoS z#i$XaHFss75$=rDri`H1*Nb@PxZsoyeaS}?^*KX}?@CNv(YO9+Q(k~4_#Kae{xTn1 zP)}=cGqc{M7mlP#ZymaQP1^jkDSh~JPeQX8l%HzCYGx*^G57w=QaKKE6us=R_5iib zp)6apx%%+4>N;8gWdUKqAn~0UvP?uj@k)Nkww@2oz4u-PBc$zar$3KvI@q{Vw~Ysx!A@Y}{AT#i zZ9kGOy?PdQumw}Irq1EDdlp)=Ddi078TiaueciK49b%hP2+#j+iH?~UGoAhCL?U?a zV9VZZDz%YT>18~go~MZaRKU0`-Q=&*NctC>Kkoxdu2AbsXhAlmU1TUmV(pMciRZ7Y zkSeP^D}78B-kU;Oc9D|Gj3_dVFB+UUcWJBW&Ho9O2?TL=)x#sCiAr*NXB~9#E$t4n zcV>x^oq{W*7r8+f>1&H;Y$O43Zgv<6m*rO_bv|P}>2cdN@wmW|>N+|K1=wFiM3ue9 zV5?pKEmWf@Gdh!>Bu7mBs_J9Xg^LUmTC}QQiu6%hOpVnd#CGSKg4v zkQbAn8Dk~LvkU1QwV(9q{%I@szxwNTC|P!T2k)+OK{9{QxD;7751rGvkJ3xoiz5X* zb%|4EoEQL1=)R!Whe}q^FKzN~BT%#zm5U-*+T8-wnZ4~O%lEljO23HU93CLXsQjhAIEdx zJtr#kZNp9R9qssDu=1p`Mu%X@oV-Pil~cJ#)Pj|siCyrE)wic~k<{6}DK^5p@2@vf zWb4p7x^byHns??lt)z+e-Y{tXRT+Ij99Sk88|?H-S~~VCO_0!0aOaWC&TSkCh_N-m9CjS%uESV5G5otSDWAI;K$_@8cAm(|q&alXBKorSGeor^Hdt zWf?xOk~V3S)78()sSwN*PS#dDU(|=6Wjm`zZpWIE=33Ntnnm5vcWNGv$8*`|#&|~o z>Jzrhyb6Ucxu2(WuFKJLzYXu*j}8Y6ab(#u^qGZCG>)7)F{#3=^syU}^yOhG;jy*( zWS}E5X}tF8t9@Hg&R|rnZRYjMcxxOuQO}^9dC? zv-``}&F}8}oS)I%Q-La7<)QZ1i30yC^;((9Bd8{8wZUetO`_$z5*tGHV4z0&NxNe= z_2$hG`xRw6QRXUI99cb+!%^PqXIZC!6Arpg>C@wE^E!VI4!1mMCAkxB%dMi5#B3G2 zcB~Li)Wsln;>bHh`FVP|=+7~n?(tFxz~@uuFMXH2DeMV*MTy7Bg8K#pMeNi@R9M#| zvFGeXciofjU4~s}8PMNBStnb>3)!=->v%tmXE@#&8t)MUoH5#;;BT ztfr${k7}Mo%%gl}ajKLkluRQIE6GZHSF<45OE+3QJRsG=^W(zo_^(q9q#}>B@U%$e zba7eQp7fPau%2n+xQf#y(K+TPCeCnpHKqY)rV`G(oseo0kn6)aKWjKd35N?aR`+@7 zeltHT`55z%H6@OusLfwdLtTg=NY`9x`vbJ782dc#f!FuA6pjr@4VK!qMZA-nhWHT) z25d-KtoiI}4K^i22Rd&}ses!JhcXd72kbauKzI& z#Y($E*@k?jI!^5D@Svt}7tZ8RihLzrM-e^6AXfgL0+bEl=MlvMoO$hM(zC(67jC;8 zy>kR86d)aS16|^pS(!Dqs}S9>(#!gbI@az)>a}%tF4fK~&&rz6P)6hoR@%SW2HN;! z6Q~JT2Y=-8Hc?r9-J#AIvaw!!^cKz}_HVeGC2rjcwdeP1URZd#QOcXR5#YP=^FKv( znFm6nMS*_D6xmrXbr)UZ0tMQxUn=iTb1zaH*%&?DF~v4l|79(~#=>llpFeDI8wsYz zqz0;Heh+SUz&IIVf3u;G$X}d6viv3a0<5}^eDwDRIq?RMFsqU^awHMX+y9uYc6zfq z8~AXGM7Bn%=c1oIfIM}G)J5rO9|{j^%T@HLBUO;?D;0EsHik*b7xU&L$gc7d4H>KZ z(K?n1TVn45fY{v5Iv?-7@-wS+GP71oLeT~>1po&8gdETG;dotF!CqW@@3}L{ zVS|mnn&^GSOS}{sc(H%ZSljJI5&Z{(HwGQ6sq1IUf1iic*xg+>P|+GJb4X5Pp=cQN z`Nfl_mmclqed;9&qexuvk0m?E2`h5L^!D7ss~#B|FR&g}QZ|8o%M~L5I(U)rhlxL} z+=V1T+NPUnL?Zt0Y4e10rb~d`GX&ZU%sr1!VpH!O#yC-MSo_Lw22Y5+#B7br#*;ZP zHG;uq3%VMEwY(zr+Jd*^#C}d5Khw;-=Ex(1$!TqeX`RL;8tE@gGoTwLL?LZz`#0lC zJ2}=~2cDpD5EHZ_EI6`M^QBd$G1!^z4h^w(5OyL1@hcJf@bXn5hQ=@d;7$GCt@`45 z3WT5C54Uao{%8-5Y3Df5!}(?!})K@Qf^b1@j6IBHV_UL z7nlIOU82b|0{K*-XAInrf?;hhh1h7_?dO|MtsMLeUkxFX zujyR->eLu)&cuJOfjvm|!r+vCSIVVJqvM>-czLcW6al21ty#o>Bb1L9LTg*|NO7f! zphxr6ow{e`T{*n;?fq44r5hswe^dIjgS$GFiDytokY3@%PLO_ky;6GSTl{`Rf!q!K z&@8;j80FF#XMXLYTooODI7{cnf1r1#?cs~FE2clEkY;a>?bYB(J~l5GCV5)O+y08T{n9599o>X;WYA$vdBe7NH!QBxi)$l|f9Bb3eYM*LOKibiWWma$ z)lU{e2w9aff3$SP%12R=aD^ftLZF^RX!a2!y zl_F2R>=42qrG=&z+V#`Jev@(+S(OxH^Eb}mQKhzbioc_bp>nmg$drE&F29T&JWl@W z*1xNqZP%4yMwYDN#yV}^#d)qdq!3dKtLd$o{G3qJ6S^SH4I&Wc-!0T(Xbnwo@);a{ zrnUUkX!{FzPV_W%qIh)r*IP*n$p3X-aI_?U!#VbFSV!3X%MC==YlJG2YQ(ammtm26R7=m#*Wc)}<2`m;Ti)9`7~cZO&7Pg>UYce=hq zf8nR`eaoL5IeODmpQ@pV_lD>jjF`d8TBv6t))x-zO*h@wffV{)EwO={IDq^|S;Oh7 zjmCGzVBW_n*f;-`3;k7<-0^blOmzOJhQW{ABF_o^r>a3P1qq?ai-=d$Ok?LyYv+iF z7yWHdCun)|u0~#Q(XfHuT6V*!Gr12E`x1;4P-64&(>U-SMb45ZqTvntiBWvhtzy_C zL{&Qavjs#h2BCvRs&_TAs?`^$6bP2^dHB}n=AF+U7F&XCKJt3^^wLWd7~-@xvC$K;^>)lKl;>g zUwC?H`<-5j&L>Kd*O}Z^+EkY*LqkT-d5QQ8LP?5(B&X$H68$@BkbQ4@b+i|@e|V-b zGCk^-8610D`8aJZb`>4OR6>(=vnrb`hg*q<%;2Yl@ng9w#oQe{L@Keg$T#g_9D5wq z=vmpf-~ZrrLnbYDhhgQ_8v+&uopAlRXODu4hO@8IjVc&~3q0Xxn+|+w9D_VDf~8xm z7GqhoO!yX4tr4gFSQ3wqenrKuzLnxw*hpWcym_H2R)FdPPA0cq`WPw)TbWWlK;AuC ziB3l~{dO!1v?V1v!%QRmYf@eVQf44&1#!HgG~R z0kb?fICwlW^xSq#5(fw8cvTLzp#e6&6T;ne+i;9#&Iq_Kuh2*0<>cf5(@fFAV$qvk z5nxCVh?Q=8czL}56(*=1$Z2Ts0Yi-WqntwyELI_u1+aQ{cXxf(_XhJ$Dab!v5a-g6 zl9nEso|ae>`tRX9;&lWBFtMDRTxzfntZ&jYFt8?mJf<**4d}yDQ(-{bG5!Moc z$t;Qezo-B7Exz)m_$ldr?$&MC0 z?di9ol{ld0fy0D8h=oN`k`72$Lsv9FSB}LRtKff~(tt6Cnp2Vao z2JBtrR8*mWOv3555CC+rh>1}}Mn)oLT_88UhYi7mI|sl* z$*!)ZD*yObDmFGYcMIwa_%K6N^V+~Kxd@1E0MS?iY;IKUD(ZN{{G2GR7dK54A7yWE z-(vpvCk^T*SW|&V#KI&kBlGHW?Zcd=CPw2@Y7!C>(EGN5l#L`*L1-)EuA(B2X1WZZ z>%#$ENesW3v0oZp>JIy-Gr{zim6bJJ`2aoPL`*{R6;S@D04UV9sVVQ-A$e%~9*Cn0 zKyN@M1cO@C@bEBUG?ki%m6g?X`go$C0AN`n)M*Tc0vbISew6^?4)9iDz&Nf=gZBxW zlv$>wr-vY*Vx{t{PyfUO6`U zg3>)lv>GT^b4lr7J`d_(1E)OMWZhwV-D0e_-4Rk zynyIYPPb}Hqa2ig$dheZ=;Ob5j#0=zxzuvrT@0WilY;}kyqj8Dq=323 z)aK5d+87xg4#3zAWtWzI%KvuT-(L>MZBd7ZUf0bUC_x8k(-snb-w2Z;N`9`5(*lS# zzC)k|vjV>l0A3)2&TyL%wzIQ?7LZw1hOmi^8of$8g$@o5XqlKoGcq#vyE38DgR3=& zh2V~sR`=0|qZ@0-@Srmb3J4II7LbNeD1cwdq88!M3ZlD(5j7O#dP!eyli?y=reifd zRQa36#wntoFmN$&eaJ)c0=~~>dkOp1W6z;cvXA)`rxYJ_LuBEx{D;cQ(e>x zHSe=bjB0@o$=Cn&1fsC2ni@86Zl?bCP#g`yR5EF=O%w_SL?_j$(&FN{{K&4(&Kp9~ za%mDB`85C}rJiD7WQ?DG{Vzz||4DG^QoQZaO95?WF4ySDNU_tKGJ=8ukc~sNfZt$1 zRb_K)s{)W)K2M)!!w?C=LGkX~sg0P_)QeDbUmCqrKXJN0denv}1AA9yQuDVraljgH<00`mIC282TIZ9maN(&qW-J<;U|jyp&P z0?C;cK(dn2(Gkj%?e6%Wo6O$7f1e~$8HbdV6jXry&YNpXORS}v9>B~d?5=_^5VRvN zj7ycRtk^)io-D|kO*0>V-UseO7^(c){($p-8sN47!M%QX&*ZTkTSZ01dkjVqdeL!5 zF(7W{KEn&fdi?k?YCvu`+P{$nxP%~5ggV!fJt>pSFQPD1c_6xt&C4Oy*PE26H$7y)sAahet=P4mk^pid2gzsO{Ft zpiAtR&(cO(H8gjyHi4Y&F4WD01Zq@5p5)gsKahhIV_uq>nZaWZgpnNz^((&IaiGSY zsF;`~bn~DlFjRZ-<;xd<@F_s}cm-}=JbJk#c}?WHah1JsL=XfCB__3l&Yy>e$$*C$ z0ybDM6yv}Jp%2LrB_A6b!+|Eza#ExWK|H8KVYGjpZor?I)6hWQGVSbk_wHTvF9(9M;m^ zjSuz(a3^Q%k`|QCcvzGuae+ywy1Kfcq@)9$Z|*bb;)XX44CQtKDh8hWtinRVt*tHU zKYAV3&Uq7#SSSz~KsTSZKRrKxKehZ?Vt<9x6h90F5K=8cv+M-(IH1lYo!lj)q}YUn zbR3DKWgXZ)$frbd-~uxL$8SKy20++jyly5e`-CN71#Zk}z>2J!J&uDfC@5$ksyfuC z#JIEzZ0Ys~v=#2>`dub*Uz{3-1mEm!`oNe@5!DEIWhBK35g-j1T3c&eK65rj(Z;2v zrOhPy$p}3MC;i{Q&!Kh5?$tjKPM+Y1xdnRLmX;P2RIDVZi-~>lah!ligNceSeT9)W zH>F`5r6Y@C~eBum~RDAGmk(wC#Ml3BV%q!lR9VI zUma*)@IeZkaWneCQt1#_KnrzSALkh#A7=sW5u|sK0TKP@dS z(qo|Bi-tkDJovV=6Ad`ps@hs;AamED%#0$?Xbg8Ab!xqoq@;$Ai#wz6n?(Ju6_4r} z;qBDcZ}*npCX1K*8xILmXliOgU&O(0)(`??Dd0-2&LHBUNbruna#42P^GM|ynZ`Fr zmd2lKJg~F#x68l}4^OX_Gz+1npumxqmM+le1;{g07RartitsU?xA+6b+SA+H8t}+~ zsx6-xS8To?4KpkaNxX{sy9x?H<1`P%0bpwh?z-b|aas@@1^{~)7cismxgVssGD3R* zIV~2HXJ236d#g^OLQyUj77OJulYjN#4b%e|k)hroA^Pk7?{Nt$sB?1?@5&EsUq5sw zZl=AG7zA8?3y7;-WFLZXNMs=1Xtr!@EjO0lspA+R_9LG^J3WrD5_+Dj&bf88zaOHU zlkBCH1f*=3uq^|a8VRZ4(Sa{ctkj8|{D#)b{;UN=_`2O*?q0pnPYMYOTUCp`D=xl> zdJhpL+W1pc6p2G}eT30x0Zsu3flAZI78ar*&IOn7Y6S3u($bg?w>~3d)~l$fuYgxp zc5>P%>D=>CG)h>3ZY1XTr^DGLefK61!P!vmx;+_1aIm97iYuH#|9MBcMZAyLOZgmC|vr%W(y?PU4%_UGrP3yP(NCe5yZP@ebu1tF4`*I~#-aWeAeJ1d@}xbIDGbfD1CgRFsE6HP zR3oFN#)Ib$todbl4w%c`*UFo)eSLkQzKl;zVUVgDzPP*`JUpz8dYy8H7BB>@cj6(eh7V6pzKE7RA=qj9MFR1l9c36q)z8nCuOQC= z9GZBz@;70=3rDKumXrQ9raWzKz#x|G}ETaWJv_MZ3(*Lci zqhk?5Q6ToyxIxJ2;0tI}&}N52;^m{^&eG=QEANG8G{8~r0=>MBp&?SufgFsw3Dx%b z9@=~nSp6Uii0?BEsBlP?``xPr^SY*czVi^7E`sP?oA-_G*Q?yz_R8)s5yeJDG2b8x zz^FqNvv-zxot74vmBorw))u23^xida9gK}p>@*)Sm)&nh;P(K9R+$Ch_DeWZjr6gG zLmFCIw_$QiPfrhXIvg%8E*^)kTU(KU(w+iR`{niZ^#Rq`)uD`NpaZaoi+hPP`zj9! z8hCkmQSh^FLS=`j9Z3T{P}8eVL^PYT3&2Z8R>I{3YU2}dL^aD3b{HFZ?T=YCq1 zzSPJ@fDHt7K|w(jL}DP^oY}|FGcyByKa_<4lAUQkd0)fz&@{ph3X|VqG6$1w@G}zl|M$ArnhO)_f3FxS^_2g||K5{R8y{ax Ti=}#kf|trIO{Fpgi=h7jm$!DQ literal 0 HcmV?d00001 diff --git a/docs/interacting-with-daemons.md b/docs/interacting-with-daemons.md deleted file mode 100644 index 923612a6..00000000 --- a/docs/interacting-with-daemons.md +++ /dev/null @@ -1,67 +0,0 @@ -# Interacting with daemons - -Before proceeding, make sure you have installed the required binaries, configured and -started both EOTS and the BTC validator daemon. - -- [Starting the EOTS daemon](./eotsd/startup-guide.md) -- [Starting the BTC validator daemon](./vald/startup-guide.md) - -The following guide will show how to interact with the daemons to create a BTC -validator and register it to Babylon. - -### 1. Creating a BTC validator - -A BTC Validator named `my_validator` can be created in the internal -storage ([bolt db](https://github.com/etcd-io/bbolt)) -through the `valcli daemon create-validator` command. This validator is associated -with a BTC public key, serving as its unique identifier, and a Babylon account to -which staking rewards will be directed. - -```bash -$ valcli daemon create-validator --key-name my-validator --chain-id chain-test ---passphrase mypassphrase -{ - "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" -} -``` - -### 2. Registering a validator to Babylon - -The BTC validator can be registered with Babylon through the `register-validator` -command. The output contains the hash of the validator registration Babylon -transaction. - -```bash -$ valcli daemon register-validator --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba -{ - "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" -} -``` - -### 3. Querying the validators managed by the daemon - -The BTC validators that are managed by the daemon can be listed through the -`valcli daemon list-validators` command. The `status` field can receive the following -values: - -- `1`: The Validator is active and has received no delegations yet -- `2`: The Validator is active and has staked BTC tokens -- `3`: The Validator is inactive (i.e. had staked BTC tokens in the past but not - anymore OR has been slashed) - The `last_committed_height` field is the Babylon height up to which the Validator - has committed sufficient EOTS randomness - -```bash -$ valcli daemon list-validators -{ - "validators": [ - ... - { - "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", - "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", - "last_committed_height": 265, - "status": 1 - } - ] -} -``` diff --git a/docs/vald/vald-config.md b/docs/vald/vald-config.md deleted file mode 100644 index cb47f3c4..00000000 --- a/docs/vald/vald-config.md +++ /dev/null @@ -1,80 +0,0 @@ -## Prerequisites - -#### Create a Babylon keyring with funds - -The `vald` daemon requires a keyring with loaded funds to pay for the transactions. -These transactions include randomness commits and vote submissions. Follow this -guide [Getting Testnet Tokens](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds) -to create a keyring and request funds. - -## Validator daemon (`vald`) configuration - -The `vald` tools serves as a control plane for the Validator Daemon. -Below, instructions are provided for configuring the daemons. - -The `vald init` command initializes a home directory for the BTC -validator daemon. This directory is created in the default home location or in a -location specified by the `--home` flag. - -```bash -$ vald init --home /path/to/vald-home/ -``` - -After initialization, the home directory will have the following structure - -```bash -$ ls /path/to/vald-home/ - ├── vald.conf # Vald-specific configuration file. - ├── logs # Vald logs -``` - -If the `--home` flag is not specified, then the default home directory -will be used. For different operating systems, those are: - -- **MacOS** `~/Library/Application Support/Vald` -- **Linux** `~/.Vald` -- **Windows** `C:\Users\\AppData\Local\Vald` - -Below are some important parameters of the `vald.conf` file. - -**Note:** - -The `Key` parameter in the config below is the name of the key in the keyring to use -for signing transactions. Use the key name you created -in [Create a Babylon keyring with funds](#create-a-babylon-keyring-with-funds) - -```bash -# Address of the EOTS Daemon -EOTSManagerAddress = 127.0.0.1:15813 - -# Babylon specific parameters - -# Chain id of the chain (Babylon) -ChainID = chain-test - -# Address of the chain's RPC server (Babylon) -RPCAddr = http://localhost:26657 - -# Address of the chain's GRPC server (Babylon) -GRPCAddr = https://localhost:9090 - -# Name of the key in the keyring to use for signing transactions -Key = node0 - -# Type of keyring to use, -# supported backends - (os|file|kwallet|pass|test|memory) -# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring -KeyringBackend = test - -# Directory to store validator keys in -KeyDirectory = /Users//Library/Application Support/Vald/data -``` - -To change the babylon rpc/grpc address, you can set - -```bash -RPCAddr = https://rpc.devnet.babylonchain.io:443 -GRPCAddr = https://grpc.devnet.babylonchain.io:443 -``` - -To see the complete list of configuration options, check the `vald.conf` file. diff --git a/docs/vald/vald-startup-guide.md b/docs/vald/vald-startup-guide.md deleted file mode 100644 index b8069f23..00000000 --- a/docs/vald/vald-startup-guide.md +++ /dev/null @@ -1,36 +0,0 @@ -## Prerequisites - -1. **Install Binaries:** - Follow the instructions in - the [installation section](../../README.md#2-installation) to install the required - binaries. - -2. **Validator Daemon Configuration:** - Follow the instructions in the [Validator Daemon Configuration](vald-config.md) - guide to configure the validator daemon. - -## Starting the Validator Daemon - -You can start the validator daemon using the following command: - -```bash -$ vald --home /path/to/vald/home -``` - -This will start the RPC server at the address specified in the configuration under -the `RawRPCListeners` field. A custom address can also be specified using -the `--rpclisten` flag. - -```bash -$ vald --rpclisten 'localhost:8082' - -time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" -time="2023-11-26T16:37:00-05:00" level=info msg="Starting ValidatorApp" -time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" -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 on 127.0.0.1:8082" -time="2023-11-26T16:37:00-05:00" level=info msg="BTC Validator 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. From f73962de7088a36329e55708403cd970a8f56773 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Thu, 14 Dec 2023 16:11:46 +0400 Subject: [PATCH 34/66] feat: Covenant handles pre-signed unbonding txs (#180) --- README.md | 1 - clientcontroller/babylon.go | 97 ++++++------------ clientcontroller/interface.go | 15 +-- covenant/covenant.go | 183 +++++++++++----------------------- covenant/covenant_test.go | 27 ++--- go.mod | 3 +- go.sum | 6 +- itest/babylon_node_handler.go | 3 +- itest/e2e_test.go | 62 ------------ itest/test_manager.go | 140 ++++++++++++-------------- testutil/mocks/babylon.go | 76 ++------------ tools/go.mod | 3 +- tools/go.sum | 6 +- types/delegation.go | 5 +- 14 files changed, 184 insertions(+), 443 deletions(-) diff --git a/README.md b/README.md index 2b33473b..9b476acd 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,6 @@ $ make build ``` The above will lead to a build directory having the following structure: - ```bash $ ls build ├── eotsd diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 1ab24866..2708acd5 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -200,7 +200,7 @@ func (bc *BabylonController) CommitPubRandList( ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), StartHeight: startHeight, PubRandList: schnorrPubRandList, - Sig: &bip340Sig, + Sig: bip340Sig, } res, err := bc.reliablySendMsg(msg) @@ -216,40 +216,19 @@ func (bc *BabylonController) CommitPubRandList( func (bc *BabylonController) SubmitCovenantSigs( covPk *btcec.PublicKey, stakingTxHash string, - sigs [][]byte, -) (*types.TxResponse, error) { - - msg := &btcstakingtypes.MsgAddCovenantSig{ - Signer: bc.mustGetTxSigner(), - Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), - StakingTxHash: stakingTxHash, - Sigs: sigs, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil -} - -// SubmitCovenantUnbondingSigs submits the Covenant signatures via a MsgAddCovenantUnbondingSigs to Babylon if the daemon runs in Covenant mode -// it returns tx hash and error -func (bc *BabylonController) SubmitCovenantUnbondingSigs( - covPk *btcec.PublicKey, - stakingTxHash string, + slashingSigs [][]byte, unbondingSig *schnorr.Signature, - slashUnbondingSigs [][]byte, + unbondingSlashingSigs [][]byte, ) (*types.TxResponse, error) { bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) - msg := &btcstakingtypes.MsgAddCovenantUnbondingSigs{ + msg := &btcstakingtypes.MsgAddCovenantSigs{ Signer: bc.mustGetTxSigner(), Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), StakingTxHash: stakingTxHash, - UnbondingTxSig: &bip340UnbondingSig, - SlashingUnbondingTxSigs: slashUnbondingSigs, + SlashingTxSigs: slashingSigs, + UnbondingTxSig: bip340UnbondingSig, + SlashingUnbondingTxSigs: unbondingSlashingSigs, } res, err := bc.reliablySendMsg(msg) @@ -308,10 +287,6 @@ func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*types.Del return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } -func (bc *BabylonController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_UNBONDING, limit) -} - // queryDelegationsWithStatus queries BTC delegations that need a Covenant signature // with the given status (either pending or unbonding) // it is only used when the program is running in Covenant mode @@ -643,6 +618,7 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde CovenantSlashingSigs: covenantSlashingSigs, CovenantUnbondingSigs: covenantUnbondingSigs, UnbondingTime: undel.UnbondingTime, + DelegatorUnbondingSig: undel.DelegatorUnbondingSig, } } @@ -656,23 +632,33 @@ func (bc *BabylonController) CreateBTCDelegation( stakingValue int64, stakingTxInfo *btcctypes.TransactionInfo, slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, + delSlashingSig *bbntypes.BIP340Signature, + unbondingTx []byte, + unbondingTime uint32, + unbondingValue int64, + unbondingSlashingTx *btcstakingtypes.BTCSlashingTx, + delUnbondingSlashingSig *bbntypes.BIP340Signature, ) (*types.TxResponse, error) { valBtcPks := make([]bbntypes.BIP340PubKey, 0, len(valPks)) for _, v := range valPks { valBtcPks = append(valBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) } msg := &btcstakingtypes.MsgCreateBTCDelegation{ - Signer: bc.mustGetTxSigner(), - BabylonPk: delBabylonPk, - BtcPk: delBtcPk, - ValBtcPkList: valBtcPks, - Pop: pop, - StakingTime: stakingTime, - StakingValue: stakingValue, - StakingTx: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delSig, + Signer: bc.mustGetTxSigner(), + BabylonPk: delBabylonPk, + Pop: pop, + BtcPk: delBtcPk, + ValBtcPkList: valBtcPks, + StakingTime: stakingTime, + StakingValue: stakingValue, + StakingTx: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSlashingSig: delSlashingSig, + UnbondingTx: unbondingTx, + UnbondingTime: unbondingTime, + UnbondingValue: unbondingValue, + UnbondingSlashingTx: unbondingSlashingTx, + DelegatorUnbondingSlashingSig: delUnbondingSlashingSig, } res, err := bc.reliablySendMsg(msg) @@ -683,31 +669,6 @@ func (bc *BabylonController) CreateBTCDelegation( return &types.TxResponse{TxHash: res.TxHash}, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) CreateBTCUndelegation( - unbondingTx []byte, - unbondingTime uint32, - unbondingValue int64, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgBTCUndelegate{ - Signer: bc.mustGetTxSigner(), - UnbondingTx: unbondingTx, - UnbondingTime: unbondingTime, - UnbondingValue: unbondingValue, - SlashingTx: slashingTx, - DelegatorSlashingSig: delSig, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - return res, nil -} - // Insert BTC block header using rpc client // Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 4347e1c4..a9e3d2b7 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -79,22 +79,11 @@ type CovenantAPIs interface { // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to // a validator that the delegation is (re-)staked to // it returns tx hash and error - SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) - - // SubmitCovenantUnbondingSigs submits the Covenant signatures for undelegation to the consumer chain - // it returns tx hash and error - SubmitCovenantUnbondingSigs( - covPk *btcec.PublicKey, - stakingTxHash string, - unbondingSig *schnorr.Signature, - slashUnbondingSigs [][]byte, - ) (*types.TxResponse, error) + SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, + sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) // QueryPendingDelegations queries BTC delegations that are in status of pending QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) - - // QueryUnbondingDelegations queries BTC delegations that are in status of unbonding - QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) } func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { diff --git a/covenant/covenant.go b/covenant/covenant.go index 76881428..c842d589 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -107,7 +107,17 @@ func (ce *CovenantEmulator) UpdateParams() error { } // AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon +// TODO: break this function into smaller components func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { + // 0. nil checks + if btcDel == nil { + return nil, fmt.Errorf("empty delegation") + } + + if btcDel.BtcUndelegation == nil { + return nil, fmt.Errorf("empty undelegation") + } + // 1. the quorum is already achieved, skip sending more sigs if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) { return nil, nil @@ -141,91 +151,23 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, fmt.Errorf("invalid txs in the delegation: %w", err) } - // 3. sign covenant sigs - covenantPrivKey, err := ce.getPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - stakingInfo, err := btcstaking.BuildStakingInfo( - btcDel.BtcPk, - btcDel.ValBtcPks, - ce.params.CovenantPks, - ce.params.CovenantQuorum, - btcDel.GetStakingTime(), - btcutil.Amount(btcDel.TotalSat), - &ce.config.BTCNetParams, - ) - if err != nil { - return nil, err - } - - slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() - if err != nil { - return nil, err - } - - covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) - for _, valPk := range btcDel.ValBtcPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) - if err != nil { - return nil, err - } - covenantSig, err := slashingTx.EncSign( - stakingMsgTx, - btcDel.StakingOutputIdx, - slashingPathInfo.GetPkScriptPath(), - covenantPrivKey, - encKey, - ) - if err != nil { - return nil, err - } - covSigs = append(covSigs, covenantSig.MustMarshal()) - } - - // 4. submit covenant sigs - res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs) - - if err != nil { - return nil, err - } - - return &AddCovenantSigResponse{TxHash: res.TxHash}, nil -} - -// AddCovenantUnbondingSignatures adds Covenant signature on the given Bitcoin delegation and submits it to Babylon -func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation) (*AddCovenantSigResponse, error) { - if del == nil { - return nil, fmt.Errorf("btc delegation is nil") - } - - if del.BtcUndelegation == nil { - return nil, fmt.Errorf("delegation does not have an unbonding transaction") - } - - // 1. skip sending sigs if the quorum has already been reached - if del.BtcUndelegation.HasAllSignatures(ce.params.CovenantQuorum) { - return nil, fmt.Errorf("undelegation of the delegation already has required signature from covenant") - } - - // 2. ensure that the unbonding tx and the slashing tx are valid - slashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.SlashingTxHex) + // 3. Check unbonding transaction + unbondingSlashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err } - unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.BtcUndelegation.UnbondingTxHex) + unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.UnbondingTxHex) if err != nil { return nil, err } unbondingInfo, err := btcstaking.BuildUnbondingInfo( - del.BtcPk, - del.ValBtcPks, + btcDel.BtcPk, + btcDel.ValBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, - uint16(del.BtcUndelegation.UnbondingTime), + uint16(btcDel.BtcUndelegation.UnbondingTime), btcutil.Amount(unbondingMsgTx.TxOut[0].Value), &ce.config.BTCNetParams, ) @@ -234,7 +176,7 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation } err = btcstaking.CheckTransactions( - slashingMsgTx, + unbondingSlashingMsgTx, unbondingMsgTx, 0, int64(ce.params.MinSlashingTxFeeSat), @@ -246,37 +188,58 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) } - // 3. Sign unbonding transaction + // 4. sign covenant staking sigs + covenantPrivKey, err := ce.getPrivKey() + if err != nil { + return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + } + stakingInfo, err := btcstaking.BuildStakingInfo( - del.BtcPk, - del.ValBtcPks, + btcDel.BtcPk, + btcDel.ValBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, - del.GetStakingTime(), - btcutil.Amount(del.TotalSat), + btcDel.GetStakingTime(), + btcutil.Amount(btcDel.TotalSat), &ce.config.BTCNetParams, ) if err != nil { return nil, err } - stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() if err != nil { return nil, err } - covenantPrivKey, err := ce.getPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) + + covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) + for _, valPk := range btcDel.ValBtcPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + if err != nil { + return nil, err + } + covenantSig, err := slashingTx.EncSign( + stakingMsgTx, + btcDel.StakingOutputIdx, + slashingPathInfo.GetPkScriptPath(), + covenantPrivKey, + encKey, + ) + if err != nil { + return nil, err + } + covSigs = append(covSigs, covenantSig.MustMarshal()) } - stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(del.StakingTxHex) + + // 5. sign covenant unbonding sig + stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() if err != nil { return nil, err } - covenantUnbondingSignature, err := btcstaking.SignTxWithOneScriptSpendInputStrict( unbondingMsgTx, stakingMsgTx, - del.StakingOutputIdx, + btcDel.StakingOutputIdx, stakingTxUnbondingPathInfo.GetPkScriptPath(), covenantPrivKey, ) @@ -284,8 +247,8 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) } - // 4. Sign slash unbonding transaction - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(del.BtcUndelegation.SlashingTxHex) + // 6. sign covenant unbonding slashing sig + slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err } @@ -295,8 +258,8 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation return nil, err } - covSlashingSigs := make([][]byte, 0, len(del.ValBtcPks)) - for _, valPk := range del.ValBtcPks { + covSlashingSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) + for _, valPk := range btcDel.ValBtcPks { encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) if err != nil { return nil, err @@ -314,21 +277,14 @@ func (ce *CovenantEmulator) AddCovenantUnbondingSignatures(del *types.Delegation covSlashingSigs = append(covSlashingSigs, covenantSig.MustMarshal()) } - // 5. submit covenant sigs - res, err := ce.cc.SubmitCovenantUnbondingSigs( - ce.pk, - stakingMsgTx.TxHash().String(), - covenantUnbondingSignature, - covSlashingSigs, - ) + // 7. submit covenant sigs + res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs, covenantUnbondingSignature, covSlashingSigs) if err != nil { return nil, err } - return &AddCovenantSigResponse{ - TxHash: res.TxHash, - }, nil + return &AddCovenantSigResponse{TxHash: res.TxHash}, nil } func (ce *CovenantEmulator) getPrivKey() (*btcec.PrivateKey, error) { @@ -359,7 +315,7 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { continue } - // 1. Get all pending delegations first, these are more important than the unbonding ones + // 1. Get all pending delegations dels, err := ce.cc.QueryPendingDelegations(limit) if err != nil { ce.logger.Debug("failed to get pending delegations", zap.Error(err)) @@ -381,29 +337,6 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } } - // 2. Get all unbonding delegations - unbondingDels, err := ce.cc.QueryUnbondingDelegations(limit) - if err != nil { - ce.logger.Debug("failed to get unbonding delegations", zap.Error(err)) - continue - } - - if len(unbondingDels) == 0 { - ce.logger.Debug("no unbonding delegations are found") - } - - for _, d := range unbondingDels { - _, err := ce.AddCovenantUnbondingSignatures(d) - if err != nil { - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(d.BtcPk).MarshalHex() - ce.logger.Error( - "failed to submit covenant signatures to the BTC undelegation", - zap.String("del_btc_pk", delPkHex), - zap.Error(err), - ) - } - } - case <-ce.quit: ce.logger.Debug("exiting covenant signature submission loop") return diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index 2899c87a..88b78816 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -11,7 +11,6 @@ import ( bbntypes "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -94,8 +93,7 @@ func FuzzAddCovenantSig(f *testing.F) { StakingOutputIdx: 0, SlashingTxHex: testInfo.SlashingTx.ToHexStr(), } - - // generate covenant sigs + // generate covenant staking sigs slashingSpendInfo, err := testInfo.StakingInfo.SlashingPathSpendInfo() require.NoError(t, err) covSigs := make([][]byte, 0, len(valPks)) @@ -112,18 +110,6 @@ func FuzzAddCovenantSig(f *testing.F) { covSigs = append(covSigs, covenantSig.MustMarshal()) } - // check the sigs are expected - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().SubmitCovenantSigs( - covKeyPair.PublicKey, - testInfo.StakingTx.TxHash().String(), - covSigs, - ). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := ce.AddCovenantSignature(btcDel) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - // generate undelegation unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 unbondingValue := int64(btcDel.TotalSat) - 1000 @@ -160,6 +146,7 @@ func FuzzAddCovenantSig(f *testing.F) { btcDel.BtcUndelegation = undel stakingTxUnbondingPathInfo, err := testInfo.StakingInfo.UnbondingPathSpendInfo() require.NoError(t, err) + // generate covenant unbonding sigs unbondingCovSig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( unbondingTxMsg, testInfo.StakingTx, @@ -168,6 +155,7 @@ func FuzzAddCovenantSig(f *testing.F) { covKeyPair.PrivateKey, ) require.NoError(t, err) + // generate covenant unbonding slashing sigs unbondingCovSlashingSigs := make([][]byte, 0, len(valPks)) for _, valPk := range valPks { encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) @@ -184,17 +172,16 @@ func FuzzAddCovenantSig(f *testing.F) { } // check the sigs are expected - expectedTxHash = testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryUnbondingDelegations(gomock.Any()). - Return([]*types.Delegation{btcDel}, nil).AnyTimes() - mockClientController.EXPECT().SubmitCovenantUnbondingSigs( + expectedTxHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT().SubmitCovenantSigs( covKeyPair.PublicKey, testInfo.StakingTx.TxHash().String(), + covSigs, unbondingCovSig, unbondingCovSlashingSigs, ). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err = ce.AddCovenantUnbondingSignatures(btcDel) + res, err := ce.AddCovenantSignature(btcDel) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) }) diff --git a/go.mod b/go.mod index d22cdd7c..13bfb2bc 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ 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.1+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/emicklei/dot v1.6.0 // indirect @@ -237,7 +238,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 09710a9e..6b5dd0af 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,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-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 h1:Cf1aNeXcSfZczocNxZZ1mM+KU4NDopzaIyi1fSoezxo= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1/go.mod h1:M/tRKH7cc0gpAqCEpHTiaYob/6xoTD4v3A4FZQ3Y3ks= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -460,6 +460,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.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+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= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 52d21905..9b1362d4 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -131,7 +131,8 @@ func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *Babylo "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--covenant-pk=%s", covenantPk.MarshalHex()), + fmt.Sprintf("--covenant-pks=%s", covenantPk.MarshalHex()), + "--covenant-quorum=1", ) var stderr bytes.Buffer diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 6f928e34..fc08cf60 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -178,65 +178,3 @@ func TestFastSync(t *testing.T) { require.NoError(t, err) require.True(t, currentHeight < finalizedHeight+uint64(n)) } - -func TestCovenantLifeCycle(t *testing.T) { - tm, valInsList := StartManagerWithValidator(t, 1) - defer tm.Stop(t) - - valIns := valInsList[0] - - params := tm.GetParams(t) - - valPk := valIns.MustGetBtcPk() - valBtcPk := valIns.GetBtcPkBIP340() - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, []*btcec.PublicKey{valPk}, stakingTime, stakingAmount, params) - dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - del := dels[0] - err := tm.Va.Stop() - require.NoError(t, err) - - tm.InsertBTCUnbonding( - t, - del, - delData.DelegatorPrivKey, - delData.ChangeAddr, - params, - ) - - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) - if err != nil { - return false - } - return len(dels) == 1 && dels[0].BtcUndelegation != nil - }, eventuallyWaitTimeOut, eventuallyPollTime) - - t.Log("undelegation is found, waiting for covenant sigs") - - // after providing validator unbonding signature, we should wait for covenant to provide both valid signatures - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valBtcPk, 1000) - if err != nil { - return false - } - - if len(dels) != 1 { - return false - } - - del := dels[0] - - if del.BtcUndelegation == nil { - return false - } - - if len(del.BtcUndelegation.CovenantSlashingSigs) != 0 && len(del.BtcUndelegation.CovenantUnbondingSigs) != 0 { - return true - } - - return false - }, 1*time.Minute, eventuallyPollTime) - - t.Log("covenant signatures for undelegation are submitted") -} diff --git a/itest/test_manager.go b/itest/test_manager.go index a7a934a3..7c1aaa58 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -267,7 +267,8 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 if err != nil { return false } - return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, bstypes.BTCDelegationStatus_ACTIVE) + return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, + params.CovenantQuorum, bstypes.BTCDelegationStatus_ACTIVE) }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("the delegation is active, validators should start voting") @@ -275,10 +276,10 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 return dels } -func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { +func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32, status bstypes.BTCDelegationStatus) bool { allChecked := true for _, d := range dels { - s := getDelStatus(d, btcHeight, w) + s := getDelStatus(d, btcHeight, w, covenantQuorum) if s != status { allChecked = false } @@ -287,30 +288,27 @@ func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, statu return allChecked } -func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64) bstypes.BTCDelegationStatus { - if del.BtcUndelegation != nil { - if del.BtcUndelegation.CovenantSlashingSigs != nil && - del.BtcUndelegation.CovenantUnbondingSigs != nil { - return bstypes.BTCDelegationStatus_UNBONDED - } - // If we received an undelegation but is still does not have all required signature, - // delegation receives UNBONING status. - // Voting power from this delegation is removed from the total voting power and now we - // are waiting for signatures from validator and covenant for delegation to become expired. - // For now we do not have any unbonding time on the consumer chain, only time lock on BTC chain - // we may consider adding unbonding time on the consumer chain later to avoid situation where - // we can lose to much voting power in to short time. - return bstypes.BTCDelegationStatus_UNBONDING +func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32) bstypes.BTCDelegationStatus { + if del.BtcUndelegation.DelegatorUnbondingSig != nil { + // this means the delegator has signed unbonding signature, and Babylon will consider + // this BTC delegation unbonded directly + return bstypes.BTCDelegationStatus_UNBONDED } - if del.StartHeight <= btcHeight && btcHeight+w <= del.EndHeight { - if del.CovenantSigs != nil { - return bstypes.BTCDelegationStatus_ACTIVE - } else { - return bstypes.BTCDelegationStatus_PENDING - } + if btcHeight < del.StartHeight || btcHeight+w > del.EndHeight { + // staking tx's timelock has not begun, or is less than w BTC + // blocks left, or is expired + return bstypes.BTCDelegationStatus_UNBONDED + } + + // at this point, BTC delegation has an active timelock, and Babylon is not + // aware of unbonding tx with delegator's signature + if del.HasCovenantQuorum(covenantQuorum) { + return bstypes.BTCDelegationStatus_ACTIVE } - return bstypes.BTCDelegationStatus_UNBONDED + + // no covenant quorum yet, pending + return bstypes.BTCDelegationStatus_PENDING } func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { @@ -466,66 +464,23 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P ) require.NoError(t, err) - // submit the BTC delegation to Babylon - _, err = tm.BabylonClient.CreateBTCDelegation( - delBabylonPubKey.(*secp256k1.PubKey), - bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), - validatorPks, - pop, - uint32(stakingTime), - stakingAmount, - txInfo, - testStakingInfo.SlashingTx, - delegatorSig) - require.NoError(t, err) - - t.Log("successfully submitted a BTC delegation") - - return &TestDelegationData{ - DelegatorPrivKey: delBtcPrivKey, - DelegatorKey: delBtcPubKey, - DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), - DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), - ValidatorPks: validatorPks, - StakingTx: testStakingInfo.StakingTx, - SlashingTx: testStakingInfo.SlashingTx, - StakingTxInfo: txInfo, - DelegatorSig: delegatorSig, - SlashingAddr: params.SlashingAddress.String(), - ChangeAddr: changeAddress.String(), - StakingTime: stakingTime, - StakingAmount: stakingAmount, - } -} - -func (tm *TestManager) InsertBTCUnbonding( - t *testing.T, - actualDel *types.Delegation, - delSK *btcec.PrivateKey, - changeAddress string, - params *types.StakingParams, -) { - stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(actualDel.StakingTxHex) - require.NoError(t, err) - stakingTxHash := stakingMsgTx.TxHash() - unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 - unbondingValue := int64(actualDel.TotalSat - 1000) - - r := rand.New(rand.NewSource(time.Now().UnixNano())) + unbondingValue := stakingAmount - 1000 + stakingTxHash := testStakingInfo.StakingTx.TxHash() testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( r, t, btcNetworkParams, - delSK, - actualDel.ValBtcPks, + delBtcPrivKey, + validatorPks, params.CovenantPks, params.CovenantQuorum, wire.NewOutPoint(&stakingTxHash, 0), unbondingTime, unbondingValue, - params.SlashingAddress.String(), changeAddress, + params.SlashingAddress.String(), + changeAddress.String(), params.SlashingRate, ) @@ -538,19 +493,48 @@ func (tm *TestManager) InsertBTCUnbonding( unbondingTxMsg, 0, unbondingSlashingPathInfo.GetPkScriptPath(), - delSK, + delBtcPrivKey, ) require.NoError(t, err) serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) require.NoError(t, err) - _, err = tm.BabylonClient.CreateBTCUndelegation( - serializedUnbondingTx, uint32(unbondingTime), unbondingValue, testUnbondingInfo.SlashingTx, unbondingSig, - ) + // submit the BTC delegation to Babylon + _, err = tm.BabylonClient.CreateBTCDelegation( + delBabylonPubKey.(*secp256k1.PubKey), + bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), + validatorPks, + pop, + uint32(stakingTime), + stakingAmount, + txInfo, + testStakingInfo.SlashingTx, + delegatorSig, + serializedUnbondingTx, + uint32(unbondingTime), + unbondingValue, + testUnbondingInfo.SlashingTx, + unbondingSig) require.NoError(t, err) - t.Log("successfully submitted a BTC undelegation") + t.Log("successfully submitted a BTC delegation") + + return &TestDelegationData{ + DelegatorPrivKey: delBtcPrivKey, + DelegatorKey: delBtcPubKey, + DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), + DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), + ValidatorPks: validatorPks, + StakingTx: testStakingInfo.StakingTx, + SlashingTx: testStakingInfo.SlashingTx, + StakingTxInfo: txInfo, + DelegatorSig: delegatorSig, + SlashingAddr: params.SlashingAddress.String(), + ChangeAddr: changeAddress.String(), + StakingTime: stakingTime, + StakingAmount: stakingAmount, + } } func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 7aee9cc3..c98901fe 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -171,21 +171,6 @@ func (mr *MockClientControllerMockRecorder) QueryStakingParams() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryStakingParams", reflect.TypeOf((*MockClientController)(nil).QueryStakingParams)) } -// QueryUnbondingDelegations mocks base method. -func (m *MockClientController) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. -func (mr *MockClientControllerMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondingDelegations), limit) -} - // QueryValidatorSlashed mocks base method. func (m *MockClientController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { m.ctrl.T.Helper() @@ -247,33 +232,18 @@ func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, block } // SubmitCovenantSigs mocks base method. -func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { +func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) -} - -// SubmitCovenantUnbondingSigs mocks base method. -func (m *MockClientController) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) } // SubmitFinalitySig mocks base method. @@ -517,47 +487,17 @@ func (mr *MockCovenantAPIsMockRecorder) QueryPendingDelegations(limit interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryPendingDelegations), limit) } -// QueryUnbondingDelegations mocks base method. -func (m *MockCovenantAPIs) QueryUnbondingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryUnbondingDelegations indicates an expected call of QueryUnbondingDelegations. -func (mr *MockCovenantAPIsMockRecorder) QueryUnbondingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryUnbondingDelegations), limit) -} - // SubmitCovenantSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte) (*types.TxResponse, error) { +func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs) + ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs) -} - -// SubmitCovenantUnbondingSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantUnbondingSigs(covPk *btcec.PublicKey, stakingTxHash string, unbondingSig *schnorr.Signature, slashUnbondingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantUnbondingSigs", covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantUnbondingSigs indicates an expected call of SubmitCovenantUnbondingSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantUnbondingSigs(covPk, stakingTxHash, unbondingSig, slashUnbondingSigs interface{}) *gomock.Call { +func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantUnbondingSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantUnbondingSigs), covPk, stakingTxHash, unbondingSig, slashUnbondingSigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) } diff --git a/tools/go.mod b/tools/go.mod index 51c21d95..9c318e5a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -81,6 +81,7 @@ 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.1+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/emicklei/dot v1.6.0 // indirect @@ -211,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index cf095a22..6b2e2198 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959 h1:DbDrHk6UXI9Og0tnQscfJriTSseyD81DYTALQ9bnO1M= -github.com/babylonchain/babylon-private v0.0.0-20231129064956-8ad04811f959/go.mod h1:hUJ0eyIpD9p9S+weU48es4P0FYDgIo2Nfg39AFiKj8Q= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= +github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= 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= @@ -441,6 +441,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.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+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= diff --git a/types/delegation.go b/types/delegation.go index de53d4cb..92014754 100644 --- a/types/delegation.go +++ b/types/delegation.go @@ -1,6 +1,7 @@ package types import ( + bbn "github.com/babylonchain/babylon/types" "math" "github.com/btcsuite/btcd/btcec/v2" @@ -40,7 +41,7 @@ type Delegation struct { // HasCovenantQuorum returns whether a delegation has sufficient sigs // from Covenant members to make a quorum func (d *Delegation) HasCovenantQuorum(quorum uint32) bool { - return uint32(len(d.CovenantSigs)) >= quorum + return uint32(len(d.CovenantSigs)) >= quorum && d.BtcUndelegation.HasAllSignatures(quorum) } func (d *Delegation) GetStakingTime() uint16 { @@ -74,6 +75,8 @@ type Undelegation struct { // (i.e., SK corresponding to covenant_pk in params) // It must be provided after processing undelagate message by the consumer chain CovenantUnbondingSigs []*CovenantSchnorrSigInfo + // The delegator signature for the unbonding tx + DelegatorUnbondingSig *bbn.BIP340Signature } func (ud *Undelegation) HasCovenantQuorumOnSlashing(quorum uint32) bool { From 5704694751069aa597ff803c20eb93e879e6495d Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Thu, 14 Dec 2023 17:27:34 +0400 Subject: [PATCH 35/66] chore: Rename btc-validator to finality-provider (#179) --- .circleci/config.yml | 6 +- Dockerfile | 22 +- Makefile | 4 +- clientcontroller/babylon.go | 100 +- clientcontroller/interface.go | 32 +- clientcontroller/retry_utils.go | 4 +- covenant/cmd/covd/init.go | 4 +- covenant/cmd/covd/key.go | 4 +- covenant/cmd/covd/start.go | 14 +- covenant/config/config.go | 6 +- covenant/covenant.go | 26 +- covenant/covenant_test.go | 30 +- covenant/service/server.go | 2 +- eotsmanager/client/rpcclient.go | 6 +- eotsmanager/cmd/eotsd/init.go | 4 +- eotsmanager/cmd/eotsd/start.go | 10 +- eotsmanager/config/config.go | 6 +- eotsmanager/eotsmanager.go | 16 +- eotsmanager/eotsstore.go | 20 +- eotsmanager/localmanager.go | 46 +- eotsmanager/localmanager_test.go | 28 +- eotsmanager/proto/eotsmanager.pb.go | 8 +- eotsmanager/proto/eotsmanager.proto | 2 +- eotsmanager/service/rpcserver.go | 6 +- eotsmanager/service/server.go | 4 +- eotsmanager/types/errors.go | 2 +- {validator => finality-provider}/Makefile | 0 .../cmd/fpcli}/daemoncmd.go | 170 +- .../cmd/fpcli}/main.go | 16 +- .../cmd/fpd}/flags.go | 2 +- .../cmd/fpd}/init.go | 14 +- .../cmd/fpd}/main.go | 6 +- finality-provider/cmd/fpd/start.go | 89 + .../config/config.go | 36 +- .../config/poller.go | 2 +- .../proto/.clang-format | 0 .../proto/buf.gen.yaml | 0 .../proto/buf.lock | 0 .../proto/buf.yaml | 2 +- finality-provider/proto/finality_providers.go | 45 + .../proto/finality_providers.pb.go | 1574 +++++++++++++++++ .../proto/finality_providers.proto | 119 +- .../proto/finality_providers_grpc.pb.go | 310 ++++ .../proto/scripts/protocgen.sh | 0 finality-provider/service/app.go | 467 +++++ .../service/app_test.go | 46 +- .../service/chain_poller.go | 6 +- finality-provider/service/client/rpcclient.go | 122 ++ .../service/fastsync.go | 24 +- .../service/fastsync_test.go | 22 +- .../service/fp_instance.go | 472 ++--- .../service/fp_instance_test.go | 72 +- finality-provider/service/fp_manager.go | 344 ++++ .../service/fp_manager_test.go | 90 +- finality-provider/service/rpcserver.go | 210 +++ .../service/server.go | 14 +- finality-provider/service/types.go | 200 +++ finality-provider/store/fpstore.go | 210 +++ finality-provider/store/fpstore_test.go | 45 + go.mod | 6 +- go.sum | 8 +- itest/e2e_test.go | 88 +- itest/eotsmanager_handler.go | 6 +- itest/test_manager.go | 134 +- keyring/keyring.go | 4 +- keyring/keyringcontroller.go | 24 +- keyring/keyringcontroller_test.go | 18 +- log/log.go | 2 +- store/bbolt_test.go | 4 +- testutil/datagen.go | 36 +- testutil/mocks/babylon.go | 222 +-- testutil/store.go | 2 +- testutil/utils.go | 4 +- tools/go.mod | 4 +- tools/go.sum | 4 +- tools/tools.go | 2 +- types/delegation.go | 8 +- validator/cmd/vald/start.go | 89 - validator/proto/validators.go | 45 - validator/proto/validators.pb.go | 1559 ---------------- validator/proto/validators_grpc.pb.go | 310 ---- validator/service/app.go | 467 ----- validator/service/client/rpcclient.go | 122 -- validator/service/rpcserver.go | 210 --- validator/service/types.go | 201 --- validator/service/validator_manager.go | 344 ---- validator/store/valstore.go | 210 --- validator/store/valstore_test.go | 45 - version/version.go | 8 +- 89 files changed, 4671 insertions(+), 4656 deletions(-) rename {validator => finality-provider}/Makefile (100%) rename {validator/cmd/valcli => finality-provider/cmd/fpcli}/daemoncmd.go (53%) rename {validator/cmd/valcli => finality-provider/cmd/fpcli}/main.go (75%) rename {validator/cmd/vald => finality-provider/cmd/fpd}/flags.go (76%) rename {validator/cmd/vald => finality-provider/cmd/fpd}/init.go (69%) rename {validator/cmd/vald => finality-provider/cmd/fpd}/main.go (67%) create mode 100644 finality-provider/cmd/fpd/start.go rename {validator => finality-provider}/config/config.go (88%) rename {validator => finality-provider}/config/poller.go (98%) rename {validator => finality-provider}/proto/.clang-format (100%) rename {validator => finality-provider}/proto/buf.gen.yaml (100%) rename {validator => finality-provider}/proto/buf.lock (100%) rename {validator => finality-provider}/proto/buf.yaml (92%) create mode 100644 finality-provider/proto/finality_providers.go create mode 100644 finality-provider/proto/finality_providers.pb.go rename validator/proto/validators.proto => finality-provider/proto/finality_providers.proto (59%) create mode 100644 finality-provider/proto/finality_providers_grpc.pb.go rename {validator => finality-provider}/proto/scripts/protocgen.sh (100%) create mode 100644 finality-provider/service/app.go rename {validator => finality-provider}/service/app_test.go (60%) rename {validator => finality-provider}/service/chain_poller.go (97%) create mode 100644 finality-provider/service/client/rpcclient.go rename {validator => finality-provider}/service/fastsync.go (74%) rename {validator => finality-provider}/service/fastsync_test.go (66%) rename validator/service/validator_instance.go => finality-provider/service/fp_instance.go (54%) rename validator/service/validator_instance_test.go => finality-provider/service/fp_instance_test.go (55%) create mode 100644 finality-provider/service/fp_manager.go rename validator/service/validator_manager_test.go => finality-provider/service/fp_manager_test.go (50%) create mode 100644 finality-provider/service/rpcserver.go rename {validator => finality-provider}/service/server.go (83%) create mode 100644 finality-provider/service/types.go create mode 100644 finality-provider/store/fpstore.go create mode 100644 finality-provider/store/fpstore_test.go delete mode 100644 validator/cmd/vald/start.go delete mode 100644 validator/proto/validators.go delete mode 100644 validator/proto/validators.pb.go delete mode 100644 validator/proto/validators_grpc.pb.go delete mode 100644 validator/service/app.go delete mode 100644 validator/service/client/rpcclient.go delete mode 100644 validator/service/rpcserver.go delete mode 100644 validator/service/types.go delete mode 100644 validator/service/validator_manager.go delete mode 100644 validator/store/valstore.go delete mode 100644 validator/store/valstore_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 870bb6f8..f3bb04ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,11 +58,11 @@ jobs: - run: name: Save Docker image to export it to workspace command: | - docker save $(docker image ls --format '{{.Repository}}:{{.Tag}}') > /tmp/btcvalidator.tar + docker save $(docker image ls --format '{{.Repository}}:{{.Tag}}') > /tmp/finality-provider.tar - persist_to_workspace: root: /tmp paths: - - btcvalidator.tar + - finality-provider.tar push_docker: machine: @@ -74,7 +74,7 @@ jobs: - run: name: Load Docker image from workspace command: | - docker load -i /tmp/btcvalidator.tar + docker load -i /tmp/finality-provider.tar - aws-ecr/ecr-login: aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY diff --git a/Dockerfile b/Dockerfile index 5d527bc5..6e0efcde 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,12 +17,12 @@ RUN git config --global url."git@github.com:".insteadOf "https://github.com/" ENV GOPRIVATE=github.com/babylonchain/* # Build -WORKDIR /go/src/github.com/babylonchain/btc-validator +WORKDIR /go/src/github.com/babylonchain/finality-provider # Cache dependencies -COPY go.mod go.sum /go/src/github.com/babylonchain/btc-validator/ +COPY go.mod go.sum /go/src/github.com/babylonchain/finality-provider/ RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download # Copy the rest of the files -COPY ./ /go/src/github.com/babylonchain/btc-validator/ +COPY ./ /go/src/github.com/babylonchain/finality-provider/ # Cosmwasm - Download correct libwasmvm version RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ @@ -41,15 +41,15 @@ RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ # FINAL IMAGE FROM alpine:3.16 AS run -RUN addgroup --gid 1138 -S btcvalidator && adduser --uid 1138 -S btcvalidator -G btcvalidator +RUN addgroup --gid 1138 -S finality-provider && adduser --uid 1138 -S finality-provider -G finality-provider RUN apk add bash curl jq -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/vald /bin/vald -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/valcli /bin/valcli -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/covd /bin/covd -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/eotsd /bin/eotsd +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpd /bin/fpd +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpcli /bin/fpcli +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/covd /bin/covd +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/eotsd /bin/eotsd -WORKDIR /home/btcvalidator -RUN chown -R btcvalidator /home/btcvalidator -USER btcvalidator +WORKDIR /home/finality-provider +RUN chown -R finality-provider /home/finality-provider +USER finality-provider diff --git a/Makefile b/Makefile index 5db0f649..23d9690a 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ + $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/finality-provider -f Dockerfile \ $(shell git rev-parse --show-toplevel) .PHONY: build build-docker @@ -61,7 +61,7 @@ proto-all: proto-gen proto-gen: make -C eotsmanager proto-gen - make -C validator proto-gen + make -C finality-provider proto-gen .PHONY: proto-gen diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 2708acd5..86c5996f 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -4,6 +4,7 @@ import ( "context" "encoding/hex" "fmt" + "github.com/btcsuite/btcd/btcec/v2" "time" "cosmossdk.io/math" @@ -13,7 +14,6 @@ import ( btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" finalitytypes "github.com/babylonchain/babylon/x/finality/types" bbnclient "github.com/babylonchain/rpc-client/client" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -25,8 +25,8 @@ import ( "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/types" ) var _ ClientController = &BabylonController{} @@ -110,7 +110,7 @@ func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) for _, pk := range stakingParamRes.Params.CovenantPks { covPk, err := pk.ToBTCPK() if err != nil { - return nil, fmt.Errorf("invalida covenant public key") + return nil, fmt.Errorf("invalid covenant public key") } covenantPks = append(covenantPks, covPk) } @@ -143,11 +143,11 @@ func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.Relayer ) } -// RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon +// RegisterFinalityProvider registers a finality provider via a MsgCreateFinalityProvider to Babylon // it returns tx hash and error -func (bc *BabylonController) RegisterValidator( +func (bc *BabylonController) RegisterFinalityProvider( chainPk []byte, - valPk *btcec.PublicKey, + fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte, @@ -162,10 +162,10 @@ func (bc *BabylonController) RegisterValidator( return nil, fmt.Errorf("invalid description: %w", err) } - msg := &btcstakingtypes.MsgCreateBTCValidator{ + msg := &btcstakingtypes.MsgCreateFinalityProvider{ Signer: bc.mustGetTxSigner(), BabylonPk: &secp256k1.PubKey{Key: chainPk}, - BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), Pop: &bbnPop, Commission: commission, Description: &sdkDescription, @@ -182,7 +182,7 @@ func (bc *BabylonController) RegisterValidator( // CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon // it returns tx hash and error func (bc *BabylonController) CommitPubRandList( - valPk *btcec.PublicKey, + fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature, @@ -197,7 +197,7 @@ func (bc *BabylonController) CommitPubRandList( msg := &finalitytypes.MsgCommitPubRandList{ Signer: bc.mustGetTxSigner(), - ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), StartHeight: startHeight, PubRandList: schnorrPubRandList, Sig: bip340Sig, @@ -240,10 +240,10 @@ func (bc *BabylonController) SubmitCovenantSigs( } // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon -func (bc *BabylonController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { +func (bc *BabylonController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { msg := &finalitytypes.MsgAddFinalitySig{ Signer: bc.mustGetTxSigner(), - ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), BlockHeight: blockHeight, BlockAppHash: blockHash, FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), @@ -258,7 +258,7 @@ func (bc *BabylonController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeig } // SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon -func (bc *BabylonController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { +func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { if len(blocks) != len(sigs) { return nil, fmt.Errorf("the number of blocks %v should match the number of finality signatures %v", len(blocks), len(sigs)) } @@ -267,7 +267,7 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blo for i, b := range blocks { msg := &finalitytypes.MsgAddFinalitySig{ Signer: bc.mustGetTxSigner(), - ValBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(valPk), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), BlockHeight: b.Height, BlockAppHash: b.Hash, FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]), @@ -308,28 +308,28 @@ func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.B return dels, nil } -func (bc *BabylonController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { +func (bc *BabylonController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - valPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(valPk) + fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk) - queryRequest := &btcstakingtypes.QueryBTCValidatorRequest{ValBtcPkHex: valPubKey.MarshalHex()} + queryRequest := &btcstakingtypes.QueryFinalityProviderRequest{FpBtcPkHex: fpPubKey.MarshalHex()} queryClient := btcstakingtypes.NewQueryClient(clientCtx) - res, err := queryClient.BTCValidator(ctx, queryRequest) + res, err := queryClient.FinalityProvider(ctx, queryRequest) if err != nil { - return false, fmt.Errorf("failed to query the validator %s: %v", valPubKey.MarshalHex(), err) + return false, fmt.Errorf("failed to query the finality provider %s: %v", fpPubKey.MarshalHex(), err) } - slashed := res.BtcValidator.SlashedBtcHeight > 0 + slashed := res.FinalityProvider.SlashedBtcHeight > 0 return slashed, nil } func (bc *BabylonController) getNDelegations( - valBtcPk *bbntypes.BIP340PubKey, + fpBtcPk *bbntypes.BIP340PubKey, startKey []byte, n uint64, ) ([]*types.Delegation, []byte, error) { @@ -338,7 +338,7 @@ func (bc *BabylonController) getNDelegations( Limit: n, } - res, err := bc.bbnClient.QueryClient.BTCValidatorDelegations(valBtcPk.MarshalHex(), pagination) + res, err := bc.bbnClient.QueryClient.FinalityProviderDelegations(fpBtcPk.MarshalHex(), pagination) if err != nil { return nil, nil, fmt.Errorf("failed to query BTC delegations: %v", err) @@ -361,8 +361,8 @@ func (bc *BabylonController) getNDelegations( return delegations, nextKey, nil } -func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( - valBtcPk *bbntypes.BIP340PubKey, +func (bc *BabylonController) getNFinalityProviderDelegationsMatchingCriteria( + fpBtcPk *bbntypes.BIP340PubKey, n uint64, match func(*types.Delegation) bool, ) ([]*types.Delegation, error) { @@ -371,7 +371,7 @@ func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( var startKey []byte for { - dels, nextKey, err := bc.getNDelegations(valBtcPk, startKey, uint64(batchSize)) + dels, nextKey, err := bc.getNDelegations(fpBtcPk, startKey, uint64(batchSize)) if err != nil { return nil, err } @@ -397,10 +397,10 @@ func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( } } -// QueryValidatorVotingPower queries the voting power of the validator at a given height -func (bc *BabylonController) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { - res, err := bc.bbnClient.QueryClient.BTCValidatorPowerAtHeight( - bbntypes.NewBIP340PubKeyFromBTCPK(valPk).MarshalHex(), +// QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height +func (bc *BabylonController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { + res, err := bc.bbnClient.QueryClient.FinalityProviderPowerAtHeight( + bbntypes.NewBIP340PubKeyFromBTCPK(fpPk).MarshalHex(), blockHeight, ) if err != nil { @@ -554,14 +554,14 @@ func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation undelegation = ConvertUndelegationType(del.BtcUndelegation) } - valBtcPks := make([]*btcec.PublicKey, 0, len(del.ValBtcPkList)) - for _, val := range del.ValBtcPkList { - valBtcPks = append(valBtcPks, val.MustToBTCPK()) + fpBtcPks := make([]*btcec.PublicKey, 0, len(del.FpBtcPkList)) + for _, fp := range del.FpBtcPkList { + fpBtcPks = append(fpBtcPks, fp.MustToBTCPK()) } return &types.Delegation{ BtcPk: del.BtcPk.MustToBTCPK(), - ValBtcPks: valBtcPks, + FpBtcPks: fpBtcPks, TotalSat: del.TotalSat, StartHeight: del.StartHeight, EndHeight: del.EndHeight, @@ -626,7 +626,7 @@ func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Unde func (bc *BabylonController) CreateBTCDelegation( delBabylonPk *secp256k1.PubKey, delBtcPk *bbntypes.BIP340PubKey, - valPks []*btcec.PublicKey, + fpPks []*btcec.PublicKey, pop *btcstakingtypes.ProofOfPossession, stakingTime uint32, stakingValue int64, @@ -639,16 +639,16 @@ func (bc *BabylonController) CreateBTCDelegation( unbondingSlashingTx *btcstakingtypes.BTCSlashingTx, delUnbondingSlashingSig *bbntypes.BIP340Signature, ) (*types.TxResponse, error) { - valBtcPks := make([]bbntypes.BIP340PubKey, 0, len(valPks)) - for _, v := range valPks { - valBtcPks = append(valBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) + fpBtcPks := make([]bbntypes.BIP340PubKey, 0, len(fpPks)) + for _, v := range fpPks { + fpBtcPks = append(fpBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) } msg := &btcstakingtypes.MsgCreateBTCDelegation{ Signer: bc.mustGetTxSigner(), BabylonPk: delBabylonPk, Pop: pop, BtcPk: delBtcPk, - ValBtcPkList: valBtcPks, + FpBtcPkList: fpBtcPks, StakingTime: stakingTime, StakingValue: stakingValue, StakingTx: stakingTxInfo, @@ -685,10 +685,10 @@ func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderB return res, nil } -// QueryValidators queries BTC validators +// QueryFinalityProvider queries finality providers // Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, error) { - var validators []*btcstakingtypes.BTCValidator +func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.FinalityProvider, error) { + var fps []*btcstakingtypes.FinalityProvider pagination := &sdkquery.PageRequest{ Limit: 100, } @@ -701,14 +701,14 @@ func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, queryClient := btcstakingtypes.NewQueryClient(clientCtx) for { - queryRequest := &btcstakingtypes.QueryBTCValidatorsRequest{ + queryRequest := &btcstakingtypes.QueryFinalityProvidersRequest{ Pagination: pagination, } - res, err := queryClient.BTCValidators(ctx, queryRequest) + res, err := queryClient.FinalityProviders(ctx, queryRequest) if err != nil { - return nil, fmt.Errorf("failed to query BTC validators: %v", err) + return nil, fmt.Errorf("failed to query finality providers: %v", err) } - validators = append(validators, res.BtcValidators...) + fps = append(fps, res.FinalityProviders...) if res.Pagination == nil || res.Pagination.NextKey == nil { break } @@ -716,7 +716,7 @@ func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, pagination.Key = res.Pagination.NextKey } - return validators, nil + return fps, nil } // Currently this is only used for e2e tests, probably does not need to add this into the interface @@ -738,9 +738,9 @@ func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo } // Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*types.Delegation, error) { - return bc.getNValidatorDelegationsMatchingCriteria( - valBtcPk, +func (bc *BabylonController) QueryFinalityProviderDelegations(fpBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*types.Delegation, error) { + return bc.getNFinalityProviderDelegationsMatchingCriteria( + fpBtcPk, max, // fitlering function which always returns true as we want all delegations func(*types.Delegation) bool { return true }, diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index a9e3d2b7..a51c7d53 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -9,8 +9,8 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/types" ) const ( @@ -18,7 +18,7 @@ const ( ) type ClientController interface { - ValidatorAPIs + FinalityProviderAPIs CovenantAPIs @@ -27,13 +27,13 @@ type ClientController interface { Close() error } -// ValidatorAPIs contains interfaces needed when the program is running in the validator mode -type ValidatorAPIs interface { - // RegisterValidator registers a BTC validator to the consumer chain +// FinalityProviderAPIs contains interfaces needed when the program is running in the finality provider mode +type FinalityProviderAPIs interface { + // RegisterFinalityProvider registers a finality provider to the consumer chain // it returns tx hash and error - RegisterValidator( + RegisterFinalityProvider( chainPk []byte, - valPk *btcec.PublicKey, + fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte, @@ -41,21 +41,21 @@ type ValidatorAPIs interface { // CommitPubRandList commits a list of EOTS public randomness the consumer chain // it returns tx hash and error - CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) + CommitPubRandList(fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) // SubmitFinalitySig submits the finality signature to the consumer chain - SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) + SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) // SubmitBatchFinalitySigs submits a batch of finality signatures to the consumer chain - SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) + SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) // Note: the following queries are only for PoC - // QueryValidatorVotingPower queries the voting power of the validator at a given height - QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) + // QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height + QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) - // QueryValidatorSlashed queries if the validator is slashed - QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) + // QueryFinalityProviderSlashed queries if the finality provider is slashed + QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) // QueryLatestFinalizedBlocks returns the latest finalized blocks QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) @@ -77,7 +77,7 @@ type ValidatorAPIs interface { // CovenantAPIs contains interfaces needed when the program is running in the covenant mode type CovenantAPIs interface { // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to - // a validator that the delegation is (re-)staked to + // a finality provider that the delegation is (re-)staked to // it returns tx hash and error SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) diff --git a/clientcontroller/retry_utils.go b/clientcontroller/retry_utils.go index d84721b8..486bf5e6 100644 --- a/clientcontroller/retry_utils.go +++ b/clientcontroller/retry_utils.go @@ -9,7 +9,7 @@ import ( ) // these errors are considered unrecoverable because these indicate -// something critical in the validator program or the consumer chain +// something critical in the finality provider program or the consumer chain var unrecoverableErrors = []*sdkErr.Error{ finalitytypes.ErrBlockNotFound, finalitytypes.ErrInvalidFinalitySig, @@ -18,7 +18,7 @@ var unrecoverableErrors = []*sdkErr.Error{ finalitytypes.ErrNoPubRandYet, finalitytypes.ErrPubRandNotFound, finalitytypes.ErrTooFewPubRand, - btcstakingtypes.ErrBTCValAlreadySlashed, + btcstakingtypes.ErrFpAlreadySlashed, } // IsUnrecoverable returns true when the error is in the unrecoverableErrors list diff --git a/covenant/cmd/covd/init.go b/covenant/cmd/covd/init.go index b28dfebb..830a95b0 100644 --- a/covenant/cmd/covd/init.go +++ b/covenant/cmd/covd/init.go @@ -2,8 +2,8 @@ package main import ( "fmt" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/util" + covcfg "github.com/babylonchain/finality-provider/covenant/config" + "github.com/babylonchain/finality-provider/util" "github.com/jessevdk/go-flags" "github.com/urfave/cli" "path/filepath" diff --git a/covenant/cmd/covd/key.go b/covenant/cmd/covd/key.go index 46573398..baefe391 100644 --- a/covenant/cmd/covd/key.go +++ b/covenant/cmd/covd/key.go @@ -4,8 +4,8 @@ import ( "encoding/json" "fmt" "github.com/babylonchain/babylon/types" - "github.com/babylonchain/btc-validator/covenant" - covcfg "github.com/babylonchain/btc-validator/covenant/config" + "github.com/babylonchain/finality-provider/covenant" + covcfg "github.com/babylonchain/finality-provider/covenant/config" "github.com/urfave/cli" ) diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go index afe479bf..31e8e577 100644 --- a/covenant/cmd/covd/start.go +++ b/covenant/cmd/covd/start.go @@ -2,18 +2,18 @@ package main import ( "fmt" - "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/log" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" "path/filepath" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/covenant" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - covsrv "github.com/babylonchain/btc-validator/covenant/service" + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/covenant" + covcfg "github.com/babylonchain/finality-provider/covenant/config" + covsrv "github.com/babylonchain/finality-provider/covenant/service" ) var startCommand = cli.Command{ diff --git a/covenant/config/config.go b/covenant/config/config.go index 42e7dbe9..b918e158 100644 --- a/covenant/config/config.go +++ b/covenant/config/config.go @@ -2,7 +2,7 @@ package config import ( "fmt" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/util" "path/filepath" "time" @@ -10,7 +10,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/finality-provider/config" ) const ( @@ -27,7 +27,7 @@ const ( var ( // DefaultCovenantDir specifies the default home directory for the covenant: // C:\Users\\AppData\Local\ on Windows - // ~/.vald on Linux + // ~/.covd on Linux // ~/Library/Application Support/Covd on MacOS DefaultCovenantDir = btcutil.AppDataDir("covd", false) diff --git a/covenant/covenant.go b/covenant/covenant.go index c842d589..cfee5f6c 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -2,25 +2,25 @@ package covenant import ( "fmt" + "github.com/avast/retry-go/v4" + "github.com/btcsuite/btcd/btcec/v2" "strings" "sync" "time" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/keyring" + "github.com/babylonchain/finality-provider/keyring" - "github.com/avast/retry-go/v4" "github.com/babylonchain/babylon/btcstaking" asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" - "github.com/babylonchain/btc-validator/clientcontroller" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/clientcontroller" + covcfg "github.com/babylonchain/finality-provider/covenant/config" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -164,7 +164,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add unbondingInfo, err := btcstaking.BuildUnbondingInfo( btcDel.BtcPk, - btcDel.ValBtcPks, + btcDel.FpBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, uint16(btcDel.BtcUndelegation.UnbondingTime), @@ -196,7 +196,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add stakingInfo, err := btcstaking.BuildStakingInfo( btcDel.BtcPk, - btcDel.ValBtcPks, + btcDel.FpBtcPks, ce.params.CovenantPks, ce.params.CovenantQuorum, btcDel.GetStakingTime(), @@ -212,8 +212,8 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, err } - covSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) - for _, valPk := range btcDel.ValBtcPks { + covSigs := make([][]byte, 0, len(btcDel.FpBtcPks)) + for _, valPk := range btcDel.FpBtcPks { encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) if err != nil { return nil, err @@ -258,9 +258,9 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, err } - covSlashingSigs := make([][]byte, 0, len(btcDel.ValBtcPks)) - for _, valPk := range btcDel.ValBtcPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + covSlashingSigs := make([][]byte, 0, len(btcDel.FpBtcPks)) + for _, fpPk := range btcDel.FpBtcPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) if err != nil { return nil, err } diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go index 88b78816..9a5f954a 100644 --- a/covenant/covenant_test.go +++ b/covenant/covenant_test.go @@ -14,10 +14,10 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/covenant" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/covenant" + covcfg "github.com/babylonchain/finality-provider/covenant/config" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" ) const ( @@ -64,14 +64,14 @@ func FuzzAddCovenantSig(f *testing.F) { require.NoError(t, err) stakingTimeBlocks := uint16(5) stakingValue := int64(2 * 10e8) - valNum := datagen.RandomInt(r, 5) + 1 - valPks := testutil.GenBtcPublicKeys(r, t, int(valNum)) + fpNum := datagen.RandomInt(r, 5) + 1 + fpPks := testutil.GenBtcPublicKeys(r, t, int(fpNum)) testInfo := datagen.GenBTCStakingSlashingInfo( r, t, net, delSK, - valPks, + fpPks, params.CovenantPks, params.CovenantQuorum, stakingTimeBlocks, @@ -85,7 +85,7 @@ func FuzzAddCovenantSig(f *testing.F) { startHeight := datagen.RandomInt(r, 1000) + 100 btcDel := &types.Delegation{ BtcPk: delPK, - ValBtcPks: valPks, + FpBtcPks: fpPks, StartHeight: startHeight, // not relevant here EndHeight: startHeight + uint64(stakingTimeBlocks), TotalSat: uint64(stakingValue), @@ -96,9 +96,9 @@ func FuzzAddCovenantSig(f *testing.F) { // generate covenant staking sigs slashingSpendInfo, err := testInfo.StakingInfo.SlashingPathSpendInfo() require.NoError(t, err) - covSigs := make([][]byte, 0, len(valPks)) - for _, valPk := range valPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + covSigs := make([][]byte, 0, len(fpPks)) + for _, fpPk := range fpPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) require.NoError(t, err) covenantSig, err := testInfo.SlashingTx.EncSign( testInfo.StakingTx, @@ -120,7 +120,7 @@ func FuzzAddCovenantSig(f *testing.F) { t, net, delSK, - btcDel.ValBtcPks, + btcDel.FpBtcPks, params.CovenantPks, params.CovenantQuorum, wire.NewOutPoint(&stakingTxHash, 0), @@ -156,9 +156,9 @@ func FuzzAddCovenantSig(f *testing.F) { ) require.NoError(t, err) // generate covenant unbonding slashing sigs - unbondingCovSlashingSigs := make([][]byte, 0, len(valPks)) - for _, valPk := range valPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) + unbondingCovSlashingSigs := make([][]byte, 0, len(fpPks)) + for _, fpPk := range fpPks { + encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) require.NoError(t, err) covenantSig, err := testUnbondingInfo.SlashingTx.EncSign( testUnbondingInfo.UnbondingTx, diff --git a/covenant/service/server.go b/covenant/service/server.go index 36162a8b..a0d283c6 100644 --- a/covenant/service/server.go +++ b/covenant/service/server.go @@ -7,7 +7,7 @@ import ( "github.com/lightningnetwork/lnd/signal" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/covenant" + "github.com/babylonchain/finality-provider/covenant" ) // CovenantServer is the main daemon construct for the covenant emulator. diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index b6caf494..47879a03 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -9,9 +9,9 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/proto" - "github.com/babylonchain/btc-validator/eotsmanager/types" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/proto" + "github.com/babylonchain/finality-provider/eotsmanager/types" ) var _ eotsmanager.EOTSManager = &EOTSManagerGRpcClient{} diff --git a/eotsmanager/cmd/eotsd/init.go b/eotsmanager/cmd/eotsd/init.go index 153397ef..757083c6 100644 --- a/eotsmanager/cmd/eotsd/init.go +++ b/eotsmanager/cmd/eotsd/init.go @@ -2,8 +2,8 @@ package main import ( "fmt" - eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/util" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/util" "github.com/jessevdk/go-flags" "github.com/urfave/cli" "path/filepath" diff --git a/eotsmanager/cmd/eotsd/start.go b/eotsmanager/cmd/eotsd/start.go index 055deab0..702f571f 100644 --- a/eotsmanager/cmd/eotsd/start.go +++ b/eotsmanager/cmd/eotsd/start.go @@ -2,11 +2,11 @@ package main import ( "fmt" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/config" - eotsservice "github.com/babylonchain/btc-validator/eotsmanager/service" - "github.com/babylonchain/btc-validator/log" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + eotsservice "github.com/babylonchain/finality-provider/eotsmanager/service" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" "path/filepath" diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 89a84ea8..f7ae10aa 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -2,8 +2,8 @@ package config import ( "fmt" - "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/util" "github.com/btcsuite/btcd/btcutil" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/jessevdk/go-flags" @@ -26,7 +26,7 @@ const ( var ( // DefaultEOTSDir the default EOTS home directory: // C:\Users\\AppData\Local\ on Windows - // ~/.vald on Linux + // ~/.eotsd on Linux // ~/Library/Application Support/Eotsd on MacOS DefaultEOTSDir = btcutil.AppDataDir("eotsd", false) diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index c24d4fb2..2e8e1619 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -4,7 +4,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/babylonchain/btc-validator/eotsmanager/types" + "github.com/babylonchain/finality-provider/eotsmanager/types" ) type EOTSManager interface { @@ -15,24 +15,24 @@ type EOTSManager interface { // 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 validator does not exist or a randomness pair has been created before + // 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) - // KeyRecord returns the validator record - // It fails if the validator does not exist or passPhrase is incorrect + // KeyRecord returns the finality provider record + // It fails if the finality provider does not exist or passPhrase is incorrect KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) - // SignEOTS signs an EOTS using the private key of the validator and the corresponding + // SignEOTS signs an EOTS using the private key of the finality provider and the corresponding // secret randomness of the give chain at the given height - // It fails if the validator does not exist or there's no randomness committed to the given height + // It fails if the finality provider does not exist or there's no randomness committed to the given height // or passPhrase is incorrect SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) - // SignSchnorrSig signs a Schnorr signature using the private key of the validator - // It fails if the validator does not exist or the message size is not 32 bytes + // SignSchnorrSig signs a Schnorr signature using the private key of the finality provider + // It fails if the finality provider does not exist or the message size is not 32 bytes // or passPhrase is incorrect SignSchnorrSig(uid []byte, msg []byte, passphrase string) (*schnorr.Signature, error) diff --git a/eotsmanager/eotsstore.go b/eotsmanager/eotsstore.go index 39992aca..40cf8401 100644 --- a/eotsmanager/eotsstore.go +++ b/eotsmanager/eotsstore.go @@ -3,12 +3,12 @@ package eotsmanager import ( "fmt" - "github.com/babylonchain/btc-validator/eotsmanager/types" - "github.com/babylonchain/btc-validator/store" + "github.com/babylonchain/finality-provider/eotsmanager/types" + "github.com/babylonchain/finality-provider/store" ) const ( - validatorKeyNamePrefix = "val-key" + finalityProviderKeyNamePrefix = "fp-key" ) type EOTSStore struct { @@ -32,22 +32,22 @@ func (es *EOTSStore) Close() error { return nil } -func (es *EOTSStore) saveValidatorKey(pk []byte, keyName string) error { - k := getValidatorKeyNameKey(pk) +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.ErrValidatorAlreadyExisted + return types.ErrFinalityProviderAlreadyExisted } return es.s.Put(k, []byte(keyName)) } -func (es *EOTSStore) getValidatorKeyName(pk []byte) (string, error) { - k := getValidatorKeyNameKey(pk) +func (es *EOTSStore) getFinalityProviderKeyName(pk []byte) (string, error) { + k := getFinalityProviderKeyNameKey(pk) v, err := es.s.Get(k) if err != nil { return "", err @@ -56,8 +56,8 @@ func (es *EOTSStore) getValidatorKeyName(pk []byte) (string, error) { return string(v), nil } -func getValidatorKeyNameKey(pk []byte) []byte { - return append([]byte(validatorKeyNamePrefix), pk...) +func getFinalityProviderKeyNameKey(pk []byte) []byte { + return append([]byte(finalityProviderKeyNamePrefix), pk...) } func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index dc9d55bb..4d07a980 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -2,7 +2,7 @@ package eotsmanager import ( "fmt" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/util" "strings" "github.com/babylonchain/babylon/crypto/eots" @@ -14,10 +14,10 @@ import ( "github.com/cosmos/go-bip39" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/codec" - "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/eotsmanager/randgenerator" - eotstypes "github.com/babylonchain/btc-validator/eotsmanager/types" + "github.com/babylonchain/finality-provider/codec" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager/randgenerator" + eotstypes "github.com/babylonchain/finality-provider/eotsmanager/types" ) const ( @@ -77,7 +77,7 @@ 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.ErrValidatorAlreadyExisted + return nil, eotstypes.ErrFinalityProviderAlreadyExisted } keyringAlgos, _ := lm.kr.SupportedAlgorithms() @@ -123,7 +123,7 @@ func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, return nil, fmt.Errorf("unsupported key type in keyring") } - if err := lm.es.saveValidatorKey(eotsPk.MustMarshal(), name); err != nil { + if err := lm.es.saveFinalityProviderKey(eotsPk.MustMarshal(), name); err != nil { return nil, err } @@ -138,14 +138,14 @@ func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, // 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 (valPk, chainID, height) or +// 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(valPk []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { +func (lm *LocalEOTSManager) CreateRandomnessPairList(fpPk []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { prList := make([]*btcec.FieldVal, 0, num) for i := uint32(0); i < num; i++ { height := startHeight + uint64(i) - _, pubRand, err := lm.getRandomnessPair(valPk, chainID, height, passphrase) + _, pubRand, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) if err != nil { return nil, err } @@ -156,13 +156,13 @@ func (lm *LocalEOTSManager) CreateRandomnessPairList(valPk []byte, chainID []byt return prList, nil } -func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { - privRand, _, err := lm.getRandomnessPair(valPk, chainID, height, passphrase) +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) if err != nil { return nil, fmt.Errorf("failed to get private randomness: %w", err) } - privKey, err := lm.getEOTSPrivKey(valPk, passphrase) + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) if err != nil { return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } @@ -170,8 +170,8 @@ func (lm *LocalEOTSManager) SignEOTS(valPk []byte, chainID []byte, msg []byte, h return eots.Sign(privKey, privRand, msg) } -func (lm *LocalEOTSManager) SignSchnorrSig(valPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { - privKey, err := lm.getEOTSPrivKey(valPk, passphrase) +func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) if err != nil { return nil, fmt.Errorf("failed to get EOTS private key: %w", err) } @@ -183,9 +183,9 @@ func (lm *LocalEOTSManager) Close() error { return lm.es.Close() } -// getRandomnessPair returns a randomness pair generated based on the given validator key, chainID and height -func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, height uint64, passphrase string) (*eots.PrivateRand, *eots.PublicRand, error) { - record, err := lm.KeyRecord(valPk, passphrase) +// 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) { + record, err := lm.KeyRecord(fpPk, passphrase) if err != nil { return nil, nil, err } @@ -194,12 +194,12 @@ func (lm *LocalEOTSManager) getRandomnessPair(valPk []byte, chainID []byte, heig } // TODO: we ignore passPhrase in local implementation for now -func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passphrase string) (*eotstypes.KeyRecord, error) { - name, err := lm.es.getValidatorKeyName(valPk) +func (lm *LocalEOTSManager) KeyRecord(fpPk []byte, passphrase string) (*eotstypes.KeyRecord, error) { + name, err := lm.es.getFinalityProviderKeyName(fpPk) if err != nil { return nil, err } - privKey, err := lm.getEOTSPrivKey(valPk, passphrase) + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) if err != nil { return nil, err } @@ -210,8 +210,8 @@ func (lm *LocalEOTSManager) KeyRecord(valPk []byte, passphrase string) (*eotstyp }, nil } -func (lm *LocalEOTSManager) getEOTSPrivKey(valPk []byte, passphrase string) (*btcec.PrivateKey, error) { - keyName, err := lm.es.getValidatorKeyName(valPk) +func (lm *LocalEOTSManager) getEOTSPrivKey(fpPk []byte, passphrase string) (*btcec.PrivateKey, error) { + keyName, err := lm.es.getFinalityProviderKeyName(fpPk) if err != nil { return nil, err } diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go index 24a90fb6..29f5d43f 100644 --- a/eotsmanager/localmanager_test.go +++ b/eotsmanager/localmanager_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/babylonchain/babylon/testutil/datagen" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/types" - "github.com/babylonchain/btc-validator/testutil" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/types" + "github.com/babylonchain/finality-provider/testutil" "github.com/stretchr/testify/require" ) @@ -25,7 +25,7 @@ func FuzzCreateKey(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - valName := testutil.GenRandomHexStr(r, 4) + fpName := testutil.GenRandomHexStr(r, 4) homeDir := filepath.Join(t.TempDir(), "eots-home") eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { @@ -36,19 +36,19 @@ func FuzzCreateKey(f *testing.F) { lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) require.NoError(t, err) - valPk, err := lm.CreateKey(valName, passphrase, hdPath) + fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) require.NoError(t, err) - valRecord, err := lm.KeyRecord(valPk, passphrase) + fpRecord, err := lm.KeyRecord(fpPk, passphrase) require.NoError(t, err) - require.Equal(t, valName, valRecord.Name) + require.Equal(t, fpName, fpRecord.Name) - sig, err := lm.SignSchnorrSig(valPk, datagen.GenRandomByteArray(r, 32), passphrase) + sig, err := lm.SignSchnorrSig(fpPk, datagen.GenRandomByteArray(r, 32), passphrase) require.NoError(t, err) require.NotNil(t, sig) - _, err = lm.CreateKey(valName, passphrase, hdPath) - require.ErrorIs(t, err, types.ErrValidatorAlreadyExisted) + _, err = lm.CreateKey(fpName, passphrase, hdPath) + require.ErrorIs(t, err, types.ErrFinalityProviderAlreadyExisted) }) } @@ -57,7 +57,7 @@ func FuzzCreateRandomnessPairList(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) - valName := testutil.GenRandomHexStr(r, 4) + fpName := testutil.GenRandomHexStr(r, 4) homeDir := filepath.Join(t.TempDir(), "eots-home") eotsCfg := testutil.GenEOTSConfig(r, t) defer func() { @@ -68,18 +68,18 @@ func FuzzCreateRandomnessPairList(f *testing.F) { lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) require.NoError(t, err) - valPk, err := lm.CreateKey(valName, passphrase, hdPath) + fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) require.NoError(t, err) chainID := datagen.GenRandomByteArray(r, 10) startHeight := datagen.RandomInt(r, 100) num := r.Intn(10) + 1 - pubRandList, err := lm.CreateRandomnessPairList(valPk, chainID, startHeight, uint32(num), passphrase) + 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(valPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i), passphrase) + sig, err := lm.SignEOTS(fpPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i), passphrase) require.NoError(t, err) require.NotNil(t, sig) } diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index 7b295d37..844ed8e6 100644 --- a/eotsmanager/proto/eotsmanager.pb.go +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -788,11 +788,11 @@ var file_eotsmanager_proto_rawDesc = []byte{ 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, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, + 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 ( diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto index f85e0347..866a9de0 100644 --- a/eotsmanager/proto/eotsmanager.proto +++ b/eotsmanager/proto/eotsmanager.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package proto; -option go_package = "github.com/babylonchain/btc-validator/eotsmanager/proto"; +option go_package = "github.com/babylonchain/btc-finality-provider/eotsmanager/proto"; service EOTSManager { rpc Ping (PingRequest) returns (PingResponse); diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go index ee7e0fc3..b8cc4990 100644 --- a/eotsmanager/service/rpcserver.go +++ b/eotsmanager/service/rpcserver.go @@ -5,11 +5,11 @@ import ( "google.golang.org/grpc" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/proto" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/proto" ) -// rpcServer is the main RPC server for the BTC-Validator daemon that handles +// rpcServer is the main RPC server for the EOTS daemon that handles // gRPC incoming requests. type rpcServer struct { proto.UnimplementedEOTSManagerServer diff --git a/eotsmanager/service/server.go b/eotsmanager/service/server.go index c475e2c8..f16008c8 100644 --- a/eotsmanager/service/server.go +++ b/eotsmanager/service/server.go @@ -10,8 +10,8 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" ) // Server is the main daemon construct for the EOTS manager server. It handles diff --git a/eotsmanager/types/errors.go b/eotsmanager/types/errors.go index d5419969..2d2879fd 100644 --- a/eotsmanager/types/errors.go +++ b/eotsmanager/types/errors.go @@ -3,5 +3,5 @@ package types import "errors" var ( - ErrValidatorAlreadyExisted = errors.New("the validator has already existed") + ErrFinalityProviderAlreadyExisted = errors.New("the finality provider has already existed") ) diff --git a/validator/Makefile b/finality-provider/Makefile similarity index 100% rename from validator/Makefile rename to finality-provider/Makefile diff --git a/validator/cmd/valcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go similarity index 53% rename from validator/cmd/valcli/daemoncmd.go rename to finality-provider/cmd/fpcli/daemoncmd.go index a1cc6f71..c3a9fdff 100644 --- a/validator/cmd/valcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -11,21 +11,21 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" - valcfg "github.com/babylonchain/btc-validator/validator/config" - dc "github.com/babylonchain/btc-validator/validator/service/client" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + dc "github.com/babylonchain/finality-provider/finality-provider/service/client" ) const ( - valdDaemonAddressFlag = "daemon-address" - keyNameFlag = "key-name" - valBTCPkFlag = "btc-pk" - blockHeightFlag = "height" - appHashFlag = "app-hash" - passphraseFlag = "passphrase" - hdPathFlag = "hd-path" - chainIdFlag = "chain-id" - defaultPassphrase = "" - defaultHdPath = "" + fpdDaemonAddressFlag = "daemon-address" + keyNameFlag = "key-name" + fpBTCPkFlag = "btc-pk" + blockHeightFlag = "height" + appHashFlag = "app-hash" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + defaultPassphrase = "" + defaultHdPath = "" // flags for description monikerFlag = "moniker" @@ -38,8 +38,8 @@ const ( ) var ( - defaultValdDaemonAddress = "127.0.0.1:" + strconv.Itoa(valcfg.DefaultRPCPort) - defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" + defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) + defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" ) var getDaemonInfoCmd = cli.Command{ @@ -48,17 +48,17 @@ var getDaemonInfoCmd = cli.Command{ Usage: "Get information of the running daemon.", Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, }, Action: getInfo, } func getInfo(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - client, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) + daemonAddress := ctx.String(fpdDaemonAddressFlag) + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } @@ -75,19 +75,19 @@ func getInfo(ctx *cli.Context) error { return nil } -var createValDaemonCmd = cli.Command{ - Name: "create-validator", - ShortName: "cv", - Usage: "Create a Bitcoin validator object and save it in database.", +var createFpDaemonCmd = cli.Command{ + Name: "create-finality-provider", + ShortName: "cfp", + Usage: "Create a finality provider object and save it in database.", Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, cli.StringFlag{ Name: keyNameFlag, - Usage: "The unique name of the validator key", + Usage: "The unique name of the finality provider key", Required: true, }, cli.StringFlag{ @@ -107,12 +107,12 @@ var createValDaemonCmd = cli.Command{ }, cli.StringFlag{ Name: commissionRateFlag, - Usage: "The commission rate for the validator, e.g., 0.05", + Usage: "The commission rate for the finality provider, e.g., 0.05", Value: "0.05", }, cli.StringFlag{ Name: monikerFlag, - Usage: "A human-readable name for the validator", + Usage: "A human-readable name for the finality provider", Value: "", }, cli.StringFlag{ @@ -136,11 +136,11 @@ var createValDaemonCmd = cli.Command{ Value: "", }, }, - Action: createValDaemon, + Action: createFpDaemon, } -func createValDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) +func createFpDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) if err != nil { @@ -152,13 +152,13 @@ func createValDaemon(ctx *cli.Context) error { return err } - client, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } defer cleanUp() - info, err := client.CreateValidator( + info, err := client.CreateFinalityProvider( context.Background(), ctx.String(keyNameFlag), ctx.String(chainIdFlag), @@ -190,29 +190,29 @@ func getDescriptionFromContext(ctx *cli.Context) (stakingtypes.Description, erro return description.EnsureLength() } -var lsValDaemonCmd = cli.Command{ - Name: "list-validators", +var lsFpDaemonCmd = cli.Command{ + Name: "list-finality-providers", ShortName: "ls", - Usage: "List validators stored in the database.", + Usage: "List finality providers stored in the database.", Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, }, - Action: lsValDaemon, + Action: lsFpDaemon, } -func lsValDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) +func lsFpDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } defer cleanUp() - resp, err := rpcClient.QueryValidatorList(context.Background()) + resp, err := rpcClient.QueryFinalityProviderList(context.Background()) if err != nil { return err } @@ -222,39 +222,39 @@ func lsValDaemon(ctx *cli.Context) error { return nil } -var valInfoDaemonCmd = cli.Command{ - Name: "validator-info", - ShortName: "vi", - Usage: "Show the information of the validator.", +var fpInfoDaemonCmd = cli.Command{ + Name: "finality-provider-info", + ShortName: "fpi", + Usage: "Show the information of the finality provider.", Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, cli.StringFlag{ - Name: valBTCPkFlag, + Name: fpBTCPkFlag, Usage: "The hex string of the BTC public key", Required: true, }, }, - Action: valInfoDaemon, + Action: fpInfoDaemon, } -func valInfoDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) +func fpInfoDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } defer cleanUp() - valPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(valBTCPkFlag)) + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(fpBTCPkFlag)) if err != nil { return err } - resp, err := rpcClient.QueryValidatorInfo(context.Background(), valPk) + resp, err := rpcClient.QueryFinalityProviderInfo(context.Background(), fpPk) if err != nil { return err } @@ -264,20 +264,20 @@ func valInfoDaemon(ctx *cli.Context) error { return nil } -var registerValDaemonCmd = cli.Command{ - Name: "register-validator", - ShortName: "rv", - Usage: "Register a created Bitcoin validator to Babylon.", - UsageText: fmt.Sprintf("register-validator --%s [key-name]", keyNameFlag), +var registerFpDaemonCmd = cli.Command{ + Name: "register-finality-provider", + ShortName: "rfp", + Usage: "Register a created finality provider to Babylon.", + UsageText: fmt.Sprintf("register-finality-provider --%s [key-name]", keyNameFlag), Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, cli.StringFlag{ - Name: valBTCPkFlag, - Usage: "The hex string of the validator BTC public key", + Name: fpBTCPkFlag, + Usage: "The hex string of the finality provider BTC public key", Required: true, }, cli.StringFlag{ @@ -286,24 +286,24 @@ var registerValDaemonCmd = cli.Command{ Value: defaultPassphrase, }, }, - Action: registerVal, + Action: registerFp, } -func registerVal(ctx *cli.Context) error { - valPkStr := ctx.String(valBTCPkFlag) - valPk, err := bbntypes.NewBIP340PubKeyFromHex(valPkStr) +func registerFp(ctx *cli.Context) error { + fpPkStr := ctx.String(fpBTCPkFlag) + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) if err != nil { return fmt.Errorf("invalid BTC public key: %w", err) } - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } defer cleanUp() - res, err := rpcClient.RegisterValidator(context.Background(), valPk, ctx.String(passphraseFlag)) + res, err := rpcClient.RegisterFinalityProvider(context.Background(), fpPk, ctx.String(passphraseFlag)) if err != nil { return err } @@ -319,15 +319,15 @@ 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", - UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", valBTCPkFlag), + UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", fpBTCPkFlag), Flags: []cli.Flag{ cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, + Name: fpdDaemonAddressFlag, + Usage: "Full address of the finality provider daemon in format tcp://:", + Value: defaultFpdDaemonAddress, }, cli.StringFlag{ - Name: valBTCPkFlag, + Name: fpBTCPkFlag, Usage: "The hex string of the BTC public key", Required: true, }, @@ -346,14 +346,14 @@ var addFinalitySigDaemonCmd = cli.Command{ } func addFinalitySig(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err } defer cleanUp() - valPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(valBTCPkFlag)) + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(fpBTCPkFlag)) if err != nil { return err } @@ -364,7 +364,7 @@ func addFinalitySig(ctx *cli.Context) error { } res, err := rpcClient.AddFinalitySignature( - context.Background(), valPk.MarshalHex(), ctx.Uint64(blockHeightFlag), lch) + context.Background(), fpPk.MarshalHex(), ctx.Uint64(blockHeightFlag), lch) if err != nil { return err } diff --git a/validator/cmd/valcli/main.go b/finality-provider/cmd/fpcli/main.go similarity index 75% rename from validator/cmd/valcli/main.go rename to finality-provider/cmd/fpcli/main.go index e101e79a..906f1d96 100644 --- a/validator/cmd/valcli/main.go +++ b/finality-provider/cmd/fpcli/main.go @@ -3,14 +3,14 @@ package main import ( "encoding/json" "fmt" - "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/finality-provider/config" "os" "github.com/urfave/cli" ) func fatal(err error) { - fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + fmt.Fprintf(os.Stderr, "[fpd] %v\n", err) os.Exit(1) } @@ -31,8 +31,8 @@ const ( func main() { app := cli.NewApp() - app.Name = "valcli" - app.Usage = "Control plane for the Bitcoin Validator Daemon (vald)." + app.Name = "fpcli" + app.Usage = "Control plane for the Finality Provider Daemon (fpd)." app.Flags = []cli.Flag{ cli.StringFlag{ Name: dbTypeFlag, @@ -48,10 +48,10 @@ func main() { app.Commands = append(app.Commands, getDaemonInfoCmd, - createValDaemonCmd, - lsValDaemonCmd, - valInfoDaemonCmd, - registerValDaemonCmd, + createFpDaemonCmd, + lsFpDaemonCmd, + fpInfoDaemonCmd, + registerFpDaemonCmd, addFinalitySigDaemonCmd, ) diff --git a/validator/cmd/vald/flags.go b/finality-provider/cmd/fpd/flags.go similarity index 76% rename from validator/cmd/vald/flags.go rename to finality-provider/cmd/fpd/flags.go index e34735b4..687cfa4e 100644 --- a/validator/cmd/vald/flags.go +++ b/finality-provider/cmd/fpd/flags.go @@ -4,7 +4,7 @@ const ( homeFlag = "home" forceFlag = "force" passphraseFlag = "passphrase" - valPkFlag = "validator-pk" + fpPkFlag = "finality-provider-pk" defaultPassphrase = "" ) diff --git a/validator/cmd/vald/init.go b/finality-provider/cmd/fpd/init.go similarity index 69% rename from validator/cmd/vald/init.go rename to finality-provider/cmd/fpd/init.go index ec8e08c6..99d3cc0b 100644 --- a/validator/cmd/vald/init.go +++ b/finality-provider/cmd/fpd/init.go @@ -2,8 +2,8 @@ package main import ( "fmt" - "github.com/babylonchain/btc-validator/util" - valcfg "github.com/babylonchain/btc-validator/validator/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/util" "github.com/jessevdk/go-flags" "github.com/urfave/cli" "path/filepath" @@ -11,12 +11,12 @@ import ( var initCommand = cli.Command{ Name: "init", - Usage: "Initialize a validator home directory", + Usage: "Initialize a finality-provider home directory", Flags: []cli.Flag{ cli.StringFlag{ Name: homeFlag, Usage: "Path to where the home directory will be initialized", - Value: valcfg.DefaultValdDir, + Value: fpcfg.DefaultFpdDir, }, cli.BoolFlag{ Name: forceFlag, @@ -44,13 +44,13 @@ func initHome(c *cli.Context) error { return err } // Create log directory - logDir := valcfg.LogDir(homePath) + logDir := fpcfg.LogDir(homePath) if err := util.MakeDirectory(logDir); err != nil { return err } - defaultConfig := valcfg.DefaultConfigWithHome(homePath) + defaultConfig := fpcfg.DefaultConfigWithHome(homePath) fileParser := flags.NewParser(&defaultConfig, flags.Default) - return flags.NewIniParser(fileParser).WriteFile(valcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) + return flags.NewIniParser(fileParser).WriteFile(fpcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) } diff --git a/validator/cmd/vald/main.go b/finality-provider/cmd/fpd/main.go similarity index 67% rename from validator/cmd/vald/main.go rename to finality-provider/cmd/fpd/main.go index b2923474..569b0521 100644 --- a/validator/cmd/vald/main.go +++ b/finality-provider/cmd/fpd/main.go @@ -8,14 +8,14 @@ import ( ) func fatal(err error) { - fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) + fmt.Fprintf(os.Stderr, "[btc-finality-provider] %v\n", err) os.Exit(1) } func main() { app := cli.NewApp() - app.Name = "vald" - app.Usage = "BTC Validator Daemon (vald)." + app.Name = "fpd" + app.Usage = "Finality Provider Daemon (fpd)." app.Commands = append(app.Commands, startCommand, initCommand) if err := app.Run(os.Args); err != nil { diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go new file mode 100644 index 00000000..dbc46524 --- /dev/null +++ b/finality-provider/cmd/fpd/start.go @@ -0,0 +1,89 @@ +package main + +import ( + "fmt" + "github.com/babylonchain/babylon/types" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + "path/filepath" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" +) + +var startCommand = cli.Command{ + Name: "start", + Usage: "fpd start", + Description: "Start the finality-provider app. Note that eotsd should be started beforehand", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to decrypt the private key", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: homeFlag, + Usage: "The path to the finality-provider home directory", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: fpPkFlag, + Usage: "The public key of the finality-provider to start", + }, + }, + Action: start, +} + +func start(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) + passphrase := ctx.String(passphraseFlag) + fpPkStr := ctx.String(fpPkFlag) + + cfg, err := fpcfg.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + + logger, err := log.NewRootLoggerWithFile(fpcfg.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to initialize the logger") + } + + fpApp, err := service.NewFinalityProviderAppFromConfig(homePath, cfg, logger) + if err != nil { + return fmt.Errorf("failed to create finality-provider app: %v", err) + } + + // 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) + } + + 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 { + return fmt.Errorf("failed to start the finality-provider instance %s: %w", fpPkStr, 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() +} diff --git a/validator/config/config.go b/finality-provider/config/config.go similarity index 88% rename from validator/config/config.go rename to finality-provider/config/config.go index 8d695be1..b666703e 100644 --- a/validator/config/config.go +++ b/finality-provider/config/config.go @@ -1,4 +1,4 @@ -package valcfg +package fpcfg import ( "fmt" @@ -7,25 +7,25 @@ import ( "strconv" "time" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/util" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/jessevdk/go-flags" - "github.com/babylonchain/btc-validator/config" + "github.com/babylonchain/finality-provider/config" - eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" ) const ( defaultChainName = "babylon" defaultLogLevel = "info" defaultLogDirname = "logs" - defaultLogFilename = "vald.log" - defaultValidatorKeyName = "btc-validator" + defaultLogFilename = "fpd.log" + defaultFinalityProviderKeyName = "finality-provider" DefaultRPCPort = 15812 - defaultConfigFileName = "vald.conf" + defaultConfigFileName = "fpd.conf" defaultNumPubRand = 100 defaultNumPubRandMax = 100 defaultMinRandHeightGap = 10 @@ -39,22 +39,22 @@ const ( defaultMaxSubmissionRetries = 20 defaultBitcoinNetwork = "simnet" defaultDataDirname = "data" - defaultDBPath = "bbolt-vald.db" - defaultMaxNumValidators = 3 + defaultDBPath = "bbolt-fpd.db" + defaultMaxNumFinalityProviders = 3 ) var ( // C:\Users\\AppData\Local\ on Windows - // ~/.vald on Linux - // ~/Library/Application Support/Vald on MacOS - DefaultValdDir = btcutil.AppDataDir("vald", false) + // ~/.fpd on Linux + // ~/Library/Application Support/Fpd on MacOS + DefaultFpdDir = btcutil.AppDataDir("fpd", false) defaultBTCNetParams = chaincfg.SimNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) ) -// Config is the main config for the vald cli command +// Config is the main config for the fpd cli command 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"` // ChainName and ChainID (if any) of the chain config identify a consumer chain @@ -62,7 +62,7 @@ type Config struct { NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` - StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of validator status"` + StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"` RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` UnbondingSigSubmissionInterval time.Duration `long:"unbondingsigsubmissioninterval" description:"The interval between each attempt to check and submit unbonding signature"` @@ -71,7 +71,7 @@ type Config struct { FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` - MaxNumValidators uint32 `long:"maxnumvalidators" description:"The maximum number of validator instances running concurrently within the daemon"` + MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"` BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` @@ -88,7 +88,7 @@ type Config struct { func DefaultConfigWithHome(homePath string) Config { bbnCfg := config.DefaultBBNConfig() - bbnCfg.Key = defaultValidatorKeyName + bbnCfg.Key = defaultFinalityProviderKeyName bbnCfg.KeyDirectory = homePath dbCfg := config.DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() @@ -113,7 +113,7 @@ func DefaultConfigWithHome(homePath string) Config { BTCNetParams: defaultBTCNetParams, EOTSManagerAddress: defaultEOTSManagerAddress, RpcListener: defaultRpcListener, - MaxNumValidators: defaultMaxNumValidators, + MaxNumFinalityProviders: defaultMaxNumFinalityProviders, } if err := cfg.Validate(); err != nil { @@ -124,7 +124,7 @@ func DefaultConfigWithHome(homePath string) Config { } func DefaultConfig() Config { - return DefaultConfigWithHome(DefaultValdDir) + return DefaultConfigWithHome(DefaultFpdDir) } func ConfigFile(homePath string) string { diff --git a/validator/config/poller.go b/finality-provider/config/poller.go similarity index 98% rename from validator/config/poller.go rename to finality-provider/config/poller.go index b0d29ea8..1ee1fee1 100644 --- a/validator/config/poller.go +++ b/finality-provider/config/poller.go @@ -1,4 +1,4 @@ -package valcfg +package fpcfg import "time" diff --git a/validator/proto/.clang-format b/finality-provider/proto/.clang-format similarity index 100% rename from validator/proto/.clang-format rename to finality-provider/proto/.clang-format diff --git a/validator/proto/buf.gen.yaml b/finality-provider/proto/buf.gen.yaml similarity index 100% rename from validator/proto/buf.gen.yaml rename to finality-provider/proto/buf.gen.yaml diff --git a/validator/proto/buf.lock b/finality-provider/proto/buf.lock similarity index 100% rename from validator/proto/buf.lock rename to finality-provider/proto/buf.lock diff --git a/validator/proto/buf.yaml b/finality-provider/proto/buf.yaml similarity index 92% rename from validator/proto/buf.yaml rename to finality-provider/proto/buf.yaml index 4b16d8ad..0e7c3e91 100644 --- a/validator/proto/buf.yaml +++ b/finality-provider/proto/buf.yaml @@ -1,5 +1,5 @@ version: v1 -name: buf.build/babylonchain/btc-validator +name: buf.build/babylonchain/btc-finality-provider deps: - buf.build/cosmos/cosmos-sdk:v0.47.0 - buf.build/cosmos/cosmos-proto:1935555c206d4afb9e94615dfd0fad31 diff --git a/finality-provider/proto/finality_providers.go b/finality-provider/proto/finality_providers.go new file mode 100644 index 00000000..d43dcb46 --- /dev/null +++ b/finality-provider/proto/finality_providers.go @@ -0,0 +1,45 @@ +package proto + +import ( + "encoding/hex" + "fmt" + + 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" +) + +func (sfp *StoreFinalityProvider) GetBabylonPK() *secp256k1.PubKey { + return &secp256k1.PubKey{ + Key: sfp.BabylonPk, + } +} + +func (sfp *StoreFinalityProvider) GetBabylonPkHexString() string { + return hex.EncodeToString(sfp.BabylonPk) +} + +func (sfp *StoreFinalityProvider) MustGetBTCPK() *btcec.PublicKey { + btcPubKey, err := schnorr.ParsePubKey(sfp.BtcPk) + if err != nil { + panic(fmt.Errorf("failed to parse BTC PK: %w", err)) + } + return btcPubKey +} + +func (sfp *StoreFinalityProvider) MustGetBIP340BTCPK() *bbn.BIP340PubKey { + btcPK := sfp.MustGetBTCPK() + return bbn.NewBIP340PubKeyFromBTCPK(btcPK) +} + +func NewFinalityProviderInfo(sfp *StoreFinalityProvider) *FinalityProviderInfo { + return &FinalityProviderInfo{ + BabylonPkHex: sfp.GetBabylonPkHexString(), + BtcPkHex: sfp.MustGetBIP340BTCPK().MarshalHex(), + Description: sfp.Description, + LastVotedHeight: sfp.LastVotedHeight, + LastCommittedHeight: sfp.LastCommittedHeight, + Status: sfp.Status, + } +} diff --git a/finality-provider/proto/finality_providers.pb.go b/finality-provider/proto/finality_providers.pb.go new file mode 100644 index 00000000..a0e64a01 --- /dev/null +++ b/finality-provider/proto/finality_providers.pb.go @@ -0,0 +1,1574 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc (unknown) +// source: finality_providers.proto + +package proto + +import ( + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/x/staking/types" + _ "github.com/cosmos/gogoproto/gogoproto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// 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 +// delegated stake) +// - Active - created and registered to Babylon with stake to vote +// - Inactive - created and registered to Babylon with no stake to vote. +// Finality Provider was already active. +// Valid State Transactions: +// - Created -> Registered +// - Registered -> Active +// - Active -> Inactive +// - Inactive -> Active +type FinalityProviderStatus int32 + +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 + FinalityProviderStatus_REGISTERED FinalityProviderStatus = 1 + // ACTIVE defines a finality provider that is delegated to vote + FinalityProviderStatus_ACTIVE FinalityProviderStatus = 2 + // INACTIVE defines a finality provider whose delegations are reduced to zero but not slashed + FinalityProviderStatus_INACTIVE FinalityProviderStatus = 3 + // SLASHED defines a finality provider that has been slashed + FinalityProviderStatus_SLASHED FinalityProviderStatus = 4 +) + +// Enum value maps for FinalityProviderStatus. +var ( + FinalityProviderStatus_name = map[int32]string{ + 0: "CREATED", + 1: "REGISTERED", + 2: "ACTIVE", + 3: "INACTIVE", + 4: "SLASHED", + } + FinalityProviderStatus_value = map[string]int32{ + "CREATED": 0, + "REGISTERED": 1, + "ACTIVE": 2, + "INACTIVE": 3, + "SLASHED": 4, + } +) + +func (x FinalityProviderStatus) Enum() *FinalityProviderStatus { + p := new(FinalityProviderStatus) + *p = x + return p +} + +func (x FinalityProviderStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FinalityProviderStatus) Descriptor() protoreflect.EnumDescriptor { + return file_finality_providers_proto_enumTypes[0].Descriptor() +} + +func (FinalityProviderStatus) Type() protoreflect.EnumType { + return &file_finality_providers_proto_enumTypes[0] +} + +func (x FinalityProviderStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FinalityProviderStatus.Descriptor instead. +func (FinalityProviderStatus) EnumDescriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{0} +} + +type GetInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetInfoRequest) Reset() { + *x = GetInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInfoRequest) ProtoMessage() {} + +func (x *GetInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[0] + 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 GetInfoRequest.ProtoReflect.Descriptor instead. +func (*GetInfoRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{0} +} + +type GetInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *GetInfoResponse) Reset() { + *x = GetInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInfoResponse) ProtoMessage() {} + +func (x *GetInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[1] + 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 GetInfoResponse.ProtoReflect.Descriptor instead. +func (*GetInfoResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{1} +} + +func (x *GetInfoResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +type CreateFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // key_name is the identifier key in keyring + KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` + // chain_id is the identifier of the consumer chain that the finality provider connected to + ChainId string `protobuf:"bytes,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // description defines the description terms for the finality provider + Description []byte `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + // commission defines the commission rate for the finality provider + Commission string `protobuf:"bytes,6,opt,name=commission,proto3" json:"commission,omitempty"` +} + +func (x *CreateFinalityProviderRequest) Reset() { + *x = CreateFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateFinalityProviderRequest) ProtoMessage() {} + +func (x *CreateFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[2] + 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 CreateFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*CreateFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateFinalityProviderRequest) GetKeyName() string { + if x != nil { + return x.KeyName + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetHdPath() string { + if x != nil { + return x.HdPath + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetDescription() []byte { + if x != nil { + return x.Description + } + return nil +} + +func (x *CreateFinalityProviderRequest) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +type CreateFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // btc_pk is the hex string of 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"` +} + +func (x *CreateFinalityProviderResponse) Reset() { + *x = CreateFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateFinalityProviderResponse) ProtoMessage() {} + +func (x *CreateFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[3] + 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 CreateFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*CreateFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateFinalityProviderResponse) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +type RegisterFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 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"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *RegisterFinalityProviderRequest) Reset() { + *x = RegisterFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFinalityProviderRequest) ProtoMessage() {} + +func (x *RegisterFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[4] + 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 RegisterFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*RegisterFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{4} +} + +func (x *RegisterFinalityProviderRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +func (x *RegisterFinalityProviderRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type RegisterFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // hash of the successful Babylon registration transaction + TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` +} + +func (x *RegisterFinalityProviderResponse) Reset() { + *x = RegisterFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFinalityProviderResponse) ProtoMessage() {} + +func (x *RegisterFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[5] + 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 RegisterFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*RegisterFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{5} +} + +func (x *RegisterFinalityProviderResponse) GetTxHash() string { + if x != nil { + return x.TxHash + } + return "" +} + +type AddFinalitySignatureRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 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 uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + // app_hash is the AppHash of the Babylon block + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (x *AddFinalitySignatureRequest) Reset() { + *x = AddFinalitySignatureRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddFinalitySignatureRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFinalitySignatureRequest) ProtoMessage() {} + +func (x *AddFinalitySignatureRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[6] + 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 AddFinalitySignatureRequest.ProtoReflect.Descriptor instead. +func (*AddFinalitySignatureRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{6} +} + +func (x *AddFinalitySignatureRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +func (x *AddFinalitySignatureRequest) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *AddFinalitySignatureRequest) GetAppHash() []byte { + if x != nil { + return x.AppHash + } + return nil +} + +type AddFinalitySignatureResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // hash of the successful Babylon 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"` + // the hex string of the local Bitcoin secp256k1 private key + LocalSkHex string `protobuf:"bytes,3,opt,name=local_sk_hex,json=localSkHex,proto3" json:"local_sk_hex,omitempty"` +} + +func (x *AddFinalitySignatureResponse) Reset() { + *x = AddFinalitySignatureResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddFinalitySignatureResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFinalitySignatureResponse) ProtoMessage() {} + +func (x *AddFinalitySignatureResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[7] + 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 AddFinalitySignatureResponse.ProtoReflect.Descriptor instead. +func (*AddFinalitySignatureResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{7} +} + +func (x *AddFinalitySignatureResponse) GetTxHash() string { + if x != nil { + return x.TxHash + } + return "" +} + +func (x *AddFinalitySignatureResponse) GetExtractedSkHex() string { + if x != nil { + return x.ExtractedSkHex + } + return "" +} + +func (x *AddFinalitySignatureResponse) GetLocalSkHex() string { + if x != nil { + return x.LocalSkHex + } + return "" +} + +type QueryFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // 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"` +} + +func (x *QueryFinalityProviderRequest) Reset() { + *x = QueryFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderRequest) ProtoMessage() {} + +func (x *QueryFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[8] + 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 QueryFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{8} +} + +func (x *QueryFinalityProviderRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +type QueryFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinalityProvider *FinalityProviderInfo `protobuf:"bytes,1,opt,name=finality_provider,json=finalityProvider,proto3" json:"finality_provider,omitempty"` +} + +func (x *QueryFinalityProviderResponse) Reset() { + *x = QueryFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderResponse) ProtoMessage() {} + +func (x *QueryFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[9] + 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 QueryFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{9} +} + +func (x *QueryFinalityProviderResponse) GetFinalityProvider() *FinalityProviderInfo { + if x != nil { + return x.FinalityProvider + } + return nil +} + +type QueryFinalityProviderListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QueryFinalityProviderListRequest) Reset() { + *x = QueryFinalityProviderListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderListRequest) ProtoMessage() {} + +func (x *QueryFinalityProviderListRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[10] + 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 QueryFinalityProviderListRequest.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderListRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{10} +} + +type QueryFinalityProviderListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinalityProviders []*FinalityProviderInfo `protobuf:"bytes,1,rep,name=finality_providers,json=finalityProviders,proto3" json:"finality_providers,omitempty"` // TODO add pagination in case the list gets large +} + +func (x *QueryFinalityProviderListResponse) Reset() { + *x = QueryFinalityProviderListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderListResponse) ProtoMessage() {} + +func (x *QueryFinalityProviderListResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[11] + 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 QueryFinalityProviderListResponse.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderListResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{11} +} + +func (x *QueryFinalityProviderListResponse) GetFinalityProviders() []*FinalityProviderInfo { + if x != nil { + return x.FinalityProviders + } + return nil +} + +type StoreFinalityProvider 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"` + // 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 *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,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"` + // 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"` + // last_committed_height defines the height of the last Babylon block + // to which the finality provider committed a randomness pair + LastCommittedHeight uint64 `protobuf:"varint,9,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_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,10,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` + // status defines the current finality provider status + Status FinalityProviderStatus `protobuf:"varint,11,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` +} + +func (x *StoreFinalityProvider) Reset() { + *x = StoreFinalityProvider{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StoreFinalityProvider) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StoreFinalityProvider) ProtoMessage() {} + +func (x *StoreFinalityProvider) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[12] + 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 StoreFinalityProvider.ProtoReflect.Descriptor instead. +func (*StoreFinalityProvider) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{12} +} + +func (x *StoreFinalityProvider) GetBabylonPk() []byte { + if x != nil { + return x.BabylonPk + } + return nil +} + +func (x *StoreFinalityProvider) GetBtcPk() []byte { + if x != nil { + return x.BtcPk + } + return nil +} + +func (x *StoreFinalityProvider) GetDescription() []byte { + if x != nil { + return x.Description + } + return nil +} + +func (x *StoreFinalityProvider) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +func (x *StoreFinalityProvider) GetPop() *ProofOfPossession { + if x != nil { + return x.Pop + } + return nil +} + +func (x *StoreFinalityProvider) GetKeyName() string { + if x != nil { + return x.KeyName + } + return "" +} + +func (x *StoreFinalityProvider) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *StoreFinalityProvider) GetLastVotedHeight() uint64 { + if x != nil { + return x.LastVotedHeight + } + return 0 +} + +func (x *StoreFinalityProvider) GetLastCommittedHeight() uint64 { + if x != nil { + return x.LastCommittedHeight + } + return 0 +} + +func (x *StoreFinalityProvider) GetLastProcessedHeight() uint64 { + if x != nil { + return x.LastProcessedHeight + } + return 0 +} + +func (x *StoreFinalityProvider) GetStatus() FinalityProviderStatus { + if x != nil { + return x.Status + } + return FinalityProviderStatus_CREATED +} + +// FinalityProviderInfo is the basic information of a finality provider mainly for external usage +type FinalityProviderInfo struct { + state protoimpl.MessageState + 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"` + // 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 []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"` + // 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"` + // last_committed_height defines the height of the last Babylon block + // to which the finality provider committed a randomness pair + LastCommittedHeight uint64 `protobuf:"varint,6,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` + // status defines the current finality provider status + Status FinalityProviderStatus `protobuf:"varint,7,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` +} + +func (x *FinalityProviderInfo) Reset() { + *x = FinalityProviderInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FinalityProviderInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinalityProviderInfo) ProtoMessage() {} + +func (x *FinalityProviderInfo) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[13] + 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 FinalityProviderInfo.ProtoReflect.Descriptor instead. +func (*FinalityProviderInfo) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{13} +} + +func (x *FinalityProviderInfo) GetBabylonPkHex() string { + if x != nil { + return x.BabylonPkHex + } + return "" +} + +func (x *FinalityProviderInfo) GetBtcPkHex() string { + if x != nil { + return x.BtcPkHex + } + return "" +} + +func (x *FinalityProviderInfo) GetDescription() []byte { + if x != nil { + return x.Description + } + return nil +} + +func (x *FinalityProviderInfo) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +func (x *FinalityProviderInfo) GetLastVotedHeight() uint64 { + if x != nil { + return x.LastVotedHeight + } + return 0 +} + +func (x *FinalityProviderInfo) GetLastCommittedHeight() uint64 { + if x != nil { + return x.LastCommittedHeight + } + return 0 +} + +func (x *FinalityProviderInfo) GetStatus() FinalityProviderStatus { + if x != nil { + return x.Status + } + return FinalityProviderStatus_CREATED +} + +// ProofOfPossession is the proof of possession that a Babylon secp256k1 +// secret key and a Bitcoin secp256k1 secret key are held by the same +// person +type ProofOfPossession struct { + state protoimpl.MessageState + 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) + // the signature follows encoding in BIP-340 spec + BtcSig []byte `protobuf:"bytes,2,opt,name=btc_sig,json=btcSig,proto3" json:"btc_sig,omitempty"` +} + +func (x *ProofOfPossession) Reset() { + *x = ProofOfPossession{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProofOfPossession) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProofOfPossession) ProtoMessage() {} + +func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[14] + 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 ProofOfPossession.ProtoReflect.Descriptor instead. +func (*ProofOfPossession) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{14} +} + +func (x *ProofOfPossession) GetBabylonSig() []byte { + if x != nil { + return x.BabylonSig + } + return nil +} + +func (x *ProofOfPossession) GetBtcSig() []byte { + if x != nil { + return x.BtcSig + } + return nil +} + +type SchnorrRandPair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PubRand []byte `protobuf:"bytes,1,opt,name=pub_rand,json=pubRand,proto3" json:"pub_rand,omitempty"` + SecRand []byte `protobuf:"bytes,2,opt,name=sec_rand,json=secRand,proto3" json:"sec_rand,omitempty"` +} + +func (x *SchnorrRandPair) Reset() { + *x = SchnorrRandPair{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchnorrRandPair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchnorrRandPair) ProtoMessage() {} + +func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[15] + 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 SchnorrRandPair.ProtoReflect.Descriptor instead. +func (*SchnorrRandPair) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{15} +} + +func (x *SchnorrRandPair) GetPubRand() []byte { + if x != nil { + return x.PubRand + } + return nil +} + +func (x *SchnorrRandPair) GetSecRand() []byte { + if x != nil { + return x.SecRand + } + return nil +} + +var File_finality_providers_proto protoreflect.FileDescriptor + +var file_finality_providers_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xf5, 0x01, 0x0a, 0x1d, 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, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, 0x02, 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, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, + 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 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, 0x06, 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, 0x22, + 0x37, 0x0a, 0x1e, 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, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x58, 0x0a, 0x1f, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, + 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, + 0x50, 0x6b, 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, 0x3b, 0x0a, 0x20, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, + 0x67, 0x0a, 0x1b, 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, 0x12, 0x15, + 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x61, 0x70, 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x61, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, + 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, + 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x35, + 0x0a, 0x1c, 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, 0x12, 0x15, + 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 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, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x10, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x22, 0x22, 0x0a, 0x20, 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, 0x22, 0x6f, 0x0a, 0x21, 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, 0x4a, 0x0a, 0x12, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 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, 0xe1, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, 0x0b, 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, 0xd8, 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, 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, + 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x35, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 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, 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, 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, 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, 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, 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 ( + file_finality_providers_proto_rawDescOnce sync.Once + file_finality_providers_proto_rawDescData = file_finality_providers_proto_rawDesc +) + +func file_finality_providers_proto_rawDescGZIP() []byte { + file_finality_providers_proto_rawDescOnce.Do(func() { + file_finality_providers_proto_rawDescData = protoimpl.X.CompressGZIP(file_finality_providers_proto_rawDescData) + }) + return file_finality_providers_proto_rawDescData +} + +var file_finality_providers_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_finality_providers_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_finality_providers_proto_goTypes = []interface{}{ + (FinalityProviderStatus)(0), // 0: proto.FinalityProviderStatus + (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest + (*GetInfoResponse)(nil), // 2: proto.GetInfoResponse + (*CreateFinalityProviderRequest)(nil), // 3: proto.CreateFinalityProviderRequest + (*CreateFinalityProviderResponse)(nil), // 4: proto.CreateFinalityProviderResponse + (*RegisterFinalityProviderRequest)(nil), // 5: proto.RegisterFinalityProviderRequest + (*RegisterFinalityProviderResponse)(nil), // 6: proto.RegisterFinalityProviderResponse + (*AddFinalitySignatureRequest)(nil), // 7: proto.AddFinalitySignatureRequest + (*AddFinalitySignatureResponse)(nil), // 8: proto.AddFinalitySignatureResponse + (*QueryFinalityProviderRequest)(nil), // 9: proto.QueryFinalityProviderRequest + (*QueryFinalityProviderResponse)(nil), // 10: proto.QueryFinalityProviderResponse + (*QueryFinalityProviderListRequest)(nil), // 11: proto.QueryFinalityProviderListRequest + (*QueryFinalityProviderListResponse)(nil), // 12: proto.QueryFinalityProviderListResponse + (*StoreFinalityProvider)(nil), // 13: proto.StoreFinalityProvider + (*FinalityProviderInfo)(nil), // 14: proto.FinalityProviderInfo + (*ProofOfPossession)(nil), // 15: proto.ProofOfPossession + (*SchnorrRandPair)(nil), // 16: proto.SchnorrRandPair +} +var file_finality_providers_proto_depIdxs = []int32{ + 14, // 0: proto.QueryFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo + 14, // 1: proto.QueryFinalityProviderListResponse.finality_providers:type_name -> proto.FinalityProviderInfo + 15, // 2: proto.StoreFinalityProvider.pop:type_name -> proto.ProofOfPossession + 0, // 3: proto.StoreFinalityProvider.status:type_name -> proto.FinalityProviderStatus + 0, // 4: proto.FinalityProviderInfo.status:type_name -> proto.FinalityProviderStatus + 1, // 5: proto.FinalityProviders.GetInfo:input_type -> proto.GetInfoRequest + 3, // 6: proto.FinalityProviders.CreateFinalityProvider:input_type -> proto.CreateFinalityProviderRequest + 5, // 7: proto.FinalityProviders.RegisterFinalityProvider:input_type -> proto.RegisterFinalityProviderRequest + 7, // 8: proto.FinalityProviders.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest + 9, // 9: proto.FinalityProviders.QueryFinalityProvider:input_type -> proto.QueryFinalityProviderRequest + 11, // 10: proto.FinalityProviders.QueryFinalityProviderList:input_type -> proto.QueryFinalityProviderListRequest + 2, // 11: proto.FinalityProviders.GetInfo:output_type -> proto.GetInfoResponse + 4, // 12: proto.FinalityProviders.CreateFinalityProvider:output_type -> proto.CreateFinalityProviderResponse + 6, // 13: proto.FinalityProviders.RegisterFinalityProvider:output_type -> proto.RegisterFinalityProviderResponse + 8, // 14: proto.FinalityProviders.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse + 10, // 15: proto.FinalityProviders.QueryFinalityProvider:output_type -> proto.QueryFinalityProviderResponse + 12, // 16: proto.FinalityProviders.QueryFinalityProviderList:output_type -> proto.QueryFinalityProviderListResponse + 11, // [11:17] is the sub-list for method output_type + 5, // [5:11] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_finality_providers_proto_init() } +func file_finality_providers_proto_init() { + if File_finality_providers_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_finality_providers_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddFinalitySignatureRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddFinalitySignatureResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StoreFinalityProvider); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FinalityProviderInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProofOfPossession); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchnorrRandPair); 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{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_finality_providers_proto_rawDesc, + NumEnums: 1, + NumMessages: 16, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_finality_providers_proto_goTypes, + DependencyIndexes: file_finality_providers_proto_depIdxs, + EnumInfos: file_finality_providers_proto_enumTypes, + MessageInfos: file_finality_providers_proto_msgTypes, + }.Build() + File_finality_providers_proto = out.File + file_finality_providers_proto_rawDesc = nil + file_finality_providers_proto_goTypes = nil + file_finality_providers_proto_depIdxs = nil +} diff --git a/validator/proto/validators.proto b/finality-provider/proto/finality_providers.proto similarity index 59% rename from validator/proto/validators.proto rename to finality-provider/proto/finality_providers.proto index 66aa0531..0ef3b8a7 100644 --- a/validator/proto/validators.proto +++ b/finality-provider/proto/finality_providers.proto @@ -6,31 +6,32 @@ import "gogoproto/gogo.proto"; import "cosmos/staking/v1beta1/staking.proto"; import "cosmos_proto/cosmos.proto"; -option go_package = "github.com/babylonchain/btc-validator/validator/proto"; +option go_package = "github.com/babylonchain/finality-provider/finality-provider/proto"; -service BtcValidators { +service FinalityProviders { // GetInfo returns the information of the daemon rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); - // CreateValidator generates and saves a validator object - rpc CreateValidator (CreateValidatorRequest) - returns (CreateValidatorResponse); + // CreateFinalityProvider generates and saves a finality provider object + rpc CreateFinalityProvider (CreateFinalityProviderRequest) + returns (CreateFinalityProviderResponse); - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - rpc RegisterValidator (RegisterValidatorRequest) - returns (RegisterValidatorResponse); + // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // finality provider + rpc RegisterFinalityProvider (RegisterFinalityProviderRequest) + returns (RegisterFinalityProviderResponse); // AddFinalitySignature sends a transactions to Babylon to add a Finality // signature for a block rpc AddFinalitySignature(AddFinalitySignatureRequest) returns (AddFinalitySignatureResponse); - // QueryValidator queries the validator - rpc QueryValidator (QueryValidatorRequest) returns (QueryValidatorResponse); - // QueryValidatorList queries a list of validators - rpc QueryValidatorList (QueryValidatorListRequest) - returns (QueryValidatorListResponse); + // QueryFinalityProvider queries the finality provider + rpc QueryFinalityProvider (QueryFinalityProviderRequest) returns (QueryFinalityProviderResponse); + + // QueryFinalityProviderList queries a list of finality providers + rpc QueryFinalityProviderList (QueryFinalityProviderListRequest) + returns (QueryFinalityProviderListResponse); } message GetInfoRequest { @@ -40,43 +41,43 @@ message GetInfoResponse { string version = 1; } -message CreateValidatorRequest { +message CreateFinalityProviderRequest { // key_name is the identifier key in keyring string key_name = 1; // passphrase is used to encrypt the keys string passphrase = 2; // hd_path is the hd path for private key derivation string hd_path = 3; - // chain_id is the identifier of the consumer chain that the validator connected to + // chain_id is the identifier of the consumer chain that the finality provider connected to string chain_id = 4; - // description defines the description terms for the validator + // description defines the description terms for the finality provider bytes description = 5; - // commission defines the commission rate for the validator + // commission defines the commission rate for the finality provider string commission = 6 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; } -message CreateValidatorResponse { - // btc_pk is the hex string of BTC secp256k1 public key of the validator encoded in BIP-340 spec +message CreateFinalityProviderResponse { + // btc_pk is the hex string of BTC secp256k1 public key of the finality provider encoded in BIP-340 spec string btc_pk = 1; } -message RegisterValidatorRequest { - // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec +message RegisterFinalityProviderRequest { + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec string btc_pk = 1; // passphrase is used to encrypt the keys string passphrase = 2; } -message RegisterValidatorResponse { +message RegisterFinalityProviderResponse { // hash of the successful Babylon registration transaction string tx_hash = 1; } message AddFinalitySignatureRequest { - // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec + // 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 uint64 height = 2; @@ -93,32 +94,32 @@ message AddFinalitySignatureResponse { string local_sk_hex = 3; } -message QueryValidatorRequest { - // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec +message QueryFinalityProviderRequest { + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec string btc_pk = 1; } -message QueryValidatorResponse { - ValidatorInfo validator = 1; +message QueryFinalityProviderResponse { + FinalityProviderInfo finality_provider = 1; } -message QueryValidatorListRequest { +message QueryFinalityProviderListRequest { // TODO add pagination in case the list gets large } -message QueryValidatorListResponse { - repeated ValidatorInfo validators = 1; +message QueryFinalityProviderListResponse { + repeated FinalityProviderInfo finality_providers = 1; // TODO add pagination in case the list gets large } -message StoreValidator { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator +message StoreFinalityProvider { + // babylon_pk is the Babylon secp256k1 PK of this finality provider bytes babylon_pk = 1; - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec + // 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 validator + // description defines the description terms for the finality provider bytes description = 3; - // commission defines the commission rate for the validator + // commission defines the commission rate for the finality provider string commission = 4 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false @@ -127,29 +128,29 @@ message StoreValidator { ProofOfPossession pop = 5; // key_name is the identifier of the keyring string key_name = 6; - // chain_id is the identifier of the consumer chain that the validator connected to + // 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; // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair + // to which the finality provider committed a randomness pair uint64 last_committed_height = 9; // last_processed_height defines the height of the last successfully processed block // even though the vote is not cast uint64 last_processed_height = 10; - // status defines the current validator status - ValidatorStatus status = 11; + // status defines the current finality provider status + FinalityProviderStatus status = 11; } -// ValidatorInfo is the basic information of a validator mainly for external usage -message ValidatorInfo { - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this BTC validator +// 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; - // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator encoded in BIP-340 spec + // 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 validator + // description defines the description terms for the finality provider bytes description = 3; - // commission defines the commission rate for the validator + // commission defines the commission rate for the finality provider string commission = 4 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false @@ -157,10 +158,10 @@ message ValidatorInfo { // last_voted_height defines the height of the last voted Babylon block uint64 last_voted_height = 5; // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair + // to which the finality provider committed a randomness pair uint64 last_committed_height = 6; - // status defines the current validator status - ValidatorStatus status = 7; + // status defines the current finality provider status + FinalityProviderStatus status = 7; } // ProofOfPossession is the proof of possession that a Babylon secp256k1 @@ -179,32 +180,32 @@ message SchnorrRandPair { bytes sec_rand = 2; } -// ValidatorStatus is the status of a BTC validator -// a Validator object has 4 states: -// - Created - created and managed by validator client, not registered to +// 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 // delegated stake) // - Active - created and registered to Babylon with stake to vote // - Inactive - created and registered to Babylon with no stake to vote. -// Validator was already active. +// Finality Provider was already active. // Valid State Transactions: // - Created -> Registered // - Registered -> Active // - Active -> Inactive // - Inactive -> Active -enum ValidatorStatus { +enum FinalityProviderStatus { option (gogoproto.goproto_enum_prefix) = false; - // CREATED defines a validator that is awaiting registration + // CREATED defines a finality provider that is awaiting registration CREATED = 0 [(gogoproto.enumvalue_customname) = "CREATED"]; - // REGISTERED defines a validator that has been registered + // REGISTERED defines a finality provider that has been registered // to Babylon but has no delegated stake REGISTERED = 1 [(gogoproto.enumvalue_customname) = "REGISTERED"]; - // ACTIVE defines a validator that is delegated to vote + // ACTIVE defines a finality provider that is delegated to vote ACTIVE = 2 [(gogoproto.enumvalue_customname) = "ACTIVE"]; - // INACTIVE defines a validator whose delegations are reduced to zero but not slashed + // INACTIVE defines a finality provider whose delegations are reduced to zero but not slashed INACTIVE = 3 [(gogoproto.enumvalue_customname) = "INACTIVE"]; - // SLASHED defines a validator that has been slashed + // SLASHED defines a finality provider that has been slashed SLASHED = 4 [(gogoproto.enumvalue_customname) = "SLASHED"]; } diff --git a/finality-provider/proto/finality_providers_grpc.pb.go b/finality-provider/proto/finality_providers_grpc.pb.go new file mode 100644 index 00000000..e8a27819 --- /dev/null +++ b/finality-provider/proto/finality_providers_grpc.pb.go @@ -0,0 +1,310 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: finality_providers.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + FinalityProviders_GetInfo_FullMethodName = "/proto.FinalityProviders/GetInfo" + FinalityProviders_CreateFinalityProvider_FullMethodName = "/proto.FinalityProviders/CreateFinalityProvider" + FinalityProviders_RegisterFinalityProvider_FullMethodName = "/proto.FinalityProviders/RegisterFinalityProvider" + FinalityProviders_AddFinalitySignature_FullMethodName = "/proto.FinalityProviders/AddFinalitySignature" + FinalityProviders_QueryFinalityProvider_FullMethodName = "/proto.FinalityProviders/QueryFinalityProvider" + FinalityProviders_QueryFinalityProviderList_FullMethodName = "/proto.FinalityProviders/QueryFinalityProviderList" +) + +// FinalityProvidersClient is the client API for FinalityProviders service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type FinalityProvidersClient interface { + // GetInfo returns the information of the daemon + 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 + // finality provider + RegisterFinalityProvider(ctx context.Context, in *RegisterFinalityProviderRequest, opts ...grpc.CallOption) (*RegisterFinalityProviderResponse, error) + // AddFinalitySignature sends a transactions to Babylon 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) +} + +type finalityProvidersClient struct { + cc grpc.ClientConnInterface +} + +func NewFinalityProvidersClient(cc grpc.ClientConnInterface) FinalityProvidersClient { + return &finalityProvidersClient{cc} +} + +func (c *finalityProvidersClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) { + out := new(GetInfoResponse) + err := c.cc.Invoke(ctx, FinalityProviders_GetInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) CreateFinalityProvider(ctx context.Context, in *CreateFinalityProviderRequest, opts ...grpc.CallOption) (*CreateFinalityProviderResponse, error) { + out := new(CreateFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_CreateFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) RegisterFinalityProvider(ctx context.Context, in *RegisterFinalityProviderRequest, opts ...grpc.CallOption) (*RegisterFinalityProviderResponse, error) { + out := new(RegisterFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_RegisterFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) { + out := new(AddFinalitySignatureResponse) + err := c.cc.Invoke(ctx, FinalityProviders_AddFinalitySignature_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) QueryFinalityProvider(ctx context.Context, in *QueryFinalityProviderRequest, opts ...grpc.CallOption) (*QueryFinalityProviderResponse, error) { + out := new(QueryFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_QueryFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) QueryFinalityProviderList(ctx context.Context, in *QueryFinalityProviderListRequest, opts ...grpc.CallOption) (*QueryFinalityProviderListResponse, error) { + out := new(QueryFinalityProviderListResponse) + err := c.cc.Invoke(ctx, FinalityProviders_QueryFinalityProviderList_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 +type FinalityProvidersServer interface { + // GetInfo returns the information of the daemon + 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 + // finality provider + RegisterFinalityProvider(context.Context, *RegisterFinalityProviderRequest) (*RegisterFinalityProviderResponse, error) + // AddFinalitySignature sends a transactions to Babylon 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) + mustEmbedUnimplementedFinalityProvidersServer() +} + +// UnimplementedFinalityProvidersServer must be embedded to have forward compatible implementations. +type UnimplementedFinalityProvidersServer struct { +} + +func (UnimplementedFinalityProvidersServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") +} +func (UnimplementedFinalityProvidersServer) CreateFinalityProvider(context.Context, *CreateFinalityProviderRequest) (*CreateFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) RegisterFinalityProvider(context.Context, *RegisterFinalityProviderRequest) (*RegisterFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddFinalitySignature not implemented") +} +func (UnimplementedFinalityProvidersServer) QueryFinalityProvider(context.Context, *QueryFinalityProviderRequest) (*QueryFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) QueryFinalityProviderList(context.Context, *QueryFinalityProviderListRequest) (*QueryFinalityProviderListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryFinalityProviderList not implemented") +} +func (UnimplementedFinalityProvidersServer) mustEmbedUnimplementedFinalityProvidersServer() {} + +// UnsafeFinalityProvidersServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to FinalityProvidersServer will +// result in compilation errors. +type UnsafeFinalityProvidersServer interface { + mustEmbedUnimplementedFinalityProvidersServer() +} + +func RegisterFinalityProvidersServer(s grpc.ServiceRegistrar, srv FinalityProvidersServer) { + s.RegisterService(&FinalityProviders_ServiceDesc, srv) +} + +func _FinalityProviders_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).GetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_GetInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).GetInfo(ctx, req.(*GetInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_CreateFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).CreateFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_CreateFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).CreateFinalityProvider(ctx, req.(*CreateFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_RegisterFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).RegisterFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_RegisterFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).RegisterFinalityProvider(ctx, req.(*RegisterFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_AddFinalitySignature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddFinalitySignatureRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).AddFinalitySignature(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_AddFinalitySignature_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).AddFinalitySignature(ctx, req.(*AddFinalitySignatureRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_QueryFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).QueryFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_QueryFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).QueryFinalityProvider(ctx, req.(*QueryFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_QueryFinalityProviderList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFinalityProviderListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).QueryFinalityProviderList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_QueryFinalityProviderList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).QueryFinalityProviderList(ctx, req.(*QueryFinalityProviderListRequest)) + } + 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) +var FinalityProviders_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.FinalityProviders", + HandlerType: (*FinalityProvidersServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetInfo", + Handler: _FinalityProviders_GetInfo_Handler, + }, + { + MethodName: "CreateFinalityProvider", + Handler: _FinalityProviders_CreateFinalityProvider_Handler, + }, + { + MethodName: "RegisterFinalityProvider", + Handler: _FinalityProviders_RegisterFinalityProvider_Handler, + }, + { + MethodName: "AddFinalitySignature", + Handler: _FinalityProviders_AddFinalitySignature_Handler, + }, + { + MethodName: "QueryFinalityProvider", + Handler: _FinalityProviders_QueryFinalityProvider_Handler, + }, + { + MethodName: "QueryFinalityProviderList", + Handler: _FinalityProviders_QueryFinalityProviderList_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "finality_providers.proto", +} diff --git a/validator/proto/scripts/protocgen.sh b/finality-provider/proto/scripts/protocgen.sh similarity index 100% rename from validator/proto/scripts/protocgen.sh rename to finality-provider/proto/scripts/protocgen.sh diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go new file mode 100644 index 00000000..42f7eb48 --- /dev/null +++ b/finality-provider/service/app.go @@ -0,0 +1,467 @@ +package service + +import ( + "encoding/hex" + "fmt" + "github.com/babylonchain/finality-provider/util" + "strings" + "sync" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "go.uber.org/zap" + + fpkr "github.com/babylonchain/finality-provider/keyring" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "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" +) + +type FinalityProviderApp struct { + startOnce sync.Once + stopOnce sync.Once + + 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 + config *fpcfg.Config + logger *zap.Logger + input *strings.Reader + + fpManager *FinalityProviderManager + eotsManager eotsmanager.EOTSManager + + createFinalityProviderRequestChan chan *createFinalityProviderRequest + registerFinalityProviderRequestChan chan *registerFinalityProviderRequest + finalityProviderRegisteredEventChan chan *finalityProviderRegisteredEvent +} + +func NewFinalityProviderAppFromConfig( + homePath string, + config *fpcfg.Config, + logger *zap.Logger, +) (*FinalityProviderApp, error) { + cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.BTCNetParams, logger) + if err != nil { + return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.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) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) + } + // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) + + return NewFinalityProviderApp(homePath, config, cc, em, logger) +} + +func NewFinalityProviderApp( + homePath string, + config *fpcfg.Config, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + logger *zap.Logger, +) (*FinalityProviderApp, error) { + fpStore, err := initStore(homePath, config) + if err != nil { + return nil, fmt.Errorf("failed to load store: %w", err) + } + + input := strings.NewReader("") + kr, err := fpkr.CreateKeyring( + config.BabylonConfig.KeyDirectory, + config.BabylonConfig.ChainID, + config.BabylonConfig.KeyringBackend, + input, + ) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + fpm, err := NewFinalityProviderManager(fpStore, config, cc, em, logger) + if err != nil { + return nil, fmt.Errorf("failed to create finality-provider manager: %w", err) + } + + return &FinalityProviderApp{ + cc: cc, + fps: fpStore, + kr: kr, + config: config, + logger: logger, + input: input, + fpManager: fpm, + eotsManager: em, + 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 { + return app.fps +} + +func (app *FinalityProviderApp) GetKeyring() keyring.Keyring { + return app.kr +} + +func (app *FinalityProviderApp) GetInput() *strings.Reader { + return app.input +} + +func (app *FinalityProviderApp) ListFinalityProviderInstances() []*FinalityProviderInstance { + return app.fpManager.ListFinalityProviderInstances() +} + +// 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) +} + +func (app *FinalityProviderApp) RegisterFinalityProvider(fpPkStr string) (*RegisterFinalityProviderResponse, error) { + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return nil, err + } + + fp, err := app.fps.GetStoreFinalityProvider(fpPk.MustMarshal()) + if err != nil { + return nil, err + } + + if fp.Status != proto.FinalityProviderStatus_CREATED { + return nil, fmt.Errorf("finality-provider is already registered") + } + + btcSig, err := bbntypes.NewBIP340Signature(fp.Pop.BtcSig) + if err != nil { + return nil, err + } + + pop := &bstypes.ProofOfPossession{ + BabylonSig: fp.Pop.BabylonSig, + 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(), + pop: pop, + description: fp.Description, + commission: &commissionRate, + errResponse: make(chan error, 1), + successResponse: make(chan *RegisterFinalityProviderResponse, 1), + } + + app.registerFinalityProviderRequestChan <- request + + select { + case err := <-request.errResponse: + return nil, err + case successResponse := <-request.successResponse: + return successResponse, nil + case <-app.quit: + return nil, fmt.Errorf("finality-provider app is shutting down") + } +} + +// StartHandlingFinalityProvider starts a finality-provider instance with the given Babylon public key +// Note: this should be called right after the finality-provider is registered +func (app *FinalityProviderApp) StartHandlingFinalityProvider(fpPk *bbntypes.BIP340PubKey, passphrase string) error { + return app.fpManager.StartFinalityProvider(fpPk, passphrase) +} + +// NOTE: this is not safe in production, so only used for testing purpose +func (app *FinalityProviderApp) getFpPrivKey(fpPk []byte) (*btcec.PrivateKey, error) { + record, err := app.eotsManager.KeyRecord(fpPk, "") + if err != nil { + return nil, err + } + + return record.PrivKey, 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) + go app.eventLoop() + + app.sentWg.Add(1) + go app.registrationLoop() + }) + + return startErr +} + +func (app *FinalityProviderApp) Stop() error { + var stopErr error + app.stopOnce.Do(func() { + app.logger.Info("Stopping FinalityProviderApp") + + // Always stop the submission loop first to not generate additional events and actions + app.logger.Debug("Stopping submission loop") + close(app.quit) + app.wg.Wait() + + app.logger.Debug("Stopping finality providers") + if err := app.fpManager.Stop(); err != nil { + stopErr = err + 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 + return + } + + app.logger.Debug("FinalityProviderApp successfully stopped") + + }) + return stopErr +} + +func (app *FinalityProviderApp) CreateFinalityProvider( + keyName, chainID, passPhrase, hdPath string, + description []byte, + commission *sdkmath.LegacyDec, +) (*CreateFinalityProviderResult, error) { + + req := &createFinalityProviderRequest{ + keyName: keyName, + chainID: chainID, + passPhrase: passPhrase, + hdPath: hdPath, + description: description, + commission: commission, + errResponse: make(chan error, 1), + successResponse: make(chan *createFinalityProviderResponse, 1), + } + + app.createFinalityProviderRequestChan <- req + + select { + case err := <-req.errResponse: + return nil, err + case successResponse := <-req.successResponse: + return &CreateFinalityProviderResult{ + FpPk: successResponse.FpPk, + }, nil + case <-app.quit: + return nil, fmt.Errorf("finality-provider app is shutting down") + } +} + +func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createFinalityProviderRequest) (*createFinalityProviderResponse, error) { + fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) + if err != nil { + return nil, err + } + + fpPk, err := bbntypes.NewBIP340PubKey(fpPkBytes) + if err != nil { + return nil, err + } + + kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) + if err != nil { + return nil, err + } + + keyPair, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + if err != nil { + return nil, fmt.Errorf("failed to create chain key for the finality-provider: %w", err) + } + pk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} + + fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), req.passPhrase) + if err != nil { + return nil, fmt.Errorf("failed to get finality-provider record: %w", err) + } + + pop, err := kr.CreatePop(fpRecord.PrivKey, req.passPhrase) + if err != nil { + return nil, fmt.Errorf("failed to create proof-of-possession of the finality-provider: %w", err) + } + + fp := fpstore.NewStoreFinalityProvider(pk, fpPk, req.keyName, req.chainID, pop, req.description, req.commission) + + if err := app.fps.SaveFinalityProvider(fp); err != nil { + return nil, fmt.Errorf("failed to save finality-provider: %w", err) + } + + app.logger.Info("successfully created a finality-provider", + zap.String("btc_pk", fpPk.MarshalHex()), + zap.String("key_name", req.keyName), + ) + + return &createFinalityProviderResponse{ + FpPk: fpPk, + }, nil +} + +// main event loop for the finality-provider app +func (app *FinalityProviderApp) eventLoop() { + defer app.eventWg.Done() + + for { + select { + case req := <-app.createFinalityProviderRequestChan: + res, err := app.handleCreateFinalityProviderRequest(req) + if err != nil { + req.errResponse <- err + continue + } + + req.successResponse <- &createFinalityProviderResponse{FpPk: res.FpPk} + + 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", + 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", + zap.String("pk", ev.btcPubKey.MarshalHex()), + zap.Error(err), + ) + } + + // return to the caller + ev.successResponse <- &RegisterFinalityProviderResponse{ + bbnPubKey: fpStored.GetBabylonPK(), + btcPubKey: fpStored.MustGetBIP340BTCPK(), + TxHash: ev.txHash, + } + + case <-app.eventQuit: + app.logger.Debug("exiting main event loop") + return + } + } +} + +func (app *FinalityProviderApp) registrationLoop() { + defer app.sentWg.Done() + for { + select { + case req := <-app.registerFinalityProviderRequestChan: + // we won't do any retries here to not block the loop for more important messages. + // Most probably it fails due so some user error so we just return the error to the user. + // TODO: need to start passing context here to be able to cancel the request in case of app quiting + popBytes, err := req.pop.Marshal() + if err != nil { + req.errResponse <- err + continue + } + + res, err := app.cc.RegisterFinalityProvider( + req.bbnPubKey.Key, + req.btcPubKey.MustToBTCPK(), + popBytes, + req.commission, + req.description, + ) + + if err != nil { + app.logger.Error( + "failed to register finality-provider", + zap.String("pk", req.btcPubKey.MarshalHex()), + zap.Error(err), + ) + req.errResponse <- err + continue + } + + app.logger.Info( + "successfully registered finality-provider on babylon", + zap.String("btc_pk", req.btcPubKey.MarshalHex()), + zap.String("babylon_pk", hex.EncodeToString(req.bbnPubKey.Key)), + zap.String("txHash", res.TxHash), + ) + + app.finalityProviderRegisteredEventChan <- &finalityProviderRegisteredEvent{ + btcPubKey: req.btcPubKey, + bbnPubKey: req.bbnPubKey, + txHash: res.TxHash, + // 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: + app.logger.Debug("exiting registration loop") + return + } + } +} diff --git a/validator/service/app_test.go b/finality-provider/service/app_test.go similarity index 60% rename from validator/service/app_test.go rename to finality-provider/service/app_test.go index 1dee92ed..1852fcd9 100644 --- a/validator/service/app_test.go +++ b/finality-provider/service/app_test.go @@ -12,11 +12,11 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/validator/service" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -24,7 +24,7 @@ var ( hdPath = "" ) -func FuzzRegisterValidator(f *testing.F) { +func FuzzRegisterFinalityProvider(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) @@ -47,14 +47,14 @@ func FuzzRegisterValidator(f *testing.F) { mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() // Create randomized config - valHomeDir := filepath.Join(t.TempDir(), "val-home") - valCfg := testutil.GenValConfig(r, t, valHomeDir) - valCfg.PollerConfig.AutoChainScanningMode = false - valCfg.PollerConfig.StaticChainScanningStartHeight = randomStartingHeight - app, err := service.NewValidatorApp(valHomeDir, valCfg, mockClientController, em, logger) + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.PollerConfig.AutoChainScanningMode = false + fpCfg.PollerConfig.StaticChainScanningStartHeight = randomStartingHeight + app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, mockClientController, em, logger) require.NoError(t, err) defer func() { - err = os.RemoveAll(valHomeDir) + err = os.RemoveAll(fpHomeDir) require.NoError(t, err) }() @@ -65,13 +65,13 @@ func FuzzRegisterValidator(f *testing.F) { require.NoError(t, err) }() - // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) + // create a finality-provider object and save it to db + fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) btcSig := new(bbntypes.BIP340Signature) - err = btcSig.Unmarshal(validator.Pop.BtcSig) + err = btcSig.Unmarshal(fp.Pop.BtcSig) require.NoError(t, err) pop := &bstypes.ProofOfPossession{ - BabylonSig: validator.Pop.BabylonSig, + BabylonSig: fp.Pop.BabylonSig, BtcSig: btcSig.MustMarshal(), BtcSigType: bstypes.BTCSigType_BIP340, } @@ -80,23 +80,23 @@ func FuzzRegisterValidator(f *testing.F) { txHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - RegisterValidator( - validator.GetBabylonPK().Key, - validator.MustGetBIP340BTCPK().MustToBTCPK(), + RegisterFinalityProvider( + fp.GetBabylonPK().Key, + fp.MustGetBIP340BTCPK().MustToBTCPK(), popBytes, testutil.ZeroCommissionRate(), testutil.EmptyDescription(), ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() - res, err := app.RegisterValidator(validator.MustGetBIP340BTCPK().MarshalHex()) + res, err := app.RegisterFinalityProvider(fp.MustGetBIP340BTCPK().MarshalHex()) require.NoError(t, err) require.Equal(t, txHash, res.TxHash) - err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK(), passphrase) + err = app.StartHandlingFinalityProvider(fp.MustGetBIP340BTCPK(), passphrase) require.NoError(t, err) - valAfterReg, err := app.GetValidatorInstance(validator.MustGetBIP340BTCPK()) + fpAfterReg, err := app.GetFinalityProviderInstance(fp.MustGetBIP340BTCPK()) require.NoError(t, err) - require.Equal(t, valAfterReg.GetStoreValidator().Status, proto.ValidatorStatus_REGISTERED) + require.Equal(t, fpAfterReg.GetStoreFinalityProvider().Status, proto.FinalityProviderStatus_REGISTERED) }) } diff --git a/validator/service/chain_poller.go b/finality-provider/service/chain_poller.go similarity index 97% rename from validator/service/chain_poller.go rename to finality-provider/service/chain_poller.go index 51b3c137..856a6d45 100644 --- a/validator/service/chain_poller.go +++ b/finality-provider/service/chain_poller.go @@ -8,9 +8,9 @@ import ( "github.com/avast/retry-go/v4" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/types" - cfg "github.com/babylonchain/btc-validator/validator/config" + "github.com/babylonchain/finality-provider/clientcontroller" + cfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/types" ) var ( diff --git a/finality-provider/service/client/rpcclient.go b/finality-provider/service/client/rpcclient.go new file mode 100644 index 00000000..afd68858 --- /dev/null +++ b/finality-provider/service/client/rpcclient.go @@ -0,0 +1,122 @@ +package client + +import ( + "context" + "fmt" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/babylonchain/finality-provider/finality-provider/proto" +) + +type FinalityProviderServiceGRpcClient struct { + client proto.FinalityProvidersClient +} + +func NewFinalityProviderServiceGRpcClient(remoteAddr string) (*FinalityProviderServiceGRpcClient, func(), error) { + conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) + } + + cleanUp := func() { + conn.Close() + } + + return &FinalityProviderServiceGRpcClient{ + client: proto.NewFinalityProvidersClient(conn), + }, cleanUp, nil +} + +func (c *FinalityProviderServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInfoResponse, error) { + req := &proto.GetInfoRequest{} + res, err := c.client.GetInfo(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) RegisterFinalityProvider( + ctx context.Context, + fpPk *bbntypes.BIP340PubKey, + passphrase string, +) (*proto.RegisterFinalityProviderResponse, error) { + + req := &proto.RegisterFinalityProviderRequest{BtcPk: fpPk.MarshalHex(), Passphrase: passphrase} + res, err := c.client.RegisterFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider( + ctx context.Context, + keyName, chainID, passphrase, hdPath string, + description types.Description, + commission *sdkmath.LegacyDec, +) (*proto.CreateFinalityProviderResponse, error) { + + descBytes, err := description.Marshal() + if err != nil { + return nil, err + } + + req := &proto.CreateFinalityProviderRequest{ + KeyName: keyName, + ChainId: chainID, + Passphrase: passphrase, + HdPath: hdPath, + Description: descBytes, + Commission: commission.String(), + } + + res, err := c.client.CreateFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature(ctx context.Context, fpPk string, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { + req := &proto.AddFinalitySignatureRequest{ + BtcPk: fpPk, + Height: height, + AppHash: lch, + } + + res, err := c.client.AddFinalitySignature(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) QueryFinalityProviderList(ctx context.Context) (*proto.QueryFinalityProviderListResponse, error) { + req := &proto.QueryFinalityProviderListRequest{} + res, err := c.client.QueryFinalityProviderList(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) QueryFinalityProviderInfo(ctx context.Context, fpPk *bbntypes.BIP340PubKey) (*proto.QueryFinalityProviderResponse, error) { + req := &proto.QueryFinalityProviderRequest{BtcPk: fpPk.MarshalHex()} + res, err := c.client.QueryFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} diff --git a/validator/service/fastsync.go b/finality-provider/service/fastsync.go similarity index 74% rename from validator/service/fastsync.go rename to finality-provider/service/fastsync.go index 0a7e7c82..d070109a 100644 --- a/validator/service/fastsync.go +++ b/finality-provider/service/fastsync.go @@ -5,7 +5,7 @@ import ( "go.uber.org/zap" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/types" ) type FastSyncResult struct { @@ -17,11 +17,11 @@ type FastSyncResult struct { // FastSync attempts to send a batch of finality signatures // from the maximum of the last voted height and the last finalized height // to the current height -func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncResult, error) { - if v.inSync.Swap(true) { - return nil, fmt.Errorf("the validator has already been in fast sync") +func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*FastSyncResult, error) { + if fp.inSync.Swap(true) { + return nil, fmt.Errorf("the finality-provider has already been in fast sync") } - defer v.inSync.Store(false) + defer fp.inSync.Store(false) if startHeight > endHeight { return nil, fmt.Errorf("the start height %v should not be higher than the end height %v", @@ -33,7 +33,7 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe // we may need several rounds to catch-up as we need to limit // the catch-up distance for each round to avoid memory overflow for startHeight <= endHeight { - blocks, err := v.cc.QueryBlocks(startHeight, endHeight, v.cfg.FastSyncLimit) + blocks, err := fp.cc.QueryBlocks(startHeight, endHeight, fp.cfg.FastSyncLimit) if err != nil { return nil, err } @@ -49,7 +49,7 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe // have gaps during sync catchUpBlocks := make([]*types.BlockInfo, 0, len(blocks)) for _, b := range blocks { - should, err := v.shouldSubmitFinalitySignature(b) + should, err := fp.shouldSubmitFinalitySignature(b) if err != nil { // stop catch-up when critical errors occur return nil, err @@ -71,22 +71,22 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe syncedHeight = catchUpBlocks[len(catchUpBlocks)-1].Height - res, err := v.SubmitBatchFinalitySignatures(catchUpBlocks) + res, err := fp.SubmitBatchFinalitySignatures(catchUpBlocks) if err != nil { return nil, err } responses = append(responses, res) - v.logger.Debug( - "the validator is catching up by sending finality signatures in a batch", - zap.String("pk", v.GetBtcPkHex()), + fp.logger.Debug( + "the finality-provider is catching up by sending finality signatures in a batch", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("start_height", catchUpBlocks[0].Height), zap.Uint64("synced_height", syncedHeight), ) } - v.MustSetLastProcessedHeight(endHeight) + fp.MustSetLastProcessedHeight(endHeight) return &FastSyncResult{ Responses: responses, diff --git a/validator/service/fastsync_test.go b/finality-provider/service/fastsync_test.go similarity index 66% rename from validator/service/fastsync_test.go rename to finality-provider/service/fastsync_test.go index 74d43bb9..a0ca1583 100644 --- a/validator/service/fastsync_test.go +++ b/finality-provider/service/fastsync_test.go @@ -7,8 +7,8 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" ) func FuzzFastSync(f *testing.F) { @@ -21,20 +21,20 @@ func FuzzFastSync(f *testing.F) { currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) - app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) + fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) require.NoError(t, err) // commit public randomness expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) + res, err := fpIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). Return(uint64(1), nil).AnyTimes() // fast sync @@ -44,13 +44,13 @@ func FuzzFastSync(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(valIns.MustGetBtcPk(), catchUpBlocks, gomock.Any()). + mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.MustGetBtcPk(), catchUpBlocks, gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - result, err := valIns.FastSync(finalizedHeight+1, currentHeight) + 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, currentHeight, valIns.GetLastVotedHeight()) - require.Equal(t, currentHeight, valIns.GetLastProcessedHeight()) + require.Equal(t, currentHeight, fpIns.GetLastVotedHeight()) + require.Equal(t, currentHeight, fpIns.GetLastProcessedHeight()) }) } diff --git a/validator/service/validator_instance.go b/finality-provider/service/fp_instance.go similarity index 54% rename from validator/service/validator_instance.go rename to finality-provider/service/fp_instance.go index 7ec9322d..ce9f74b5 100644 --- a/validator/service/validator_instance.go +++ b/finality-provider/service/fp_instance.go @@ -17,20 +17,20 @@ import ( "go.uber.org/atomic" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" - "github.com/babylonchain/btc-validator/validator/proto" - valstore "github.com/babylonchain/btc-validator/validator/store" + "github.com/babylonchain/finality-provider/clientcontroller" + "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/types" ) -type ValidatorInstance struct { +type FinalityProviderInstance struct { bbnPk *secp256k1.PubKey btcPk *bbntypes.BIP340PubKey - state *valState - cfg *valcfg.Config + state *fpState + cfg *fpcfg.Config logger *zap.Logger em eotsmanager.EOTSManager @@ -51,34 +51,34 @@ type ValidatorInstance struct { quit chan struct{} } -// NewValidatorInstance returns a ValidatorInstance instance with the given Babylon public key -// the validator should be registered before -func NewValidatorInstance( - valPk *bbntypes.BIP340PubKey, - cfg *valcfg.Config, - s *valstore.ValidatorStore, +// NewFinalityProviderInstance returns a FinalityProviderInstance instance with the given Babylon public key +// the finality-provider should be registered before +func NewFinalityProviderInstance( + fpPk *bbntypes.BIP340PubKey, + cfg *fpcfg.Config, + s *fpstore.FinalityProviderStore, cc clientcontroller.ClientController, em eotsmanager.EOTSManager, passphrase string, errChan chan<- *CriticalError, logger *zap.Logger, -) (*ValidatorInstance, error) { - v, err := s.GetStoreValidator(valPk.MustMarshal()) +) (*FinalityProviderInstance, error) { + sfp, err := s.GetStoreFinalityProvider(fpPk.MustMarshal()) if err != nil { - return nil, fmt.Errorf("failed to retrive the validator %s from DB: %w", v.GetBabylonPkHexString(), err) + return nil, fmt.Errorf("failed to retrive the finality-provider %s from DB: %w", sfp.GetBabylonPkHexString(), err) } - // ensure the validator has been registered - if v.Status < proto.ValidatorStatus_REGISTERED { - return nil, fmt.Errorf("the validator %s has not been registered", v.KeyName) + // 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 &ValidatorInstance{ - btcPk: v.MustGetBIP340BTCPK(), - bbnPk: v.GetBabylonPK(), - state: &valState{ - v: v, - s: s, + return &FinalityProviderInstance{ + btcPk: sfp.MustGetBIP340BTCPK(), + bbnPk: sfp.GetBabylonPK(), + state: &fpState{ + fp: sfp, + s: s, }, cfg: cfg, logger: logger, @@ -92,57 +92,57 @@ func NewValidatorInstance( }, nil } -func (v *ValidatorInstance) Start() error { - if v.isStarted.Swap(true) { - return fmt.Errorf("the validator instance %s is already started", v.GetBtcPkHex()) +func (fp *FinalityProviderInstance) Start() error { + if fp.isStarted.Swap(true) { + return fmt.Errorf("the finality-provider instance %s is already started", fp.GetBtcPkHex()) } - v.logger.Info("Starting validator instance", zap.String("pk", v.GetBtcPkHex())) + fp.logger.Info("Starting finality-provider instance", zap.String("pk", fp.GetBtcPkHex())) - startHeight, err := v.bootstrap() + startHeight, err := fp.bootstrap() if err != nil { - return fmt.Errorf("failed to bootstrap the validator %s: %w", v.GetBtcPkHex(), err) + return fmt.Errorf("failed to bootstrap the finality-provider %s: %w", fp.GetBtcPkHex(), err) } - v.logger.Info("the validator %s has been bootstrapped", - zap.String("pk", v.GetBtcPkHex()), zap.Uint64("height", startHeight)) + fp.logger.Info("the finality-provider %s has been bootstrapped", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", startHeight)) - poller := NewChainPoller(v.logger, v.cfg.PollerConfig, v.cc) + poller := NewChainPoller(fp.logger, fp.cfg.PollerConfig, fp.cc) if err := poller.Start(startHeight + 1); err != nil { return fmt.Errorf("failed to start the poller: %w", err) } - v.poller = poller + fp.poller = poller - v.laggingTargetChan = make(chan *types.BlockInfo, 1) + fp.laggingTargetChan = make(chan *types.BlockInfo, 1) - v.quit = make(chan struct{}) + fp.quit = make(chan struct{}) - v.wg.Add(1) - go v.finalitySigSubmissionLoop() - v.wg.Add(1) - go v.randomnessCommitmentLoop() - v.wg.Add(1) - go v.checkLaggingLoop() + fp.wg.Add(1) + go fp.finalitySigSubmissionLoop() + fp.wg.Add(1) + go fp.randomnessCommitmentLoop() + fp.wg.Add(1) + go fp.checkLaggingLoop() return nil } -func (v *ValidatorInstance) bootstrap() (uint64, error) { - latestBlock, err := v.getLatestBlockWithRetry() +func (fp *FinalityProviderInstance) bootstrap() (uint64, error) { + latestBlock, err := fp.getLatestBlockWithRetry() if err != nil { return 0, err } - if v.checkLagging(latestBlock) { - _, err := v.tryFastSync(latestBlock) + if fp.checkLagging(latestBlock) { + _, err := fp.tryFastSync(latestBlock) if err != nil { return 0, err } } - startHeight, err := v.getPollerStartingHeight() + startHeight, err := fp.getPollerStartingHeight() if err != nil { return 0, err } @@ -150,222 +150,222 @@ func (v *ValidatorInstance) bootstrap() (uint64, error) { return startHeight, nil } -func (v *ValidatorInstance) Stop() error { - if !v.isStarted.Swap(false) { - return fmt.Errorf("the validator %s has already stopped", v.GetBtcPkHex()) +func (fp *FinalityProviderInstance) Stop() error { + if !fp.isStarted.Swap(false) { + return fmt.Errorf("the finality-provider %s has already stopped", fp.GetBtcPkHex()) } - if err := v.poller.Stop(); err != nil { + if err := fp.poller.Stop(); err != nil { return fmt.Errorf("failed to stop the poller: %w", err) } - v.logger.Info("stopping validator instance", zap.String("pk", v.GetBtcPkHex())) + fp.logger.Info("stopping finality-provider instance", zap.String("pk", fp.GetBtcPkHex())) - close(v.quit) - v.wg.Wait() + close(fp.quit) + fp.wg.Wait() - v.logger.Info("the validator instance %s is successfully stopped", zap.String("pk", v.GetBtcPkHex())) + fp.logger.Info("the finality-provider instance %s is successfully stopped", zap.String("pk", fp.GetBtcPkHex())) return nil } -func (v *ValidatorInstance) IsRunning() bool { - return v.isStarted.Load() +func (fp *FinalityProviderInstance) IsRunning() bool { + return fp.isStarted.Load() } -func (v *ValidatorInstance) finalitySigSubmissionLoop() { - defer v.wg.Done() +func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { + defer fp.wg.Done() for { select { - case b := <-v.poller.GetBlockInfoChan(): - v.logger.Debug( - "the validator received a new block, start processing", - zap.String("pk", v.GetBtcPkHex()), + case b := <-fp.poller.GetBlockInfoChan(): + fp.logger.Debug( + "the finality-provider received a new block, start processing", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", b.Height), ) - if b.Height <= v.GetLastProcessedHeight() { - v.logger.Debug( + if b.Height <= fp.GetLastProcessedHeight() { + fp.logger.Debug( "the block has been processed before, skip processing", zap.Uint64("height", b.Height), - zap.Uint64("last_processed_height", v.GetLastProcessedHeight()), - zap.Uint64("last_voted_height", v.GetLastVotedHeight()), + zap.Uint64("last_processed_height", fp.GetLastProcessedHeight()), + zap.Uint64("last_voted_height", fp.GetLastVotedHeight()), ) continue } // use the copy of the block to avoid the impact to other receivers nextBlock := *b - should, err := v.shouldSubmitFinalitySignature(&nextBlock) + should, err := fp.shouldSubmitFinalitySignature(&nextBlock) if err != nil { - v.reportCriticalErr(err) + fp.reportCriticalErr(err) continue } if !should { - v.MustSetLastProcessedHeight(nextBlock.Height) + fp.MustSetLastProcessedHeight(nextBlock.Height) continue } - res, err := v.retrySubmitFinalitySignatureUntilBlockFinalized(&nextBlock) + res, err := fp.retrySubmitFinalitySignatureUntilBlockFinalized(&nextBlock) if err != nil { - v.reportCriticalErr(err) + fp.reportCriticalErr(err) continue } if res == nil { - v.reportCriticalErr(fmt.Errorf("received an empty response when submitting finality sig")) + fp.reportCriticalErr(fmt.Errorf("received an empty response when submitting finality sig")) continue } - v.logger.Info( + fp.logger.Info( "successfully submitted a finality signature to the consumer chain", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", b.Height), zap.String("tx_hash", res.TxHash), ) - case targetBlock := <-v.laggingTargetChan: - res, err := v.tryFastSync(targetBlock) - v.isLagging.Store(false) + case targetBlock := <-fp.laggingTargetChan: + res, err := fp.tryFastSync(targetBlock) + fp.isLagging.Store(false) if err != nil { - if errors.Is(err, bstypes.ErrBTCValAlreadySlashed) { - v.reportCriticalErr(err) + if errors.Is(err, bstypes.ErrFpAlreadySlashed) { + fp.reportCriticalErr(err) continue } - v.logger.Debug( + fp.logger.Debug( "failed to sync up, will try again later", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Error(err), ) continue } // response might be nil if sync is not needed if res != nil { - v.logger.Info( + fp.logger.Info( "fast sync is finished", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("synced_height", res.SyncedHeight), zap.Uint64("last_processed_height", res.LastProcessedHeight), ) // set the poller to fetch blocks that have not been processed - v.poller.SetNextHeightAndClearBuffer(v.GetLastProcessedHeight() + 1) + fp.poller.SetNextHeightAndClearBuffer(fp.GetLastProcessedHeight() + 1) } - case <-v.quit: - v.logger.Info("the finality signature submission loop is closing") + case <-fp.quit: + fp.logger.Info("the finality signature submission loop is closing") return } } } -func (v *ValidatorInstance) randomnessCommitmentLoop() { - defer v.wg.Done() +func (fp *FinalityProviderInstance) randomnessCommitmentLoop() { + defer fp.wg.Done() - commitRandTicker := time.NewTicker(v.cfg.RandomnessCommitInterval) + commitRandTicker := time.NewTicker(fp.cfg.RandomnessCommitInterval) defer commitRandTicker.Stop() for { select { case <-commitRandTicker.C: - tipBlock, err := v.getLatestBlockWithRetry() + tipBlock, err := fp.getLatestBlockWithRetry() if err != nil { - v.reportCriticalErr(err) + fp.reportCriticalErr(err) continue } - txRes, err := v.retryCommitPubRandUntilBlockFinalized(tipBlock) + txRes, err := fp.retryCommitPubRandUntilBlockFinalized(tipBlock) if err != nil { - v.reportCriticalErr(err) + fp.reportCriticalErr(err) continue } // txRes could be nil if no need to commit more randomness if txRes != nil { - v.logger.Info( + fp.logger.Info( "successfully committed public randomness to the consumer chain", - zap.String("pk", v.GetBtcPkHex()), - zap.Uint64("last_committed_height", v.GetLastCommittedHeight()), + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("last_committed_height", fp.GetLastCommittedHeight()), zap.String("tx_hash", txRes.TxHash), ) } - case <-v.quit: - v.logger.Info("the randomness commitment loop is closing") + case <-fp.quit: + fp.logger.Info("the randomness commitment loop is closing") return } } } -func (v *ValidatorInstance) checkLaggingLoop() { - defer v.wg.Done() +func (fp *FinalityProviderInstance) checkLaggingLoop() { + defer fp.wg.Done() - if v.cfg.FastSyncInterval == 0 { - v.logger.Info("the fast sync is disabled") + if fp.cfg.FastSyncInterval == 0 { + fp.logger.Info("the fast sync is disabled") return } - fastSyncTicker := time.NewTicker(v.cfg.FastSyncInterval) + fastSyncTicker := time.NewTicker(fp.cfg.FastSyncInterval) defer fastSyncTicker.Stop() for { select { case <-fastSyncTicker.C: - if v.isLagging.Load() { + if fp.isLagging.Load() { // we are in fast sync mode, skip do not do checks continue } - latestBlock, err := v.getLatestBlockWithRetry() + latestBlock, err := fp.getLatestBlockWithRetry() if err != nil { - v.logger.Debug( + fp.logger.Debug( "failed to get the latest block of the consumer chain", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Error(err), ) continue } - if v.checkLagging(latestBlock) { - v.isLagging.Store(true) - v.laggingTargetChan <- latestBlock + if fp.checkLagging(latestBlock) { + fp.isLagging.Store(true) + fp.laggingTargetChan <- latestBlock } - case <-v.quit: - v.logger.Debug("the fast sync loop is closing") + case <-fp.quit: + fp.logger.Debug("the fast sync loop is closing") return } } } -func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSyncResult, error) { - if v.inSync.Load() { - return nil, fmt.Errorf("the validator %s is already in sync", v.GetBtcPkHex()) +func (fp *FinalityProviderInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSyncResult, error) { + if fp.inSync.Load() { + return nil, fmt.Errorf("the finality-provider %s is already in sync", fp.GetBtcPkHex()) } - if v.GetLastCommittedHeight() <= v.GetLastVotedHeight() { - if err := v.SetLastProcessedHeight(targetBlock.Height); err != nil { + if fp.GetLastCommittedHeight() <= fp.GetLastVotedHeight() { + if err := fp.SetLastProcessedHeight(targetBlock.Height); err != nil { return nil, err } - v.logger.Debug( + fp.logger.Debug( "insufficient public randomness, jumping to the latest block", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("target_height", targetBlock.Height), ) return nil, nil } // get the last finalized height - lastFinalizedBlocks, err := v.cc.QueryLatestFinalizedBlocks(1) + lastFinalizedBlocks, err := fp.cc.QueryLatestFinalizedBlocks(1) if err != nil { return nil, err } if lastFinalizedBlocks == nil { - v.logger.Debug( + fp.logger.Debug( "no finalized blocks yet, no need to catch up", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", targetBlock.Height), ) return nil, nil } lastFinalizedHeight := lastFinalizedBlocks[0].Height - lastProcessedHeight := v.GetLastProcessedHeight() + lastProcessedHeight := fp.GetLastProcessedHeight() // get the startHeight from the maximum of the lastVotedHeight and // the lastFinalizedHeight plus 1 @@ -380,49 +380,49 @@ func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSync return nil, fmt.Errorf("the start height %v should not be higher than the current block %v", startHeight, targetBlock.Height) } - v.logger.Debug("the validator is entering fast sync") + fp.logger.Debug("the finality-provider is entering fast sync") - return v.FastSync(startHeight, targetBlock.Height) + return fp.FastSync(startHeight, targetBlock.Height) } // shouldSubmitFinalitySignature checks all the conditions that a finality should not be sent: -// 1. the validator does not have voting power on the given block -// 2. the last committed height is lower than the block height as this indicates the validator +// 1. the finality-provider does not have voting power on the given block +// 2. the last committed height is lower than the block height as this indicates the finality-provider // does not have the corresponding public randomness -// 3. the block height is lower than the last voted height as this indicates that the validator +// 3. the block height is lower than the last voted height as this indicates that the finality-provider // does not need to send finality signature over this block -func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (bool, error) { +func (fp *FinalityProviderInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (bool, error) { // check last voted height - if v.GetLastVotedHeight() >= b.Height { - v.logger.Debug( + if fp.GetLastVotedHeight() >= b.Height { + fp.logger.Debug( "the block has been voted before, skip voting", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), - zap.Uint64("last_voted_height", v.GetLastVotedHeight()), + zap.Uint64("last_voted_height", fp.GetLastVotedHeight()), ) return false, nil } // check last committed height - if v.GetLastCommittedHeight() < b.Height { - v.logger.Debug( + if fp.GetLastCommittedHeight() < b.Height { + fp.logger.Debug( "public rand is not committed, skip voting", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), - zap.Uint64("last_committed_height", v.GetLastCommittedHeight()), + zap.Uint64("last_committed_height", fp.GetLastCommittedHeight()), ) return false, nil } - power, err := v.GetVotingPowerWithRetry(b.Height) + power, err := fp.GetVotingPowerWithRetry(b.Height) if err != nil { return false, err } if power == 0 { - v.logger.Debug( - "the validator does not have voting power, skip voting", - zap.String("pk", v.GetBtcPkHex()), + fp.logger.Debug( + "the finality-provider does not have voting power, skip voting", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), ) return false, nil @@ -431,42 +431,42 @@ func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (b return true, nil } -func (v *ValidatorInstance) reportCriticalErr(err error) { - v.criticalErrChan <- &CriticalError{ - err: err, - valBtcPk: v.GetBtcPkBIP340(), +func (fp *FinalityProviderInstance) reportCriticalErr(err error) { + fp.criticalErrChan <- &CriticalError{ + err: err, + fpBtcPk: fp.GetBtcPkBIP340(), } } // checkLagging returns true if the lasted voted height is behind by a configured gap -func (v *ValidatorInstance) checkLagging(currentBlock *types.BlockInfo) bool { - return currentBlock.Height >= v.GetLastProcessedHeight()+v.cfg.FastSyncGap +func (fp *FinalityProviderInstance) checkLagging(currentBlock *types.BlockInfo) bool { + return currentBlock.Height >= fp.GetLastProcessedHeight()+fp.cfg.FastSyncGap } // 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 (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { +func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { var failedCycles uint32 // we break the for loop if the block is finalized or the signature is successfully submitted // 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 := v.SubmitFinalitySignature(targetBlock) + res, err := fp.SubmitFinalitySignature(targetBlock) if err != nil { if clientcontroller.IsUnrecoverable(err) { return nil, err } - v.logger.Debug( + fp.logger.Debug( "failed to submit finality signature to the consumer chain", - zap.String("pk", v.GetBtcPkHex()), + 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(v.cfg.MaxSubmissionRetries) { + if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { return nil, fmt.Errorf("reached max failed cycles with err: %w", err) } } else { @@ -474,30 +474,30 @@ func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targ return res, nil } select { - case <-time.After(v.cfg.SubmissionRetryInterval): + case <-time.After(fp.cfg.SubmissionRetryInterval): // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.checkBlockFinalization(targetBlock.Height) + 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 { - v.logger.Debug( + fp.logger.Debug( "the block is already finalized, skip submission", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("target_height", targetBlock.Height), ) return nil, nil } - case <-v.quit: - v.logger.Debug("the validator instance is closing", zap.String("pk", v.GetBtcPkHex())) + case <-fp.quit: + fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) return nil, nil } } } -func (v *ValidatorInstance) checkBlockFinalization(height uint64) (bool, error) { - b, err := v.cc.QueryBlock(height) +func (fp *FinalityProviderInstance) checkBlockFinalization(height uint64) (bool, error) { + b, err := fp.cc.QueryBlock(height) if err != nil { return false, err } @@ -507,28 +507,28 @@ func (v *ValidatorInstance) checkBlockFinalization(height uint64) (bool, error) // 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 (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { +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 := v.CommitPubRand(targetBlock) + res, err := fp.CommitPubRand(targetBlock) if err != nil { if clientcontroller.IsUnrecoverable(err) { return nil, err } - v.logger.Debug( + fp.logger.Debug( "failed to commit public randomness to the consumer chain", - zap.String("pk", v.GetBtcPkHex()), + 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(v.cfg.MaxSubmissionRetries) { + if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { return nil, fmt.Errorf("reached max failed cycles with err: %w", err) } } else { @@ -536,48 +536,48 @@ func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *t return res, nil } select { - case <-time.After(v.cfg.SubmissionRetryInterval): + case <-time.After(fp.cfg.SubmissionRetryInterval): // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.checkBlockFinalization(targetBlock.Height) + 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 { - v.logger.Debug( + fp.logger.Debug( "the block is already finalized, skip submission", - zap.String("pk", v.GetBtcPkHex()), + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("target_height", targetBlock.Height), ) return nil, nil } - case <-v.quit: - v.logger.Debug("the validator instance is closing", zap.String("pk", v.GetBtcPkHex())) + 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 validators, +// commits the public randomness for the managed finality providers, // and save the randomness pair to DB -func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxResponse, error) { - lastCommittedHeight := v.GetLastCommittedHeight() +func (fp *FinalityProviderInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxResponse, error) { + lastCommittedHeight := fp.GetLastCommittedHeight() var startHeight uint64 if lastCommittedHeight == uint64(0) { - // the validator has never submitted public rand before + // 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 < v.cfg.MinRandHeightGap+tipBlock.Height { + } else if lastCommittedHeight < fp.cfg.MinRandHeightGap+tipBlock.Height { // we are running out of the randomness startHeight = lastCommittedHeight + 1 } else { - v.logger.Debug( - "the validator has sufficient public randomness, skip committing more", - zap.String("pk", v.GetBtcPkHex()), + 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", v.GetLastCommittedHeight()), + zap.Uint64("last_committed_height", fp.GetLastCommittedHeight()), ) return nil, nil } @@ -588,14 +588,14 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxR // 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 := v.createPubRandList(startHeight) + 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{ - ValBtcPk: v.btcPk, + FpBtcPk: fp.btcPk, StartHeight: startHeight, PubRandList: pubRandList, } @@ -604,8 +604,8 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxR return nil, fmt.Errorf("failed to sign the commit public randomness message: %w", err) } - // sign the message hash using the validator's BTC private key - schnorrSig, err := v.em.SignSchnorrSig(v.btcPk.MustMarshal(), hash, v.passphrase) + // 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) } @@ -614,26 +614,26 @@ func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxR for _, r := range pubRandList { pubRandByteList = append(pubRandByteList, r.ToFieldVal()) } - res, err := v.cc.CommitPubRandList(v.MustGetBtcPk(), startHeight, pubRandByteList, schnorrSig) + res, err := fp.cc.CommitPubRandList(fp.MustGetBtcPk(), startHeight, pubRandByteList, schnorrSig) if err != nil { - // TODO Add retry. check issue: https://github.com/babylonchain/btc-validator/issues/34 + // 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) } newLastCommittedHeight := startHeight + uint64(len(pubRandList)-1) - v.MustSetLastCommittedHeight(newLastCommittedHeight) + fp.MustSetLastCommittedHeight(newLastCommittedHeight) return res, nil } -func (v *ValidatorInstance) createPubRandList(startHeight uint64) ([]bbntypes.SchnorrPubRand, error) { - pubRandList, err := v.em.CreateRandomnessPairList( - v.btcPk.MustMarshal(), - v.GetChainID(), +func (fp *FinalityProviderInstance) createPubRandList(startHeight uint64) ([]bbntypes.SchnorrPubRand, error) { + pubRandList, err := fp.em.CreateRandomnessPairList( + fp.btcPk.MustMarshal(), + fp.GetChainID(), startHeight, - uint32(v.cfg.NumPubRand), - v.passphrase, + uint32(fp.cfg.NumPubRand), + fp.passphrase, ) if err != nil { return nil, err @@ -648,34 +648,34 @@ func (v *ValidatorInstance) createPubRandList(startHeight uint64) ([]bbntypes.Sc } // SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain -func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*types.TxResponse, error) { - eotsSig, err := v.signEotsSig(b) +func (fp *FinalityProviderInstance) SubmitFinalitySignature(b *types.BlockInfo) (*types.TxResponse, error) { + eotsSig, err := fp.signEotsSig(b) if err != nil { return nil, err } // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) if err != nil { return nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) } // update DB - v.MustUpdateStateAfterFinalitySigSubmission(b.Height) + fp.MustUpdateStateAfterFinalitySigSubmission(b.Height) return res, nil } // SubmitBatchFinalitySignatures builds and sends a finality signature over the given block to the consumer chain // NOTE: the input blocks should be in the ascending order of height -func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*types.TxResponse, error) { +func (fp *FinalityProviderInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*types.TxResponse, error) { if len(blocks) == 0 { return nil, fmt.Errorf("should not submit batch finality signature with zero block") } sigs := make([]*btcec.ModNScalar, 0, len(blocks)) for _, b := range blocks { - eotsSig, err := v.signEotsSig(b) + eotsSig, err := fp.signEotsSig(b) if err != nil { return nil, err } @@ -683,27 +683,27 @@ func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockI } // send finality signature to the consumer chain - res, err := v.cc.SubmitBatchFinalitySigs(v.MustGetBtcPk(), blocks, sigs) + res, err := fp.cc.SubmitBatchFinalitySigs(fp.MustGetBtcPk(), blocks, sigs) if err != nil { return nil, fmt.Errorf("failed to send a batch of finality signatures to the consumer chain: %w", err) } // update DB highBlock := blocks[len(blocks)-1] - v.MustUpdateStateAfterFinalitySigSubmission(highBlock.Height) + fp.MustUpdateStateAfterFinalitySigSubmission(highBlock.Height) return res, nil } -func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { +func (fp *FinalityProviderInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { // build proper finality signature request msg := &ftypes.MsgAddFinalitySig{ - ValBtcPk: v.btcPk, + FpBtcPk: fp.btcPk, BlockHeight: b.Height, BlockAppHash: b.Hash, } msgToSign := msg.MsgToSign() - sig, err := v.em.SignEOTS(v.btcPk.MustMarshal(), v.GetChainID(), msgToSign, b.Height, v.passphrase) + sig, err := fp.em.SignEOTS(fp.btcPk.MustMarshal(), fp.GetChainID(), msgToSign, b.Height, fp.passphrase) if err != nil { return nil, fmt.Errorf("failed to sign EOTS: %w", err) } @@ -714,20 +714,20 @@ func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEO // TestSubmitFinalitySignatureAndExtractPrivKey is exposed for presentation/testing purpose to allow manual sending finality signature // 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 (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { +func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { // check last committed height - if v.GetLastCommittedHeight() < b.Height { - return nil, nil, fmt.Errorf("the validator's last committed height %v is lower than the current block height %v", - v.GetLastCommittedHeight(), b.Height) + if fp.GetLastCommittedHeight() < b.Height { + return nil, nil, fmt.Errorf("the finality-provider's last committed height %v is lower than the current block height %v", + fp.GetLastCommittedHeight(), b.Height) } - eotsSig, err := v.signEotsSig(b) + eotsSig, err := fp.signEotsSig(b) if err != nil { return nil, nil, err } // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), 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) } @@ -735,9 +735,9 @@ func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *type // try to extract the private key var privKey *btcec.PrivateKey for _, ev := range res.Events { - if strings.Contains(ev.EventType, "EventSlashedBTCValidator") { + if strings.Contains(ev.EventType, "EventSlashedFinalityProvider") { evidenceStr := ev.Attributes["evidence"] - v.logger.Debug("found slashing evidence") + fp.logger.Debug("found slashing evidence") var evidence ftypes.Evidence if err := jsonpb.UnmarshalString(evidenceStr, &evidence); err != nil { return nil, nil, fmt.Errorf("failed to decode evidence bytes to evidence: %s", err.Error()) @@ -753,9 +753,9 @@ func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *type return res, privKey, nil } -func (v *ValidatorInstance) getPollerStartingHeight() (uint64, error) { - if !v.cfg.PollerConfig.AutoChainScanningMode { - return v.cfg.PollerConfig.StaticChainScanningStartHeight, nil +func (fp *FinalityProviderInstance) getPollerStartingHeight() (uint64, error) { + if !fp.cfg.PollerConfig.AutoChainScanningMode { + return fp.cfg.PollerConfig.StaticChainScanningStartHeight, nil } // Set initial block to the maximum of @@ -763,12 +763,12 @@ func (v *ValidatorInstance) getPollerStartingHeight() (uint64, error) { // - the latest Babylon finalised height // The above is to ensure that: // - // (1) Any validator that is eligible to vote for a block, + // (1) Any finality-provider that is eligible to vote for a block, // doesn't miss submitting a vote for it. - // (2) The validators do not submit signatures for any already + // (2) The finality providers do not submit signatures for any already // finalised blocks. - initialBlockToGet := v.GetLastProcessedHeight() - latestFinalisedBlock, err := v.latestFinalizedBlocksWithRetry(1) + initialBlockToGet := fp.GetLastProcessedHeight() + latestFinalisedBlock, err := fp.latestFinalizedBlocksWithRetry(1) if err != nil { return 0, err } @@ -785,17 +785,17 @@ func (v *ValidatorInstance) getPollerStartingHeight() (uint64, error) { return initialBlockToGet, nil } -func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*types.BlockInfo, error) { +func (fp *FinalityProviderInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*types.BlockInfo, error) { var response []*types.BlockInfo if err := retry.Do(func() error { - latestFinalisedBlock, err := v.cc.QueryLatestFinalizedBlocks(count) + latestFinalisedBlock, err := fp.cc.QueryLatestFinalizedBlocks(count) if err != nil { return err } response = latestFinalisedBlock return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.Debug( + fp.logger.Debug( "failed to query babylon for the latest finalised blocks", zap.Uint("attempt", n+1), zap.Uint("max_attempts", RtyAttNum), @@ -807,20 +807,20 @@ func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*typ return response, nil } -func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { +func (fp *FinalityProviderInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { var ( latestBlock *types.BlockInfo err error ) if err := retry.Do(func() error { - latestBlock, err = v.cc.QueryBestBlock() + latestBlock, err = fp.cc.QueryBestBlock() if err != nil { return err } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.Debug( + fp.logger.Debug( "failed to query the consumer chain for the latest block", zap.Uint("attempt", n+1), zap.Uint("max_attempts", RtyAttNum), @@ -833,20 +833,20 @@ func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) return latestBlock, nil } -func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, error) { +func (fp *FinalityProviderInstance) GetVotingPowerWithRetry(height uint64) (uint64, error) { var ( power uint64 err error ) if err := retry.Do(func() error { - power, err = v.cc.QueryValidatorVotingPower(v.MustGetBtcPk(), height) + power, err = fp.cc.QueryFinalityProviderVotingPower(fp.MustGetBtcPk(), height) if err != nil { return err } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.Debug( + fp.logger.Debug( "failed to query the voting power", zap.Uint("attempt", n+1), zap.Uint("max_attempts", RtyAttNum), @@ -859,21 +859,21 @@ func (v *ValidatorInstance) GetVotingPowerWithRetry(height uint64) (uint64, erro return power, nil } -func (v *ValidatorInstance) GetValidatorSlashedWithRetry() (bool, error) { +func (fp *FinalityProviderInstance) GetFinalityProviderSlashedWithRetry() (bool, error) { var ( slashed bool err error ) if err := retry.Do(func() error { - slashed, err = v.cc.QueryValidatorSlashed(v.MustGetBtcPk()) + slashed, err = fp.cc.QueryFinalityProviderSlashed(fp.MustGetBtcPk()) if err != nil { return err } return nil }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.Debug( - "failed to query the validator", + fp.logger.Debug( + "failed to query the finality-provider", zap.Uint("attempt", n+1), zap.Uint("max_attempts", RtyAttNum), zap.Error(err), diff --git a/validator/service/validator_instance_test.go b/finality-provider/service/fp_instance_test.go similarity index 55% rename from validator/service/validator_instance_test.go rename to finality-provider/service/fp_instance_test.go index 1e92f2fc..6cf19ac7 100644 --- a/validator/service/validator_instance_test.go +++ b/finality-provider/service/fp_instance_test.go @@ -10,12 +10,12 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/validator/service" + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" ) func FuzzCommitPubRandList(f *testing.F) { @@ -28,24 +28,24 @@ func FuzzCommitPubRandList(f *testing.F) { startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() - valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) + fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) require.NoError(t, err) expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) + res, err := fpIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) // check the last_committed_height numPubRand := app.GetConfig().NumPubRand - require.Equal(t, startingBlock.Height+numPubRand, valIns.GetStoreValidator().LastCommittedHeight) + require.Equal(t, startingBlock.Height+numPubRand, fpIns.GetStoreFinalityProvider().LastCommittedHeight) }) } @@ -59,22 +59,22 @@ func FuzzSubmitFinalitySig(f *testing.F) { startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := startValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) + app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). Return(uint64(0), nil).AnyTimes() - valIns, err := app.GetValidatorInstance(storeValidator.MustGetBIP340BTCPK()) + fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) require.NoError(t, err) // commit public randomness expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - CommitPubRandList(valIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) + res, err := fpIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). Return(uint64(1), nil).AnyTimes() // submit finality sig @@ -84,19 +84,19 @@ func FuzzSubmitFinalitySig(f *testing.F) { } expectedTxHash = testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). - SubmitFinalitySig(valIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). + SubmitFinalitySig(fpIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - providerRes, err := valIns.SubmitFinalitySignature(nextBlock) + providerRes, err := fpIns.SubmitFinalitySignature(nextBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, providerRes.TxHash) // check the last_voted_height - require.Equal(t, nextBlock.Height, valIns.GetLastVotedHeight()) - require.Equal(t, nextBlock.Height, valIns.GetLastProcessedHeight()) + require.Equal(t, nextBlock.Height, fpIns.GetLastVotedHeight()) + require.Equal(t, nextBlock.Height, fpIns.GetLastProcessedHeight()) }) } -func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.ValidatorApp, *proto.StoreValidator, func()) { +func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.FinalityProviderApp, *proto.StoreFinalityProvider, func()) { logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") @@ -104,22 +104,22 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) require.NoError(t, err) - // create validator app with randomized config - valHomeDir := filepath.Join(t.TempDir(), "val-home") - valCfg := testutil.GenValConfig(r, t, valHomeDir) - valCfg.NumPubRand = uint64(25) - valCfg.PollerConfig.AutoChainScanningMode = false - valCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight - app, err := service.NewValidatorApp(valHomeDir, valCfg, cc, em, logger) + // create finality-provider app with randomized config + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.NumPubRand = uint64(25) + fpCfg.PollerConfig.AutoChainScanningMode = false + fpCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight + app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, cc, em, logger) require.NoError(t, err) err = app.Start() require.NoError(t, err) - // create registered validator - validator := testutil.GenStoredValidator(r, t, app, passphrase, hdPath) - err = app.GetValidatorStore().SetValidatorStatus(validator, proto.ValidatorStatus_REGISTERED) + // create registered finality-provider + fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) + err = app.GetFinalityProviderStore().SetFinalityProviderStatus(fp, proto.FinalityProviderStatus_REGISTERED) require.NoError(t, err) - err = app.StartHandlingValidator(validator.MustGetBIP340BTCPK(), passphrase) + err = app.StartHandlingFinalityProvider(fp.MustGetBIP340BTCPK(), passphrase) require.NoError(t, err) cleanUp := func() { @@ -127,9 +127,9 @@ func startValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc cli require.NoError(t, err) err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) - err = os.RemoveAll(valHomeDir) + err = os.RemoveAll(fpHomeDir) require.NoError(t, err) } - return app, validator, cleanUp + return app, fp, cleanUp } diff --git a/finality-provider/service/fp_manager.go b/finality-provider/service/fp_manager.go new file mode 100644 index 00000000..c1d176b4 --- /dev/null +++ b/finality-provider/service/fp_manager.go @@ -0,0 +1,344 @@ +package service + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/avast/retry-go/v4" + bbntypes "github.com/babylonchain/babylon/types" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + "go.uber.org/atomic" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + "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/types" +) + +const instanceTerminatingMsg = "terminating the finality-provider instance due to critical error" + +type CriticalError struct { + err error + fpBtcPk *bbntypes.BIP340PubKey +} + +func (ce *CriticalError) Error() string { + return fmt.Sprintf("critical err on finality-provider %s: %s", ce.fpBtcPk.MarshalHex(), ce.err.Error()) +} + +type FinalityProviderManager struct { + isStarted *atomic.Bool + + mu sync.Mutex + wg sync.WaitGroup + + // running finality-provider instances map keyed by the hex string of the BTC public key + fpis map[string]*FinalityProviderInstance + + // needed for initiating finality-provider instances + fps *fpstore.FinalityProviderStore + config *fpcfg.Config + cc clientcontroller.ClientController + em eotsmanager.EOTSManager + logger *zap.Logger + + criticalErrChan chan *CriticalError + + quit chan struct{} +} + +func NewFinalityProviderManager(fps *fpstore.FinalityProviderStore, + config *fpcfg.Config, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + logger *zap.Logger, +) (*FinalityProviderManager, error) { + return &FinalityProviderManager{ + fpis: make(map[string]*FinalityProviderInstance), + criticalErrChan: make(chan *CriticalError), + isStarted: atomic.NewBool(false), + fps: fps, + config: config, + cc: cc, + em: em, + logger: logger, + quit: make(chan struct{}), + }, nil +} + +// monitorCriticalErr takes actions when it receives critical errors from a finality-provider instance +// if the finality-provider is slashed, it will be terminated and the program keeps running in case +// new finality providers join +// otherwise, the program will panic +func (fpm *FinalityProviderManager) monitorCriticalErr() { + defer fpm.wg.Done() + + var criticalErr *CriticalError + for { + select { + case criticalErr = <-fpm.criticalErrChan: + fpi, err := fpm.GetFinalityProviderInstance(criticalErr.fpBtcPk) + if err != nil { + panic(fmt.Errorf("failed to get the finality-provider instance: %w", err)) + } + if errors.Is(criticalErr.err, btcstakingtypes.ErrFpAlreadySlashed) { + fpm.setFinalityProviderSlashed(fpi) + fpm.logger.Debug("the finality-provider has been slashed", + zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) + continue + } + fpi.logger.Fatal(instanceTerminatingMsg, + zap.String("pk", criticalErr.fpBtcPk.MarshalHex()), zap.Error(criticalErr.err)) + case <-fpm.quit: + return + } + } +} + +// monitorStatusUpdate periodically check the status of each managed finality providers and update +// it accordingly. We update the status by querying the latest voting power and the slashed_height. +// In particular, we perform the following status transitions (REGISTERED, ACTIVE, INACTIVE, SLASHED): +// 1. if power == 0 and slashed_height == 0, if status == ACTIVE, change to INACTIVE, otherwise remain the same +// 2. if power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the finality-provider instance +// 3. if power > 0 (slashed_height must > 0), set status to ACTIVE +// NOTE: once error occurs, we log and continue as the status update is not critical to the entire program +func (fpm *FinalityProviderManager) monitorStatusUpdate() { + defer fpm.wg.Done() + + if fpm.config.StatusUpdateInterval == 0 { + fpm.logger.Info("the status update is disabled") + return + } + + statusUpdateTicker := time.NewTicker(fpm.config.StatusUpdateInterval) + defer statusUpdateTicker.Stop() + + for { + select { + case <-statusUpdateTicker.C: + latestBlock, err := fpm.getLatestBlockWithRetry() + if err != nil { + fpm.logger.Debug("failed to get the latest block", zap.Error(err)) + continue + } + fpis := fpm.ListFinalityProviderInstances() + for _, fpi := range fpis { + oldStatus := fpi.GetStatus() + power, err := fpi.GetVotingPowerWithRetry(latestBlock.Height) + if err != nil { + fpm.logger.Debug( + "failed to get the voting power", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.Uint64("height", latestBlock.Height), + zap.Error(err), + ) + continue + } + // power > 0 (slashed_height must > 0), set status to ACTIVE + if power > 0 { + if oldStatus != proto.FinalityProviderStatus_ACTIVE { + fpi.MustSetStatus(proto.FinalityProviderStatus_ACTIVE) + fpm.logger.Debug( + "the finality-provider status is changed to ACTIVE", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + zap.Uint64("power", power), + ) + } + continue + } + slashed, err := fpi.GetFinalityProviderSlashedWithRetry() + if err != nil { + fpm.logger.Debug( + "failed to get the slashed height", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.Error(err), + ) + continue + } + // power == 0 and slashed == true, set status to SLASHED and stop and remove the finality-provider instance + if slashed { + fpm.setFinalityProviderSlashed(fpi) + fpm.logger.Debug( + "the finality-provider is slashed", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) + continue + } + // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE + if oldStatus == proto.FinalityProviderStatus_ACTIVE { + fpi.MustSetStatus(proto.FinalityProviderStatus_INACTIVE) + fpm.logger.Debug( + "the finality-provider status is changed to INACTIVE", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) + } + } + case <-fpm.quit: + return + } + } +} + +func (fpm *FinalityProviderManager) setFinalityProviderSlashed(fpi *FinalityProviderInstance) { + fpi.MustSetStatus(proto.FinalityProviderStatus_SLASHED) + if err := fpm.removeFinalityProviderInstance(fpi.GetBtcPkBIP340()); err != nil { + panic(fmt.Errorf("failed to terminate a slashed finality-provider %s: %w", fpi.GetBtcPkHex(), err)) + } +} + +func (fpm *FinalityProviderManager) StartFinalityProvider(fpPk *bbntypes.BIP340PubKey, passphrase string) error { + if !fpm.isStarted.Load() { + fpm.isStarted.Store(true) + + fpm.wg.Add(1) + go fpm.monitorCriticalErr() + + fpm.wg.Add(1) + go fpm.monitorStatusUpdate() + } + + if fpm.numOfRunningFinalityProviders() >= int(fpm.config.MaxNumFinalityProviders) { + return fmt.Errorf("reaching maximum number of running finality providers %v", fpm.config.MaxNumFinalityProviders) + } + + if err := fpm.addFinalityProviderInstance(fpPk, passphrase); err != nil { + return err + } + + return nil +} + +func (fpm *FinalityProviderManager) Stop() error { + if !fpm.isStarted.Swap(false) { + return fmt.Errorf("the finality-provider manager has already stopped") + } + + var stopErr error + + for _, fpi := range fpm.fpis { + if !fpi.IsRunning() { + continue + } + if err := fpi.Stop(); err != nil { + stopErr = err + break + } + } + + close(fpm.quit) + fpm.wg.Wait() + + return stopErr +} + +func (fpm *FinalityProviderManager) ListFinalityProviderInstances() []*FinalityProviderInstance { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + fpisList := make([]*FinalityProviderInstance, 0, len(fpm.fpis)) + for _, fpi := range fpm.fpis { + fpisList = append(fpisList, fpi) + } + + return fpisList +} + +func (fpm *FinalityProviderManager) GetFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) (*FinalityProviderInstance, error) { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + keyHex := fpPk.MarshalHex() + v, exists := fpm.fpis[keyHex] + if !exists { + return nil, fmt.Errorf("cannot find the finality-provider instance with PK: %s", keyHex) + } + + return v, nil +} + +func (fpm *FinalityProviderManager) removeFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) error { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + keyHex := fpPk.MarshalHex() + fpi, exists := fpm.fpis[keyHex] + if !exists { + return fmt.Errorf("cannot find the finality-provider instance with PK: %s", keyHex) + } + if fpi.IsRunning() { + if err := fpi.Stop(); err != nil { + return fmt.Errorf("failed to stop the finality-provider instance %s", keyHex) + } + } + + delete(fpm.fpis, keyHex) + return nil +} + +func (fpm *FinalityProviderManager) numOfRunningFinalityProviders() int { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + return len(fpm.fpis) +} + +// addFinalityProviderInstance creates a finality-provider instance, starts it and adds it into the finality-provider manager +func (fpm *FinalityProviderManager) addFinalityProviderInstance( + pk *bbntypes.BIP340PubKey, + passphrase string, +) error { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + pkHex := pk.MarshalHex() + if _, exists := fpm.fpis[pkHex]; exists { + 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) + if err != nil { + return fmt.Errorf("failed to create finality-provider %s instance: %w", pkHex, err) + } + + if err := fpIns.Start(); err != nil { + return fmt.Errorf("failed to start finality-provider %s instance: %w", pkHex, err) + } + + fpm.fpis[pkHex] = fpIns + + return nil +} + +func (fpm *FinalityProviderManager) getLatestBlockWithRetry() (*types.BlockInfo, error) { + var ( + latestBlock *types.BlockInfo + err error + ) + + if err := retry.Do(func() error { + latestBlock, err = fpm.cc.QueryBestBlock() + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fpm.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + + return latestBlock, nil +} diff --git a/validator/service/validator_manager_test.go b/finality-provider/service/fp_manager_test.go similarity index 50% rename from validator/service/validator_manager_test.go rename to finality-provider/service/fp_manager_test.go index 94831315..841cecd7 100644 --- a/validator/service/validator_manager_test.go +++ b/finality-provider/service/fp_manager_test.go @@ -1,8 +1,8 @@ package service_test import ( - "github.com/babylonchain/btc-validator/util" - valcfg "github.com/babylonchain/btc-validator/validator/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/util" "math/rand" "os" "path/filepath" @@ -12,22 +12,22 @@ import ( "go.uber.org/zap" - "github.com/babylonchain/btc-validator/keyring" + "github.com/babylonchain/finality-provider/keyring" "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/testutil/mocks" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/validator/service" - valstore "github.com/babylonchain/btc-validator/validator/store" + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -42,7 +42,7 @@ func FuzzStatusUpdate(f *testing.F) { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) - vm, valPk, cleanUp := newValidatorManagerWithRegisteredValidator(t, r, mockClientController) + vm, fpPk, cleanUp := newFinalityProviderManagerWithRegisteredFp(t, r, mockClientController) defer cleanUp() // setup mocks @@ -59,39 +59,39 @@ func FuzzStatusUpdate(f *testing.F) { mockClientController.EXPECT().QueryBlock(gomock.Any()).Return(currentBlockRes, nil).AnyTimes() votingPower := uint64(r.Intn(2)) - mockClientController.EXPECT().QueryValidatorVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() var slashedHeight uint64 if votingPower == 0 { - mockClientController.EXPECT().QueryValidatorSlashed(gomock.Any()).Return(true, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderSlashed(gomock.Any()).Return(true, nil).AnyTimes() } - err := vm.StartValidator(valPk, passphrase) + err := vm.StartFinalityProvider(fpPk, passphrase) require.NoError(t, err) - valIns := vm.ListValidatorInstances()[0] - // stop the validator as we are testing static functionalities - err = valIns.Stop() + fpIns := vm.ListFinalityProviderInstances()[0] + // stop the finality-provider as we are testing static functionalities + err = fpIns.Stop() require.NoError(t, err) if votingPower > 0 { - waitForStatus(t, valIns, proto.ValidatorStatus_ACTIVE) + waitForStatus(t, fpIns, proto.FinalityProviderStatus_ACTIVE) } else { - if slashedHeight == 0 && valIns.GetStatus() == proto.ValidatorStatus_ACTIVE { - waitForStatus(t, valIns, proto.ValidatorStatus_INACTIVE) + if slashedHeight == 0 && fpIns.GetStatus() == proto.FinalityProviderStatus_ACTIVE { + waitForStatus(t, fpIns, proto.FinalityProviderStatus_INACTIVE) } else if slashedHeight > 0 { - waitForStatus(t, valIns, proto.ValidatorStatus_SLASHED) + waitForStatus(t, fpIns, proto.FinalityProviderStatus_SLASHED) } } }) } -func waitForStatus(t *testing.T, valIns *service.ValidatorInstance, s proto.ValidatorStatus) { +func waitForStatus(t *testing.T, fpIns *service.FinalityProviderInstance, s proto.FinalityProviderStatus) { require.Eventually(t, func() bool { - return valIns.GetStatus() == s + return fpIns.GetStatus() == s }, eventuallyWaitTimeOut, eventuallyPollTime) } -func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.ValidatorManager, *bbntypes.BIP340PubKey, func()) { +func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.FinalityProviderManager, *bbntypes.BIP340PubKey, func()) { logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") @@ -99,31 +99,31 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) require.NoError(t, err) - // create validator app with randomized config - valHomeDir := filepath.Join(t.TempDir(), "val-home") - valCfg := testutil.GenValConfig(r, t, valHomeDir) - valCfg.StatusUpdateInterval = 10 * time.Millisecond + // create finality-provider app with randomized config + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.StatusUpdateInterval = 10 * time.Millisecond input := strings.NewReader("") kr, err := keyring.CreateKeyring( - valCfg.BabylonConfig.KeyDirectory, - valCfg.BabylonConfig.ChainID, - valCfg.BabylonConfig.KeyringBackend, + fpCfg.BabylonConfig.KeyDirectory, + fpCfg.BabylonConfig.ChainID, + fpCfg.BabylonConfig.KeyringBackend, input, ) require.NoError(t, err) - err = util.MakeDirectory(valcfg.DataDir(valHomeDir)) + err = util.MakeDirectory(fpcfg.DataDir(fpHomeDir)) require.NoError(t, err) - valStore, err := valstore.NewValidatorStore( - valcfg.DBPath(valHomeDir), - valCfg.DatabaseConfig.Name, - valCfg.DatabaseConfig.Backend, + fpStore, err := fpstore.NewFinalityProviderStore( + fpcfg.DBPath(fpHomeDir), + fpCfg.DatabaseConfig.Name, + fpCfg.DatabaseConfig.Backend, ) require.NoError(t, err) - vm, err := service.NewValidatorManager(valStore, valCfg, cc, em, logger) + vm, err := service.NewFinalityProviderManager(fpStore, fpCfg, cc, em, logger) require.NoError(t, err) - // create registered validator + // create registered finality-provider keyName := datagen.GenRandomHexStr(r, 10) chainID := datagen.GenRandomHexStr(r, 10) kc, err := keyring.NewChainKeyringControllerWithKeyring(kr, keyName, input) @@ -135,14 +135,14 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c keyPair, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} - valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) + fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) - pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) + pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) require.NoError(t, err) - storedValidator := valstore.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) - storedValidator.Status = proto.ValidatorStatus_REGISTERED - err = valStore.SaveValidator(storedValidator) + storedFp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + storedFp.Status = proto.FinalityProviderStatus_REGISTERED + err = fpStore.SaveFinalityProvider(storedFp) require.NoError(t, err) cleanUp := func() { @@ -150,7 +150,7 @@ func newValidatorManagerWithRegisteredValidator(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) err = os.RemoveAll(eotsHomeDir) require.NoError(t, err) - err = os.RemoveAll(valHomeDir) + err = os.RemoveAll(fpHomeDir) require.NoError(t, err) } diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go new file mode 100644 index 00000000..77438fb8 --- /dev/null +++ b/finality-provider/service/rpcserver.go @@ -0,0 +1,210 @@ +package service + +import ( + "context" + "encoding/hex" + "fmt" + "sync" + "sync/atomic" + + "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + "google.golang.org/grpc" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/version" +) + +// rpcServer is the main RPC server for the Finality Provider daemon that handles +// gRPC incoming requests. +type rpcServer struct { + started int32 + shutdown int32 + + proto.UnimplementedFinalityProvidersServer + + app *FinalityProviderApp + + quit chan struct{} + wg sync.WaitGroup +} + +// newRPCServer creates a new RPC sever from the set of input dependencies. +func newRPCServer( + fpa *FinalityProviderApp, +) *rpcServer { + + return &rpcServer{ + quit: make(chan struct{}), + app: fpa, + } +} + +// Start signals that the RPC server starts accepting requests. +func (r *rpcServer) Start() error { + if atomic.AddInt32(&r.started, 1) != 1 { + return nil + } + + return nil +} + +// Stop signals that the RPC server should attempt a graceful shutdown and +// cancel any outstanding requests. +func (r *rpcServer) Stop() error { + if atomic.AddInt32(&r.shutdown, 1) != 1 { + return nil + } + + close(r.quit) + + r.wg.Wait() + + return nil +} + +// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC +// server. +func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { + // Register the main RPC server. + proto.RegisterFinalityProvidersServer(grpcServer, r) + return nil +} + +// GetInfo returns general information relating to the active daemon +func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetInfoResponse, error) { + + return &proto.GetInfoResponse{ + Version: version.Version(), + }, nil +} + +// CreateFinalityProvider generates a finality-provider object and saves it in the database +func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.CreateFinalityProviderRequest) ( + *proto.CreateFinalityProviderResponse, error) { + + commissionRate, err := math.LegacyNewDecFromStr(req.Commission) + if err != nil { + return nil, err + } + + result, err := r.app.CreateFinalityProvider( + req.KeyName, + req.ChainId, + req.Passphrase, + req.HdPath, + req.Description, + &commissionRate, + ) + + if err != nil { + return nil, err + } + + return &proto.CreateFinalityProviderResponse{ + BtcPk: result.FpPk.MarshalHex(), + }, nil + +} + +// RegisterFinalityProvider sends a transactions to Babylon to register a BTC finality-provider +func (r *rpcServer) RegisterFinalityProvider(ctx context.Context, req *proto.RegisterFinalityProviderRequest) ( + *proto.RegisterFinalityProviderResponse, error) { + + txRes, err := r.app.RegisterFinalityProvider(req.BtcPk) + if err != nil { + return nil, fmt.Errorf("failed to register the finality-provider to Babylon: %w", err) + } + + // the finality-provider instance should be started right after registration + if err := r.app.StartHandlingFinalityProvider(txRes.btcPubKey, req.Passphrase); err != nil { + return nil, fmt.Errorf("failed to start the registered finality-provider %s: %w", hex.EncodeToString(txRes.bbnPubKey.Key), err) + } + + return &proto.RegisterFinalityProviderResponse{TxHash: txRes.TxHash}, nil +} + +// AddFinalitySignature adds a manually constructed finality signature to Babylon +// NOTE: this is only used for presentation/testing purposes +func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFinalitySignatureRequest) ( + *proto.AddFinalitySignatureResponse, error) { + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + + fpi, err := r.app.GetFinalityProviderInstance(fpPk) + if err != nil { + return nil, err + } + + b := &types.BlockInfo{ + Height: req.Height, + Hash: req.AppHash, + } + + txRes, privKey, err := fpi.TestSubmitFinalitySignatureAndExtractPrivKey(b) + if err != nil { + return nil, err + } + + res := &proto.AddFinalitySignatureResponse{TxHash: txRes.TxHash} + + // if privKey is not empty, then this BTC finality-provider + // has voted for a fork and will be slashed + if privKey != nil { + localPrivKey, err := r.app.getFpPrivKey(fpPk.MustMarshal()) + res.ExtractedSkHex = privKey.Key.String() + if err != nil { + return nil, err + } + localSkHex := localPrivKey.Key.String() + localSkNegateHex := localPrivKey.Key.Negate().String() + if res.ExtractedSkHex == localSkHex { + res.LocalSkHex = localSkHex + } else if res.ExtractedSkHex == localSkNegateHex { + res.LocalSkHex = localSkNegateHex + } else { + return nil, fmt.Errorf("the finality-provider's BTC private key is extracted but does not match the local key,"+ + "extrated: %s, local: %s, local-negated: %s", + res.ExtractedSkHex, localSkHex, localSkNegateHex) + } + } + + return res, nil +} + +// QueryFinalityProvider queries the information of the finality-provider +func (r *rpcServer) QueryFinalityProvider(ctx context.Context, req *proto.QueryFinalityProviderRequest) ( + *proto.QueryFinalityProviderResponse, error) { + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + fp, err := r.app.GetFinalityProviderInstance(fpPk) + if err != nil { + return nil, err + } + + fpInfo := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + + return &proto.QueryFinalityProviderResponse{FinalityProvider: fpInfo}, 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() + + fpsInfo := make([]*proto.FinalityProviderInfo, len(fps)) + for i, fp := range fps { + fpInfo := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + fpsInfo[i] = fpInfo + } + + return &proto.QueryFinalityProviderListResponse{FinalityProviders: fpsInfo}, nil +} diff --git a/validator/service/server.go b/finality-provider/service/server.go similarity index 83% rename from validator/service/server.go rename to finality-provider/service/server.go index 85ed5fee..5b4dbf58 100644 --- a/validator/service/server.go +++ b/finality-provider/service/server.go @@ -10,16 +10,16 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" - valcfg "github.com/babylonchain/btc-validator/validator/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" ) -// Server is the main daemon construct for the BTC-Validator server. It handles +// Server is the main daemon construct for the Finality Provider server. It handles // spinning up the RPC sever, the database, and any other components that the // Taproot Asset server needs to function. type Server struct { started int32 - cfg *valcfg.Config + cfg *fpcfg.Config logger *zap.Logger rpcServer *rpcServer @@ -28,12 +28,12 @@ type Server struct { quit chan struct{} } -// NewValidatorServer creates a new server with the given config. -func NewValidatorServer(cfg *valcfg.Config, l *zap.Logger, v *ValidatorApp, sig signal.Interceptor) *Server { +// NewFinalityproviderServer creates a new server with the given config. +func NewFinalityProviderServer(cfg *fpcfg.Config, l *zap.Logger, fpa *FinalityProviderApp, sig signal.Interceptor) *Server { return &Server{ cfg: cfg, logger: l, - rpcServer: newRPCServer(v), + rpcServer: newRPCServer(fpa), interceptor: sig, quit: make(chan struct{}, 1), } @@ -72,7 +72,7 @@ func (s *Server) RunUntilShutdown() error { return fmt.Errorf("failed to start gRPC listener: %v", err) } - s.logger.Info("BTC Validator Daemon is fully active!") + s.logger.Info("Finality Provider Daemon is fully active!") // Wait for shutdown signal from either a graceful server stop or from // the interrupt handler. diff --git a/finality-provider/service/types.go b/finality-provider/service/types.go new file mode 100644 index 00000000..59ebf46e --- /dev/null +++ b/finality-provider/service/types.go @@ -0,0 +1,200 @@ +package service + +import ( + "sync" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" +) + +type createFinalityProviderResponse struct { + FpPk *bbntypes.BIP340PubKey +} +type createFinalityProviderRequest struct { + keyName string + passPhrase string + hdPath string + chainID string + description []byte + commission *sdkmath.LegacyDec + errResponse chan error + successResponse chan *createFinalityProviderResponse +} + +type registerFinalityProviderRequest struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + // TODO we should have our own representation of PoP + pop *btcstakingtypes.ProofOfPossession + description []byte + commission *sdkmath.LegacyDec + errResponse chan error + successResponse chan *RegisterFinalityProviderResponse +} + +type finalityProviderRegisteredEvent struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + txHash string + successResponse chan *RegisterFinalityProviderResponse +} + +type RegisterFinalityProviderResponse struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + TxHash string +} + +type CreateFinalityProviderResult struct { + FpPk *bbntypes.BIP340PubKey +} + +type fpState struct { + mu sync.Mutex + fp *proto.StoreFinalityProvider + s *fpstore.FinalityProviderStore +} + +func (fps *fpState) getStoreFinalityProvider() *proto.StoreFinalityProvider { + fps.mu.Lock() + defer fps.mu.Unlock() + return fps.fp +} + +func (fps *fpState) setStatus(s proto.FinalityProviderStatus) error { + fps.mu.Lock() + fps.fp.Status = s + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fps *fpState) setLastProcessedHeight(height uint64) error { + fps.mu.Lock() + fps.fp.LastProcessedHeight = height + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fps *fpState) setLastCommittedHeight(height uint64) error { + fps.mu.Lock() + fps.fp.LastCommittedHeight = height + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fps *fpState) setLastProcessedAndVotedHeight(height uint64) error { + fps.mu.Lock() + fps.fp.LastVotedHeight = height + fps.fp.LastProcessedHeight = height + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fp *FinalityProviderInstance) GetStoreFinalityProvider() *proto.StoreFinalityProvider { + 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() +} + +func (fp *FinalityProviderInstance) MustGetBtcPk() *btcec.PublicKey { + return fp.state.getStoreFinalityProvider().MustGetBTCPK() +} + +func (fp *FinalityProviderInstance) GetBtcPkHex() string { + return fp.GetBtcPkBIP340().MarshalHex() +} + +func (fp *FinalityProviderInstance) GetStatus() proto.FinalityProviderStatus { + return fp.state.getStoreFinalityProvider().Status +} + +func (fp *FinalityProviderInstance) GetLastVotedHeight() uint64 { + return fp.state.getStoreFinalityProvider().LastVotedHeight +} + +func (fp *FinalityProviderInstance) GetLastProcessedHeight() uint64 { + return fp.state.getStoreFinalityProvider().LastProcessedHeight +} + +func (fp *FinalityProviderInstance) GetLastCommittedHeight() uint64 { + return fp.state.getStoreFinalityProvider().LastCommittedHeight +} + +func (fp *FinalityProviderInstance) GetChainID() []byte { + return []byte(fp.state.getStoreFinalityProvider().ChainId) +} + +func (fp *FinalityProviderInstance) SetStatus(s proto.FinalityProviderStatus) error { + return fp.state.setStatus(s) +} + +func (fp *FinalityProviderInstance) MustSetStatus(s proto.FinalityProviderStatus) { + if err := fp.SetStatus(s); err != nil { + fp.logger.Fatal("failed to set finality-provider status", + zap.String("pk", fp.GetBtcPkHex()), zap.String("status", s.String())) + } +} + +func (fp *FinalityProviderInstance) SetLastProcessedHeight(height uint64) error { + return fp.state.setLastProcessedHeight(height) +} + +func (fp *FinalityProviderInstance) MustSetLastProcessedHeight(height uint64) { + if err := fp.SetLastProcessedHeight(height); err != nil { + fp.logger.Fatal("failed to set last processed height", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("last_processed_height", height)) + } +} + +func (fp *FinalityProviderInstance) SetLastCommittedHeight(height uint64) error { + return fp.state.setLastCommittedHeight(height) +} + +func (fp *FinalityProviderInstance) MustSetLastCommittedHeight(height uint64) { + if err := fp.SetLastCommittedHeight(height); err != nil { + fp.logger.Fatal("failed to set last committed height", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("last_committed_height", height)) + } +} + +func (fp *FinalityProviderInstance) updateStateAfterFinalitySigSubmission(height uint64) error { + return fp.state.setLastProcessedAndVotedHeight(height) +} + +func (fp *FinalityProviderInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { + if err := fp.updateStateAfterFinalitySigSubmission(height); err != nil { + fp.logger.Fatal("failed to update state after finality signature submitted", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", height)) + } +} + +func (fp *FinalityProviderInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { + record, err := fp.em.KeyRecord(fp.btcPk.MustMarshal(), fp.passphrase) + if err != nil { + return nil, err + } + + return record.PrivKey, nil +} + +// only used for testing purposes +func (fp *FinalityProviderInstance) BtcPrivKey() (*btcec.PrivateKey, error) { + return fp.getEOTSPrivKey() +} diff --git a/finality-provider/store/fpstore.go b/finality-provider/store/fpstore.go new file mode 100644 index 00000000..feaa6088 --- /dev/null +++ b/finality-provider/store/fpstore.go @@ -0,0 +1,210 @@ +package store + +import ( + "fmt" + "math" + + sdkmath "cosmossdk.io/math" + "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + gproto "google.golang.org/protobuf/proto" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/store" +) + +const ( + fpPrefix = "finality-provider" +) + +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 +} + +func NewFinalityProviderStore(dbPath string, dbName string, dbBackend string) (*FinalityProviderStore, error) { + s, err := openStore(dbPath, dbName, dbBackend) + if err != nil { + return nil, err + } + + return &FinalityProviderStore{s: s}, nil +} + +func getFinalityProviderKey(pk []byte) []byte { + return append([]byte(fpPrefix), pk...) +} + +func (vs *FinalityProviderStore) getFinalityProviderListKey() []byte { + return []byte(fpPrefix) +} + +func (vs *FinalityProviderStore) SaveFinalityProvider(fp *proto.StoreFinalityProvider) error { + k := getFinalityProviderKey(fp.BtcPk) + v, err := gproto.Marshal(fp) + if err != nil { + return fmt.Errorf("failed to marshal the created finality-provider object: %w", err) + } + + if err := vs.s.Put(k, v); err != nil { + return fmt.Errorf("failed to save the created finality-provider object: %w", err) + } + + return nil +} + +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") + } + + v, err := gproto.Marshal(fp) + if err != nil { + return err + } + + if err := vs.s.Put(k, v); err != nil { + return err + } + + return nil +} + +func (vs *FinalityProviderStore) SetFinalityProviderStatus(fp *proto.StoreFinalityProvider, status proto.FinalityProviderStatus) error { + fp.Status = status + return vs.UpdateFinalityProvider(fp) +} + +func (vs *FinalityProviderStore) GetStoreFinalityProvider(pk []byte) (*proto.StoreFinalityProvider, error) { + k := getFinalityProviderKey(pk) + fpBytes, err := vs.s.Get(k) + if err != nil { + return nil, err + } + + fp := new(proto.StoreFinalityProvider) + err = gproto.Unmarshal(fpBytes, fp) + if err != nil { + panic(fmt.Errorf("unable to unmarshal finality-provider object: %w", err)) + } + + return fp, nil +} + +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)) + } + fpsList[i] = fp + } + + return fpsList, nil +} + +// 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 + } + + 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)) + } + if fp.Status > proto.FinalityProviderStatus_CREATED && fp.Status < proto.FinalityProviderStatus_SLASHED { + fpsList = append(fpsList, fp) + } + } + + return fpsList, nil +} + +func (vs *FinalityProviderStore) GetEarliestActiveFinalityProviderVotedHeight() (uint64, error) { + registeredFps, err := vs.ListRegisteredFinalityProviders() + if err != nil { + return 0, err + } + + if len(registeredFps) == 0 { + return 0, nil + } + + 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 + } + activeFpsCnt += 1 + if earliestHeight > fp.LastVotedHeight { + earliestHeight = fp.LastVotedHeight + } + } + // 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 + } + + return 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") + } +} diff --git a/finality-provider/store/fpstore_test.go b/finality-provider/store/fpstore_test.go new file mode 100644 index 00000000..a8c39a2b --- /dev/null +++ b/finality-provider/store/fpstore_test.go @@ -0,0 +1,45 @@ +package store_test + +import ( + "math/rand" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/testutil" +) + +// FuzzFinalityProvidersStore tests save and list finality providers properly +func FuzzFinalityProvidersStore(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + 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) + require.NoError(t, err) + + defer func() { + err := os.RemoveAll(dbPath) + require.NoError(t, err) + }() + + fp := testutil.GenRandomFinalityProvider(r, t) + err = vs.SaveFinalityProvider(fp) + require.NoError(t, err) + + fpList, err := vs.ListFinalityProviders() + require.NoError(t, err) + require.Equal(t, fp.BtcPk, fpList[0].BtcPk) + + actualFp, err := vs.GetStoreFinalityProvider(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) + }) +} diff --git a/go.mod b/go.mod index 13bfb2bc..3763a9de 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/babylonchain/btc-validator +module github.com/babylonchain/finality-provider go 1.21 @@ -238,8 +238,8 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b - github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 + github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 6b5dd0af..5ce19912 100644 --- a/go.sum +++ b/go.sum @@ -279,10 +279,10 @@ 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-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= -github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1 h1:Cf1aNeXcSfZczocNxZZ1mM+KU4NDopzaIyi1fSoezxo= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231128092309-ad2ef0696dc1/go.mod h1:M/tRKH7cc0gpAqCEpHTiaYob/6xoTD4v3A4FZQ3Y3ks= +github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 h1:fFlLF+rl6Buwb3eYgIoUQ4JkYdNMMTk9ihoznTTw2hk= +github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a h1:IwntCUOlcsczQfl4P72ckqGf09coMdM42LvAG1aM+mg= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a/go.mod h1:dnUVCa5yHq2giiSpBpXx7W3CbJuuMabvQi3hG81AAtM= 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= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index fc08cf60..cfb11d4b 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -4,16 +4,16 @@ package e2etest import ( + "github.com/btcsuite/btcd/btcec/v2" "math/rand" "testing" "time" "github.com/babylonchain/babylon/testutil/datagen" - "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/service" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -21,110 +21,110 @@ var ( stakingAmount = int64(20000) ) -// TestValidatorLifeCycle tests the whole life cycle of a validator +// TestFinalityProviderLifeCycle tests the whole life cycle of a finality-provider // creation -> registration -> randomness commitment -> // activation with BTC delegation and Covenant sig -> // vote submission -> block finalization -func TestValidatorLifeCycle(t *testing.T) { - tm, valInsList := StartManagerWithValidator(t, 1) +func TestFinalityProviderLifeCycle(t *testing.T) { + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - valIns := valInsList[0] + fpIns := fpInsList[0] params := tm.GetParams(t) // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized - lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) tm.CheckBlockFinalization(t, lastVotedHeight, 1) t.Logf("the block at height %v is finalized", lastVotedHeight) } -// TestDoubleSigning tests the attack scenario where the validator +// TestDoubleSigning tests the attack scenario where the finality-provider // 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, valInsList := StartManagerWithValidator(t, 1) + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - valIns := valInsList[0] + fpIns := fpInsList[0] params := tm.GetParams(t) // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) // check the BTC delegation is active - _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized - lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) tm.CheckBlockFinalization(t, lastVotedHeight, 1) t.Logf("the block at height %v is finalized", lastVotedHeight) finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) // attack: manually submit a finality vote over a conflicting block - // to trigger the extraction of validator's private key + // to trigger the extraction of finality-provider's private key r := rand.New(rand.NewSource(time.Now().UnixNano())) b := &types.BlockInfo{ Height: finalizedBlocks[0].Height, Hash: datagen.GenRandomAppHash(r), } - _, extractedKey, err := valIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) + _, extractedKey, err := fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) require.NotNil(t, extractedKey) - localKey := tm.GetValPrivKey(t, valIns.GetBtcPkBIP340().MustMarshal()) + localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal()) require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) t.Logf("the equivocation attack is successful") } -// TestMultipleValidators tests starting with multiple validators -func TestMultipleValidators(t *testing.T) { +// TestMultipleFinalityProviders tests starting with multiple finality providers +func TestMultipleFinalityProviders(t *testing.T) { n := 3 - tm, valInstances := StartManagerWithValidator(t, n) + tm, fpInstances := StartManagerWithFinalityProvider(t, n) defer tm.Stop(t) params := tm.GetParams(t) - // submit BTC delegations for each validator - for _, valIns := range valInstances { + // submit BTC delegations for each finality-provider + for _, fpIns := range fpInstances { tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { + go func(fpi *service.FinalityProviderInstance) { defer tm.Wg.Done() // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, v) + tm.WaitForFpPubRandCommitted(t, fpi) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{v.MustGetBtcPk()}, stakingTime, stakingAmount, params) - }(valIns) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpi.MustGetBtcPk()}, stakingTime, stakingAmount, params) + }(fpIns) } tm.Wg.Wait() - for _, valIns := range valInstances { + for _, fpIns := range fpInstances { tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { + go func(fpi *service.FinalityProviderInstance) { defer tm.Wg.Done() - _ = tm.WaitForValNActiveDels(t, v.GetBtcPkBIP340(), 1) - }(valIns) + _ = tm.WaitForFpNActiveDels(t, fpi.GetBtcPkBIP340(), 1) + }(fpIns) } tm.Wg.Wait() @@ -132,28 +132,28 @@ func TestMultipleValidators(t *testing.T) { _ = tm.WaitForNFinalizedBlocks(t, 1) } -// TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync +// TestFastSync tests the fast sync process where the finality-provider is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm, valInsList := StartManagerWithValidator(t, 1) + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - valIns := valInsList[0] + fpIns := fpInsList[0] params := tm.GetParams(t) // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{valIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) // check the BTC delegation is pending _ = tm.WaitForNPendingDels(t, 1) - _ = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) // check the last voted block is finalized - lastVotedHeight := tm.WaitForValVoteCast(t, valIns) + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) tm.CheckBlockFinalization(t, lastVotedHeight, 1) t.Logf("the block at height %v is finalized", lastVotedHeight) @@ -162,9 +162,9 @@ func TestFastSync(t *testing.T) { finalizedBlocks = tm.WaitForNFinalizedBlocks(t, 1) n := 3 - // stop the validator for a few blocks then restart to trigger the fast sync - tm.ValConfig.FastSyncGap = uint64(n) - tm.StopAndRestartValidatorAfterNBlocks(t, n, valIns) + // stop the finality-provider for a few blocks then restart to trigger the fast sync + tm.FpConfig.FastSyncGap = uint64(n) + tm.StopAndRestartFpAfterNBlocks(t, n, fpIns) // check there are n+1 blocks finalized finalizedBlocks = tm.WaitForNFinalizedBlocks(t, n+1) diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go index 0a041c97..2c644500 100644 --- a/itest/eotsmanager_handler.go +++ b/itest/eotsmanager_handler.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/eotsmanager/service" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager/service" ) type EOTSServerHandler struct { diff --git a/itest/test_manager.go b/itest/test_manager.go index 7c1aaa58..4da76eae 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -1,6 +1,7 @@ package e2etest import ( + "github.com/btcsuite/btcd/btcec/v2" "math/rand" "os" "path/filepath" @@ -16,7 +17,6 @@ import ( btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -25,14 +25,14 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/covenant" - covcfg "github.com/babylonchain/btc-validator/covenant/config" - "github.com/babylonchain/btc-validator/eotsmanager/client" - eotsconfig "github.com/babylonchain/btc-validator/eotsmanager/config" - "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" - "github.com/babylonchain/btc-validator/validator/service" + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/covenant" + covcfg "github.com/babylonchain/finality-provider/covenant/config" + "github.com/babylonchain/finality-provider/eotsmanager/client" + eotsconfig "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -40,7 +40,7 @@ var ( eventuallyPollTime = 500 * time.Millisecond btcNetworkParams = &chaincfg.SimNetParams - valNamePrefix = "test-val-" + fpNamePrefix = "test-fp-" monikerPrefix = "moniker-" covenantKeyName = "covenant-key" chainID = "chain-test" @@ -53,10 +53,10 @@ type TestManager struct { BabylonHandler *BabylonNodeHandler EOTSServerHandler *EOTSServerHandler CovenantEmulator *covenant.CovenantEmulator - ValConfig *valcfg.Config + FpConfig *fpcfg.Config EOTSConfig *eotsconfig.Config CovenanConfig *covcfg.Config - Va *service.ValidatorApp + Fpa *service.FinalityProviderApp EOTSClient *client.EOTSManagerGRpcClient BabylonClient *clientcontroller.BabylonController baseDir string @@ -71,7 +71,7 @@ type TestDelegationData struct { StakingTx *wire.MsgTx StakingTxInfo *btcctypes.TransactionInfo DelegatorSig *bbntypes.BIP340Signature - ValidatorPks []*btcec.PublicKey + FpPks []*btcec.PublicKey SlashingAddr string ChangeAddr string @@ -80,7 +80,7 @@ type TestDelegationData struct { } func StartManager(t *testing.T) *TestManager { - testDir, err := tempDirWithName("vale2etest") + testDir, err := tempDirWithName("fpe2etest") require.NoError(t, err) logger := zap.NewNop() @@ -96,8 +96,8 @@ func StartManager(t *testing.T) *TestManager { bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covKeyPair.PublicKey)) err = bh.Start() require.NoError(t, err) - valHomeDir := filepath.Join(testDir, "val-home") - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), valHomeDir) + fpHomeDir := filepath.Join(testDir, "fp-home") + cfg := defaultFpConfig(bh.GetNodeDataDir(), fpHomeDir) bc, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) require.NoError(t, err) @@ -109,10 +109,10 @@ func StartManager(t *testing.T) *TestManager { eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) - // 4. prepare validator - valApp, err := service.NewValidatorApp(valHomeDir, cfg, bc, eotsCli, logger) + // 4. prepare finality-provider + fpApp, err := service.NewFinalityProviderApp(fpHomeDir, cfg, bc, eotsCli, logger) require.NoError(t, err) - err = valApp.Start() + err = fpApp.Start() require.NoError(t, err) // 5. prepare covenant emulator @@ -124,9 +124,9 @@ func StartManager(t *testing.T) *TestManager { tm := &TestManager{ BabylonHandler: bh, EOTSServerHandler: eh, - ValConfig: cfg, + FpConfig: cfg, EOTSConfig: eotsCfg, - Va: valApp, + Fpa: fpApp, CovenantEmulator: ce, CovenanConfig: covenantConfig, EOTSClient: eotsCli, @@ -150,44 +150,44 @@ func (tm *TestManager) WaitForServicesStart(t *testing.T) { t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int) (*TestManager, []*service.ValidatorInstance) { +func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*service.FinalityProviderInstance) { tm := StartManager(t) - app := tm.Va + app := tm.Fpa for i := 0; i < n; i++ { - valName := valNamePrefix + strconv.Itoa(i) + fpName := fpNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) commission := sdkmath.LegacyZeroDec() desc, err := newDescription(moniker).Marshal() require.NoError(t, err) - res, err := app.CreateValidator(valName, chainID, passphrase, hdPath, desc, &commission) + res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, desc, &commission) require.NoError(t, err) - _, err = app.RegisterValidator(res.ValPk.MarshalHex()) + _, err = app.RegisterFinalityProvider(res.FpPk.MarshalHex()) require.NoError(t, err) - err = app.StartHandlingValidator(res.ValPk, passphrase) + err = app.StartHandlingFinalityProvider(res.FpPk, passphrase) require.NoError(t, err) - valIns, err := app.GetValidatorInstance(res.ValPk) + fpIns, err := app.GetFinalityProviderInstance(res.FpPk) require.NoError(t, err) - require.True(t, valIns.IsRunning()) + require.True(t, fpIns.IsRunning()) require.NoError(t, err) - // check validators on Babylon side + // check finality providers on Babylon side require.Eventually(t, func() bool { - vals, err := tm.BabylonClient.QueryValidators() + fps, err := tm.BabylonClient.QueryFinalityProviders() if err != nil { - t.Logf("failed to query validtors from Babylon %s", err.Error()) + t.Logf("failed to query finality providers from Babylon %s", err.Error()) return false } - if len(vals) != i+1 { + if len(fps) != i+1 { return false } - for _, v := range vals { - if !strings.Contains(v.Description.Moniker, monikerPrefix) { + for _, fp := range fps { + if !strings.Contains(fp.Description.Moniker, monikerPrefix) { return false } - if !v.Commission.Equal(sdkmath.LegacyZeroDec()) { + if !fp.Commission.Equal(sdkmath.LegacyZeroDec()) { return false } } @@ -196,16 +196,16 @@ func StartManagerWithValidator(t *testing.T, n int) (*TestManager, []*service.Va }, eventuallyWaitTimeOut, eventuallyPollTime) } - valInsList := app.ListValidatorInstances() - require.Equal(t, n, len(valInsList)) + fpInsList := app.ListFinalityProviderInstances() + require.Equal(t, n, len(fpInsList)) - t.Logf("the test manager is running with %v validator(s)", len(valInsList)) + t.Logf("the test manager is running with %v finality-provider(s)", len(fpInsList)) - return tm, valInsList + return tm, fpInsList } func (tm *TestManager) Stop(t *testing.T) { - err := tm.Va.Stop() + err := tm.Fpa.Stop() require.NoError(t, err) err = tm.CovenantEmulator.Stop() require.NoError(t, err) @@ -216,21 +216,21 @@ func (tm *TestManager) Stop(t *testing.T) { tm.EOTSServerHandler.Stop() } -func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { +func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { require.Eventually(t, func() bool { - queriedValidators, err := tm.BabylonClient.QueryValidators() + queriedFps, err := tm.BabylonClient.QueryFinalityProviders() if err != nil { return false } - return len(queriedValidators) == 1 && queriedValidators[0].BabylonPk.Equals(bbnPk) + return len(queriedFps) == 1 && queriedFps[0].BabylonPk.Equals(bbnPk) }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Logf("the validator is successfully registered") + t.Logf("the finality-provider is successfully registered") } -func (tm *TestManager) WaitForValPubRandCommitted(t *testing.T, valIns *service.ValidatorInstance) { +func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.FinalityProviderInstance) { require.Eventually(t, func() bool { - return valIns.GetLastCommittedHeight() > 0 + return fpIns.GetLastCommittedHeight() > 0 }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("public randomness is successfully committed") @@ -256,14 +256,14 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegat return dels } -func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { +func (tm *TestManager) WaitForFpNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { var dels []*types.Delegation currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() require.NoError(t, err) params, err := tm.BabylonClient.QueryStakingParams() require.NoError(t, err) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(btcPk, 1000) + dels, err = tm.BabylonClient.QueryFinalityProviderDelegations(btcPk, 1000) if err != nil { return false } @@ -271,7 +271,7 @@ func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP34 params.CovenantQuorum, bstypes.BTCDelegationStatus_ACTIVE) }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Logf("the delegation is active, validators should start voting") + t.Logf("the delegation is active, finality providers should start voting") return dels } @@ -333,11 +333,11 @@ func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num i }, eventuallyWaitTimeOut, eventuallyPollTime) } -func (tm *TestManager) WaitForValVoteCast(t *testing.T, valIns *service.ValidatorInstance) uint64 { +func (tm *TestManager) WaitForFpVoteCast(t *testing.T, fpIns *service.FinalityProviderInstance) uint64 { var lastVotedHeight uint64 require.Eventually(t, func() bool { - if valIns.GetLastVotedHeight() > 0 { - lastVotedHeight = valIns.GetLastVotedHeight() + if fpIns.GetLastVotedHeight() > 0 { + lastVotedHeight = fpIns.GetLastVotedHeight() return true } else { return false @@ -366,10 +366,10 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo return blocks } -func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, valIns *service.ValidatorInstance) { +func (tm *TestManager) StopAndRestartFpAfterNBlocks(t *testing.T, n int, fpIns *service.FinalityProviderInstance) { blockBeforeStop, err := tm.BabylonClient.QueryBestBlock() require.NoError(t, err) - err = valIns.Stop() + err = fpIns.Stop() require.NoError(t, err) require.Eventually(t, func() bool { @@ -381,20 +381,20 @@ func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, return headerAfterStop.Height >= uint64(n)+blockBeforeStop.Height }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Log("restarting the validator instance") + t.Log("restarting the finality-provider instance") - tm.ValConfig.PollerConfig.AutoChainScanningMode = true - err = valIns.Start() + tm.FpConfig.PollerConfig.AutoChainScanningMode = true + err = fpIns.Start() require.NoError(t, err) } -func (tm *TestManager) GetValPrivKey(t *testing.T, valPk []byte) *btcec.PrivateKey { - record, err := tm.EOTSClient.KeyRecord(valPk, passphrase) +func (tm *TestManager) GetFpPrivKey(t *testing.T, fpPk []byte) *btcec.PrivateKey { + record, err := tm.EOTSClient.KeyRecord(fpPk, passphrase) require.NoError(t, err) return record.PrivKey } -func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *types.StakingParams) *TestDelegationData { +func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *types.StakingParams) *TestDelegationData { r := rand.New(rand.NewSource(time.Now().UnixNano())) // delegator BTC key pairs, staking tx and slashing tx @@ -409,7 +409,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P t, btcNetworkParams, delBtcPrivKey, - validatorPks, + fpPks, params.CovenantPks, params.CovenantQuorum, stakingTime, @@ -473,7 +473,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P t, btcNetworkParams, delBtcPrivKey, - validatorPks, + fpPks, params.CovenantPks, params.CovenantQuorum, wire.NewOutPoint(&stakingTxHash, 0), @@ -504,7 +504,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P _, err = tm.BabylonClient.CreateBTCDelegation( delBabylonPubKey.(*secp256k1.PubKey), bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), - validatorPks, + fpPks, pop, uint32(stakingTime), stakingAmount, @@ -525,7 +525,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, validatorPks []*btcec.P DelegatorKey: delBtcPubKey, DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), - ValidatorPks: validatorPks, + FpPks: fpPks, StakingTx: testStakingInfo.StakingTx, SlashingTx: testStakingInfo.SlashingTx, StakingTxInfo: txInfo, @@ -543,8 +543,8 @@ func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { return p } -func defaultValidatorConfig(keyringDir, homeDir string) *valcfg.Config { - cfg := valcfg.DefaultConfigWithHome(homeDir) +func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { + cfg := fpcfg.DefaultConfigWithHome(homeDir) cfg.PollerConfig.AutoChainScanningMode = false // babylon configs for sending transactions diff --git a/keyring/keyring.go b/keyring/keyring.go index 920d0cfd..36b526b3 100644 --- a/keyring/keyring.go +++ b/keyring/keyring.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/babylonchain/btc-validator/codec" + "github.com/babylonchain/finality-provider/codec" ) func CreateKeyring(keyringDir string, chainId string, backend string, input *strings.Reader) (keyring.Keyring, error) { @@ -45,7 +45,7 @@ func CreateClientCtx(keyringDir string, chainId string) (client.Context, error) if err != nil { return client.Context{}, err } - keyringDir = path.Join(homeDir, ".btc-validator") + keyringDir = path.Join(homeDir, ".finality-provider") } return client.Context{}. diff --git a/keyring/keyringcontroller.go b/keyring/keyringcontroller.go index d8d40d34..f5d141af 100644 --- a/keyring/keyringcontroller.go +++ b/keyring/keyringcontroller.go @@ -11,7 +11,7 @@ import ( sdksecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/go-bip39" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/types" ) const ( @@ -20,8 +20,8 @@ const ( ) type ChainKeyringController struct { - kr keyring.Keyring - valName string + kr keyring.Keyring + fpName string // input is to send passphrase to kr input *strings.Reader } @@ -48,9 +48,9 @@ func NewChainKeyringController(ctx client.Context, name, keyringBackend string) } return &ChainKeyringController{ - valName: name, - kr: kr, - input: inputReader, + fpName: name, + kr: kr, + input: inputReader, }, nil } @@ -60,9 +60,9 @@ func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string, input } return &ChainKeyringController{ - kr: kr, - valName: name, - input: input, + kr: kr, + fpName: name, + input: input, }, nil } @@ -89,11 +89,11 @@ func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*ty } // TODO use a better way to remind the user to keep it - fmt.Printf("Generated mnemonic for the validator %s is:\n%s\n", kc.valName, mnemonic) + fmt.Printf("Generated mnemonic for the finality provider %s is:\n%s\n", kc.fpName, mnemonic) // we need to repeat the passphrase to mock the reentry kc.input.Reset(passphrase + "\n" + passphrase) - record, err := kc.kr.NewAccount(kc.valName, mnemonic, passphrase, hdPath, algo) + record, err := kc.kr.NewAccount(kc.fpName, mnemonic, passphrase, hdPath, algo) if err != nil { return nil, err } @@ -123,7 +123,7 @@ func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey, passph func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*sdksecp256k1.PrivKey, error) { kc.input.Reset(passphrase) - k, err := kc.kr.Key(kc.valName) + k, err := kc.kr.Key(kc.fpName) if err != nil { return nil, fmt.Errorf("failed to get private key: %w", err) } diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go index 1c88b9ef..1a8c6e57 100644 --- a/keyring/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -7,7 +7,7 @@ import ( "path/filepath" "testing" - valstore "github.com/babylonchain/btc-validator/validator/store" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" "github.com/babylonchain/babylon/types" "github.com/btcsuite/btcd/chaincfg" @@ -15,10 +15,10 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/stretchr/testify/require" - valkr "github.com/babylonchain/btc-validator/keyring" + fpkr "github.com/babylonchain/finality-provider/keyring" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/testutil" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/testutil" ) var ( @@ -36,7 +36,7 @@ func FuzzCreatePoP(f *testing.F) { sdkCtx := testutil.GenSdkContext(r, t) chainID := testutil.GenRandomHexStr(r, 4) - kc, err := valkr.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) + kc, err := fpkr.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) require.NoError(t, err) eotsHome := filepath.Join(t.TempDir(), "eots-home") @@ -55,14 +55,14 @@ func FuzzCreatePoP(f *testing.F) { keyPair, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} - valRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) + fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) require.NoError(t, err) - pop, err := kc.CreatePop(valRecord.PrivKey, passphrase) + pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) require.NoError(t, err) - validator := valstore.NewStoreValidator(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + fp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) btcSig := new(types.BIP340Signature) - err = btcSig.Unmarshal(validator.Pop.BtcSig) + err = btcSig.Unmarshal(fp.Pop.BtcSig) require.NoError(t, err) err = pop.Verify(bbnPk, btcPk, &chaincfg.SimNetParams) require.NoError(t, err) diff --git a/log/log.go b/log/log.go index f8ed33a2..fd3643c4 100644 --- a/log/log.go +++ b/log/log.go @@ -2,7 +2,7 @@ package log import ( "fmt" - "github.com/babylonchain/btc-validator/util" + "github.com/babylonchain/finality-provider/util" "io" "os" "path/filepath" diff --git a/store/bbolt_test.go b/store/bbolt_test.go index 6ce9f922..7a407cee 100644 --- a/store/bbolt_test.go +++ b/store/bbolt_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" - kvstore "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/testutil" + kvstore "github.com/babylonchain/finality-provider/store" + "github.com/babylonchain/finality-provider/testutil" ) // FuzzBboltStore tests store interfaces works properly. diff --git a/testutil/datagen.go b/testutil/datagen.go index 7cb5a75e..e842c53b 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -2,8 +2,8 @@ package testutil import ( "encoding/hex" - eotscfg "github.com/babylonchain/btc-validator/eotsmanager/config" - valcfg "github.com/babylonchain/btc-validator/validator/config" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "math/rand" "testing" "time" @@ -17,11 +17,11 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/codec" - "github.com/babylonchain/btc-validator/config" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/validator/service" + "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" ) func GenRandomByteArray(r *rand.Rand, length uint64) []byte { @@ -44,7 +44,7 @@ func AddRandomSeedsToFuzzer(f *testing.F, num uint) { } } -func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { +func GenRandomFinalityProvider(r *rand.Rand, t *testing.T) *proto.StoreFinalityProvider { // generate BTC key pair btcSK, btcPK, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) @@ -60,7 +60,7 @@ func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { err = pop.Verify(babylonPK, bip340PK, &chaincfg.SigNetParams) require.NoError(t, err) - return &proto.StoreValidator{ + return &proto.StoreFinalityProvider{ KeyName: GenRandomHexStr(r, 4), BabylonPk: babylonPK.Bytes(), BtcPk: bip340PK.MustMarshal(), @@ -122,19 +122,19 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { return blocks } -// GenStoredValidator generates a random validator from the keyring and store it in DB -func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp, passphrase, hdPath string) *proto.StoreValidator { +// 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 { // generate keyring keyName := GenRandomHexStr(r, 4) chainID := GenRandomHexStr(r, 4) - res, err := app.CreateValidator(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) + res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) - storedVal, err := app.GetValidatorStore().GetStoreValidator(res.ValPk.MustMarshal()) + storedFp, err := app.GetFinalityProviderStore().GetStoreFinalityProvider(res.FpPk.MustMarshal()) require.NoError(t, err) - return storedVal + return storedFp } func GenDBConfig(r *rand.Rand, t *testing.T) *config.DatabaseConfig { @@ -154,11 +154,11 @@ func GenEOTSConfig(r *rand.Rand, t *testing.T) *eotscfg.Config { return &eotsCfg } -func GenValConfig(r *rand.Rand, t *testing.T, homeDir string) *valcfg.Config { - valCfg := valcfg.DefaultConfigWithHome(homeDir) - valCfg.DatabaseConfig = GenDBConfig(r, t) +func GenFpConfig(r *rand.Rand, t *testing.T, homeDir string) *fpcfg.Config { + fpCfg := fpcfg.DefaultConfigWithHome(homeDir) + fpCfg.DatabaseConfig = GenDBConfig(r, t) - return &valCfg + return &fpCfg } func GenSdkContext(r *rand.Rand, t *testing.T) client.Context { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index c98901fe..21ffc81b 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -8,7 +8,7 @@ import ( reflect "reflect" math "cosmossdk.io/math" - types "github.com/babylonchain/btc-validator/types" + 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" @@ -52,18 +52,18 @@ func (mr *MockClientControllerMockRecorder) Close() *gomock.Call { } // CommitPubRandList mocks base method. -func (m *MockClientController) CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { +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", valPk, startHeight, pubRandList, sig) + 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(valPk, startHeight, pubRandList, sig interface{}) *gomock.Call { +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), valPk, startHeight, pubRandList, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), fpPk, startHeight, pubRandList, sig) } // QueryActivatedHeight mocks base method. @@ -126,6 +126,36 @@ func (mr *MockClientControllerMockRecorder) QueryBlocks(startHeight, endHeight, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockClientController)(nil).QueryBlocks), startHeight, endHeight, limit) } +// QueryFinalityProviderSlashed mocks base method. +func (m *MockClientController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryFinalityProviderSlashed", fpPk) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryFinalityProviderSlashed indicates an expected call of QueryFinalityProviderSlashed. +func (mr *MockClientControllerMockRecorder) QueryFinalityProviderSlashed(fpPk interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderSlashed", reflect.TypeOf((*MockClientController)(nil).QueryFinalityProviderSlashed), fpPk) +} + +// QueryFinalityProviderVotingPower mocks base method. +func (m *MockClientController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryFinalityProviderVotingPower", fpPk, blockHeight) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryFinalityProviderVotingPower indicates an expected call of QueryFinalityProviderVotingPower. +func (mr *MockClientControllerMockRecorder) QueryFinalityProviderVotingPower(fpPk, blockHeight interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) +} + // QueryLatestFinalizedBlocks mocks base method. func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() @@ -171,64 +201,34 @@ func (mr *MockClientControllerMockRecorder) QueryStakingParams() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryStakingParams", reflect.TypeOf((*MockClientController)(nil).QueryStakingParams)) } -// QueryValidatorSlashed mocks base method. -func (m *MockClientController) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorSlashed", valPk) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryValidatorSlashed indicates an expected call of QueryValidatorSlashed. -func (mr *MockClientControllerMockRecorder) QueryValidatorSlashed(valPk interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorSlashed", reflect.TypeOf((*MockClientController)(nil).QueryValidatorSlashed), valPk) -} - -// QueryValidatorVotingPower mocks base method. -func (m *MockClientController) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorVotingPower", valPk, blockHeight) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryValidatorVotingPower indicates an expected call of QueryValidatorVotingPower. -func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(valPk, blockHeight interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryValidatorVotingPower), valPk, blockHeight) -} - -// RegisterValidator mocks base method. -func (m *MockClientController) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { +// RegisterFinalityProvider mocks base method. +func (m *MockClientController) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) + ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RegisterValidator indicates an expected call of RegisterValidator. -func (mr *MockClientControllerMockRecorder) RegisterValidator(chainPk, valPk, pop, commission, description interface{}) *gomock.Call { +// RegisterFinalityProvider indicates an expected call of RegisterFinalityProvider. +func (mr *MockClientControllerMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockClientController)(nil).RegisterValidator), chainPk, valPk, pop, commission, description) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockClientController)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description) } // SubmitBatchFinalitySigs mocks base method. -func (m *MockClientController) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { +func (m *MockClientController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", valPk, blocks, sigs) + ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", fpPk, blocks, sigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. -func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(valPk, blocks, sigs interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(fpPk, blocks, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), fpPk, blocks, sigs) } // SubmitCovenantSigs mocks base method. @@ -247,60 +247,60 @@ func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxH } // SubmitFinalitySig mocks base method. -func (m *MockClientController) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { +func (m *MockClientController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) + ret := m.ctrl.Call(m, "SubmitFinalitySig", fpPk, blockHeight, blockHash, sig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(fpPk, blockHeight, blockHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), fpPk, blockHeight, blockHash, sig) } -// MockValidatorAPIs is a mock of ValidatorAPIs interface. -type MockValidatorAPIs struct { +// MockFinalityProviderAPIs is a mock of FinalityProviderAPIs interface. +type MockFinalityProviderAPIs struct { ctrl *gomock.Controller - recorder *MockValidatorAPIsMockRecorder + recorder *MockFinalityProviderAPIsMockRecorder } -// MockValidatorAPIsMockRecorder is the mock recorder for MockValidatorAPIs. -type MockValidatorAPIsMockRecorder struct { - mock *MockValidatorAPIs +// MockFinalityProviderAPIsMockRecorder is the mock recorder for MockFinalityProviderAPIs. +type MockFinalityProviderAPIsMockRecorder struct { + mock *MockFinalityProviderAPIs } -// NewMockValidatorAPIs creates a new mock instance. -func NewMockValidatorAPIs(ctrl *gomock.Controller) *MockValidatorAPIs { - mock := &MockValidatorAPIs{ctrl: ctrl} - mock.recorder = &MockValidatorAPIsMockRecorder{mock} +// NewMockFinalityProviderAPIs creates a new mock instance. +func NewMockFinalityProviderAPIs(ctrl *gomock.Controller) *MockFinalityProviderAPIs { + mock := &MockFinalityProviderAPIs{ctrl: ctrl} + mock.recorder = &MockFinalityProviderAPIsMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockValidatorAPIs) EXPECT() *MockValidatorAPIsMockRecorder { +func (m *MockFinalityProviderAPIs) EXPECT() *MockFinalityProviderAPIsMockRecorder { return m.recorder } // CommitPubRandList mocks base method. -func (m *MockValidatorAPIs) CommitPubRandList(valPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { +func (m *MockFinalityProviderAPIs) 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", valPk, startHeight, pubRandList, sig) + 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 *MockValidatorAPIsMockRecorder) CommitPubRandList(valPk, startHeight, pubRandList, sig interface{}) *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) CommitPubRandList(fpPk, startHeight, pubRandList, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockValidatorAPIs)(nil).CommitPubRandList), valPk, startHeight, pubRandList, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).CommitPubRandList), fpPk, startHeight, pubRandList, sig) } // QueryActivatedHeight mocks base method. -func (m *MockValidatorAPIs) QueryActivatedHeight() (uint64, error) { +func (m *MockFinalityProviderAPIs) QueryActivatedHeight() (uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryActivatedHeight") ret0, _ := ret[0].(uint64) @@ -309,13 +309,13 @@ func (m *MockValidatorAPIs) QueryActivatedHeight() (uint64, error) { } // QueryActivatedHeight indicates an expected call of QueryActivatedHeight. -func (mr *MockValidatorAPIsMockRecorder) QueryActivatedHeight() *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) QueryActivatedHeight() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryActivatedHeight)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryActivatedHeight)) } // QueryBestBlock mocks base method. -func (m *MockValidatorAPIs) QueryBestBlock() (*types.BlockInfo, error) { +func (m *MockFinalityProviderAPIs) QueryBestBlock() (*types.BlockInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryBestBlock") ret0, _ := ret[0].(*types.BlockInfo) @@ -324,13 +324,13 @@ func (m *MockValidatorAPIs) QueryBestBlock() (*types.BlockInfo, error) { } // QueryBestBlock indicates an expected call of QueryBestBlock. -func (mr *MockValidatorAPIsMockRecorder) QueryBestBlock() *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) QueryBestBlock() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBestBlock)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBestBlock)) } // QueryBlock mocks base method. -func (m *MockValidatorAPIs) QueryBlock(height uint64) (*types.BlockInfo, error) { +func (m *MockFinalityProviderAPIs) QueryBlock(height uint64) (*types.BlockInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryBlock", height) ret0, _ := ret[0].(*types.BlockInfo) @@ -339,13 +339,13 @@ func (m *MockValidatorAPIs) QueryBlock(height uint64) (*types.BlockInfo, error) } // QueryBlock indicates an expected call of QueryBlock. -func (mr *MockValidatorAPIsMockRecorder) QueryBlock(height interface{}) *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) QueryBlock(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBlock), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBlock), height) } // QueryBlocks mocks base method. -func (m *MockValidatorAPIs) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { +func (m *MockFinalityProviderAPIs) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) ret0, _ := ret[0].([]*types.BlockInfo) @@ -354,99 +354,99 @@ func (m *MockValidatorAPIs) QueryBlocks(startHeight, endHeight, limit uint64) ([ } // QueryBlocks indicates an expected call of QueryBlocks. -func (mr *MockValidatorAPIsMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryBlocks), startHeight, endHeight, limit) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBlocks), startHeight, endHeight, limit) } -// QueryLatestFinalizedBlocks mocks base method. -func (m *MockValidatorAPIs) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { +// QueryFinalityProviderSlashed mocks base method. +func (m *MockFinalityProviderAPIs) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) - ret0, _ := ret[0].([]*types.BlockInfo) + ret := m.ctrl.Call(m, "QueryFinalityProviderSlashed", fpPk) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. -func (mr *MockValidatorAPIsMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { +// QueryFinalityProviderSlashed indicates an expected call of QueryFinalityProviderSlashed. +func (mr *MockFinalityProviderAPIsMockRecorder) QueryFinalityProviderSlashed(fpPk interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryLatestFinalizedBlocks), count) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderSlashed", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryFinalityProviderSlashed), fpPk) } -// QueryValidatorSlashed mocks base method. -func (m *MockValidatorAPIs) QueryValidatorSlashed(valPk *btcec.PublicKey) (bool, error) { +// QueryFinalityProviderVotingPower mocks base method. +func (m *MockFinalityProviderAPIs) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorSlashed", valPk) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "QueryFinalityProviderVotingPower", fpPk, blockHeight) + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryValidatorSlashed indicates an expected call of QueryValidatorSlashed. -func (mr *MockValidatorAPIsMockRecorder) QueryValidatorSlashed(valPk interface{}) *gomock.Call { +// QueryFinalityProviderVotingPower indicates an expected call of QueryFinalityProviderVotingPower. +func (mr *MockFinalityProviderAPIsMockRecorder) QueryFinalityProviderVotingPower(fpPk, blockHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorSlashed", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryValidatorSlashed), valPk) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) } -// QueryValidatorVotingPower mocks base method. -func (m *MockValidatorAPIs) QueryValidatorVotingPower(valPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { +// QueryLatestFinalizedBlocks mocks base method. +func (m *MockFinalityProviderAPIs) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorVotingPower", valPk, blockHeight) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) + ret0, _ := ret[0].([]*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryValidatorVotingPower indicates an expected call of QueryValidatorVotingPower. -func (mr *MockValidatorAPIsMockRecorder) QueryValidatorVotingPower(valPk, blockHeight interface{}) *gomock.Call { +// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. +func (mr *MockFinalityProviderAPIsMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockValidatorAPIs)(nil).QueryValidatorVotingPower), valPk, blockHeight) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryLatestFinalizedBlocks), count) } -// RegisterValidator mocks base method. -func (m *MockValidatorAPIs) RegisterValidator(chainPk []byte, valPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { +// RegisterFinalityProvider mocks base method. +func (m *MockFinalityProviderAPIs) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterValidator", chainPk, valPk, pop, commission, description) + ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RegisterValidator indicates an expected call of RegisterValidator. -func (mr *MockValidatorAPIsMockRecorder) RegisterValidator(chainPk, valPk, pop, commission, description interface{}) *gomock.Call { +// RegisterFinalityProvider indicates an expected call of RegisterFinalityProvider. +func (mr *MockFinalityProviderAPIsMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockValidatorAPIs)(nil).RegisterValidator), chainPk, valPk, pop, commission, description) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description) } // SubmitBatchFinalitySigs mocks base method. -func (m *MockValidatorAPIs) SubmitBatchFinalitySigs(valPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { +func (m *MockFinalityProviderAPIs) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", valPk, blocks, sigs) + ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", fpPk, blocks, sigs) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. -func (mr *MockValidatorAPIsMockRecorder) SubmitBatchFinalitySigs(valPk, blocks, sigs interface{}) *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) SubmitBatchFinalitySigs(fpPk, blocks, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitBatchFinalitySigs), valPk, blocks, sigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).SubmitBatchFinalitySigs), fpPk, blocks, sigs) } // SubmitFinalitySig mocks base method. -func (m *MockValidatorAPIs) SubmitFinalitySig(valPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { +func (m *MockFinalityProviderAPIs) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", valPk, blockHeight, blockHash, sig) + ret := m.ctrl.Call(m, "SubmitFinalitySig", fpPk, blockHeight, blockHash, sig) ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockValidatorAPIsMockRecorder) SubmitFinalitySig(valPk, blockHeight, blockHash, sig interface{}) *gomock.Call { +func (mr *MockFinalityProviderAPIsMockRecorder) SubmitFinalitySig(fpPk, blockHeight, blockHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockValidatorAPIs)(nil).SubmitFinalitySig), valPk, blockHeight, blockHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).SubmitFinalitySig), fpPk, blockHeight, blockHash, sig) } // MockCovenantAPIs is a mock of CovenantAPIs interface. diff --git a/testutil/store.go b/testutil/store.go index 67b13631..8232282a 100644 --- a/testutil/store.go +++ b/testutil/store.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - kvstore "github.com/babylonchain/btc-validator/store" + kvstore "github.com/babylonchain/finality-provider/store" ) func CreateStore(r *rand.Rand, t *testing.T) (kvstore.Store, string) { diff --git a/testutil/utils.go b/testutil/utils.go index a9235e6f..ca3b8808 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -7,8 +7,8 @@ import ( sdkmath "cosmossdk.io/math" "github.com/golang/mock/gomock" - "github.com/babylonchain/btc-validator/testutil/mocks" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" ) func EmptyDescription() []byte { diff --git a/tools/go.mod b/tools/go.mod index 9c318e5a..5cc29ef9 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,4 +1,4 @@ -module github.com/babylonchain/btc-validator/tools +module github.com/babylonchain/finality-provider/tools go 1.21 @@ -212,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index 6b2e2198..52d832dd 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b h1:FAadQ5l5ORQa/P8IRRtHXibK7g7MHOzhKxmvObY42OI= -github.com/babylonchain/babylon-private v0.0.0-20231212092759-3504554e618b/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= +github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 h1:fFlLF+rl6Buwb3eYgIoUQ4JkYdNMMTk9ihoznTTw2hk= +github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= 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= diff --git a/tools/tools.go b/tools/tools.go index 213715c3..752851fa 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -1,7 +1,7 @@ //go:build tools // +build tools -package btcvalidator +package finalityprovider import ( _ "github.com/babylonchain/babylon/cmd/babylond" diff --git a/types/delegation.go b/types/delegation.go index 92014754..c326c1d3 100644 --- a/types/delegation.go +++ b/types/delegation.go @@ -11,9 +11,9 @@ import ( type Delegation struct { // The Bitcoin secp256k1 PK of this BTC delegation BtcPk *btcec.PublicKey - // The Bitcoin secp256k1 PKs of the BTC validators that + // The Bitcoin secp256k1 PKs of the finality providers that // this BTC delegation delegates to - ValBtcPks []*btcec.PublicKey + FpBtcPks []*btcec.PublicKey // The start BTC height of the BTC delegation // it is the start BTC height of the timelock StartHeight uint64 @@ -48,7 +48,7 @@ func (d *Delegation) GetStakingTime() uint16 { diff := d.EndHeight - d.StartHeight if diff > math.MaxUint16 { - // In valid delegation, EndHeight is always greater than StartHeight and it is always uint16 value + // In a valid delegation, EndHeight is always greater than StartHeight and it is always uint16 value panic("invalid delegation in database") } @@ -65,7 +65,7 @@ type Undelegation struct { UnbondingTxHex string // The hex string of the slashing tx for unbonding transactions // It is partially signed by SK corresponding to btc_pk, but not signed by - // validator or covenant yet. + // finality provider or covenant yet. SlashingTxHex string // The signatures on the slashing tx by the covenant // (i.e., SK corresponding to covenant_pk in params) diff --git a/validator/cmd/vald/start.go b/validator/cmd/vald/start.go deleted file mode 100644 index 57ffe188..00000000 --- a/validator/cmd/vald/start.go +++ /dev/null @@ -1,89 +0,0 @@ -package main - -import ( - "fmt" - "github.com/babylonchain/babylon/types" - "github.com/babylonchain/btc-validator/log" - "github.com/babylonchain/btc-validator/util" - "github.com/lightningnetwork/lnd/signal" - "github.com/urfave/cli" - "path/filepath" - - valcfg "github.com/babylonchain/btc-validator/validator/config" - "github.com/babylonchain/btc-validator/validator/service" -) - -var startCommand = cli.Command{ - Name: "start", - Usage: "vald start", - Description: "Start the validator daemon. Note that eotsd should be started beforehand", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: passphraseFlag, - Usage: "The pass phrase used to decrypt the private key", - Value: defaultPassphrase, - }, - cli.StringFlag{ - Name: homeFlag, - Usage: "The path to the validator home directory", - Value: valcfg.DefaultValdDir, - }, - cli.StringFlag{ - Name: valPkFlag, - Usage: "The public key of the validator to start", - }, - }, - Action: start, -} - -func start(ctx *cli.Context) error { - homePath, err := filepath.Abs(ctx.String(homeFlag)) - if err != nil { - return err - } - homePath = util.CleanAndExpandPath(homePath) - passphrase := ctx.String(passphraseFlag) - valPkStr := ctx.String(valPkFlag) - - cfg, err := valcfg.LoadConfig(homePath) - if err != nil { - return fmt.Errorf("failed to load configuration: %w", err) - } - - logger, err := log.NewRootLoggerWithFile(valcfg.LogFile(homePath), cfg.LogLevel) - if err != nil { - return fmt.Errorf("failed to initialize the logger") - } - - valApp, err := service.NewValidatorAppFromConfig(homePath, cfg, logger) - if err != nil { - return fmt.Errorf("failed to create validator app: %v", err) - } - - // only start the daemon without starting any validator instance - // as there might be no validator registered yet - if err := valApp.Start(); err != nil { - return fmt.Errorf("failed to start the validator daemon: %w", err) - } - - if valPkStr != "" { - // start the validator instance with the given public key - valPk, err := types.NewBIP340PubKeyFromHex(valPkStr) - if err != nil { - return fmt.Errorf("invalid validator public key %s: %w", valPkStr, err) - } - if err := valApp.StartHandlingValidator(valPk, passphrase); err != nil { - return fmt.Errorf("failed to start the validator instance %s: %w", valPkStr, err) - } - } - - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - return err - } - - valServer := service.NewValidatorServer(cfg, logger, valApp, shutdownInterceptor) - - return valServer.RunUntilShutdown() -} diff --git a/validator/proto/validators.go b/validator/proto/validators.go deleted file mode 100644 index 45128f06..00000000 --- a/validator/proto/validators.go +++ /dev/null @@ -1,45 +0,0 @@ -package proto - -import ( - "encoding/hex" - "fmt" - - 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" -) - -func (v *StoreValidator) GetBabylonPK() *secp256k1.PubKey { - return &secp256k1.PubKey{ - Key: v.BabylonPk, - } -} - -func (v *StoreValidator) GetBabylonPkHexString() string { - return hex.EncodeToString(v.BabylonPk) -} - -func (v *StoreValidator) MustGetBTCPK() *btcec.PublicKey { - btcPubKey, err := schnorr.ParsePubKey(v.BtcPk) - if err != nil { - panic(fmt.Errorf("failed to parse BTC PK: %w", err)) - } - return btcPubKey -} - -func (v *StoreValidator) MustGetBIP340BTCPK() *bbn.BIP340PubKey { - btcPK := v.MustGetBTCPK() - return bbn.NewBIP340PubKeyFromBTCPK(btcPK) -} - -func NewValidatorInfo(v *StoreValidator) *ValidatorInfo { - return &ValidatorInfo{ - BabylonPkHex: v.GetBabylonPkHexString(), - BtcPkHex: v.MustGetBIP340BTCPK().MarshalHex(), - Description: v.Description, - LastVotedHeight: v.LastVotedHeight, - LastCommittedHeight: v.LastCommittedHeight, - Status: v.Status, - } -} diff --git a/validator/proto/validators.pb.go b/validator/proto/validators.pb.go deleted file mode 100644 index 163e22e2..00000000 --- a/validator/proto/validators.pb.go +++ /dev/null @@ -1,1559 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.0 -// protoc (unknown) -// source: validators.proto - -package proto - -import ( - _ "github.com/cosmos/cosmos-proto" - _ "github.com/cosmos/cosmos-sdk/x/staking/types" - _ "github.com/cosmos/gogoproto/gogoproto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// ValidatorStatus is the status of a BTC validator -// a Validator object has 4 states: -// - Created - created and managed by validator client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, 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. -// Validator was already active. -// Valid State Transactions: -// - Created -> Registered -// - Registered -> Active -// - Active -> Inactive -// - Inactive -> Active -type ValidatorStatus int32 - -const ( - // CREATED defines a validator that is awaiting registration - ValidatorStatus_CREATED ValidatorStatus = 0 - // REGISTERED defines a validator that has been registered - // to Babylon but has no delegated stake - ValidatorStatus_REGISTERED ValidatorStatus = 1 - // ACTIVE defines a validator that is delegated to vote - ValidatorStatus_ACTIVE ValidatorStatus = 2 - // INACTIVE defines a validator whose delegations are reduced to zero but not slashed - ValidatorStatus_INACTIVE ValidatorStatus = 3 - // SLASHED defines a validator that has been slashed - ValidatorStatus_SLASHED ValidatorStatus = 4 -) - -// Enum value maps for ValidatorStatus. -var ( - ValidatorStatus_name = map[int32]string{ - 0: "CREATED", - 1: "REGISTERED", - 2: "ACTIVE", - 3: "INACTIVE", - 4: "SLASHED", - } - ValidatorStatus_value = map[string]int32{ - "CREATED": 0, - "REGISTERED": 1, - "ACTIVE": 2, - "INACTIVE": 3, - "SLASHED": 4, - } -) - -func (x ValidatorStatus) Enum() *ValidatorStatus { - p := new(ValidatorStatus) - *p = x - return p -} - -func (x ValidatorStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ValidatorStatus) Descriptor() protoreflect.EnumDescriptor { - return file_validators_proto_enumTypes[0].Descriptor() -} - -func (ValidatorStatus) Type() protoreflect.EnumType { - return &file_validators_proto_enumTypes[0] -} - -func (x ValidatorStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ValidatorStatus.Descriptor instead. -func (ValidatorStatus) EnumDescriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{0} -} - -type GetInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetInfoRequest) Reset() { - *x = GetInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetInfoRequest) ProtoMessage() {} - -func (x *GetInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[0] - 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 GetInfoRequest.ProtoReflect.Descriptor instead. -func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{0} -} - -type GetInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *GetInfoResponse) Reset() { - *x = GetInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetInfoResponse) ProtoMessage() {} - -func (x *GetInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[1] - 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 GetInfoResponse.ProtoReflect.Descriptor instead. -func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{1} -} - -func (x *GetInfoResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type CreateValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // key_name is the identifier key in keyring - KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` - // passphrase is used to encrypt the keys - Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` - // hd_path is the hd path for private key derivation - HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` - // chain_id is the identifier of the consumer chain that the validator connected to - ChainId string `protobuf:"bytes,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - // description defines the description terms for the validator - Description []byte `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - Commission string `protobuf:"bytes,6,opt,name=commission,proto3" json:"commission,omitempty"` -} - -func (x *CreateValidatorRequest) Reset() { - *x = CreateValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateValidatorRequest) ProtoMessage() {} - -func (x *CreateValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[2] - 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 CreateValidatorRequest.ProtoReflect.Descriptor instead. -func (*CreateValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{2} -} - -func (x *CreateValidatorRequest) GetKeyName() string { - if x != nil { - return x.KeyName - } - return "" -} - -func (x *CreateValidatorRequest) GetPassphrase() string { - if x != nil { - return x.Passphrase - } - return "" -} - -func (x *CreateValidatorRequest) GetHdPath() string { - if x != nil { - return x.HdPath - } - return "" -} - -func (x *CreateValidatorRequest) GetChainId() string { - if x != nil { - return x.ChainId - } - return "" -} - -func (x *CreateValidatorRequest) GetDescription() []byte { - if x != nil { - return x.Description - } - return nil -} - -func (x *CreateValidatorRequest) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -type CreateValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // btc_pk is the hex string of BTC secp256k1 public key of the validator encoded in BIP-340 spec - BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` -} - -func (x *CreateValidatorResponse) Reset() { - *x = CreateValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateValidatorResponse) ProtoMessage() {} - -func (x *CreateValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[3] - 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 CreateValidatorResponse.ProtoReflect.Descriptor instead. -func (*CreateValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{3} -} - -func (x *CreateValidatorResponse) GetBtcPk() string { - if x != nil { - return x.BtcPk - } - return "" -} - -type RegisterValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec - BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` - // passphrase is used to encrypt the keys - Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` -} - -func (x *RegisterValidatorRequest) Reset() { - *x = RegisterValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterValidatorRequest) ProtoMessage() {} - -func (x *RegisterValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[4] - 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 RegisterValidatorRequest.ProtoReflect.Descriptor instead. -func (*RegisterValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{4} -} - -func (x *RegisterValidatorRequest) GetBtcPk() string { - if x != nil { - return x.BtcPk - } - return "" -} - -func (x *RegisterValidatorRequest) GetPassphrase() string { - if x != nil { - return x.Passphrase - } - return "" -} - -type RegisterValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // hash of the successful Babylon registration transaction - TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` -} - -func (x *RegisterValidatorResponse) Reset() { - *x = RegisterValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterValidatorResponse) ProtoMessage() {} - -func (x *RegisterValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[5] - 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 RegisterValidatorResponse.ProtoReflect.Descriptor instead. -func (*RegisterValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{5} -} - -func (x *RegisterValidatorResponse) GetTxHash() string { - if x != nil { - return x.TxHash - } - return "" -} - -type AddFinalitySignatureRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // btc_pk is hex string of the BTC secp256k1 public key of the validator 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 uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - // app_hash is the AppHash of the Babylon block - AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` -} - -func (x *AddFinalitySignatureRequest) Reset() { - *x = AddFinalitySignatureRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddFinalitySignatureRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddFinalitySignatureRequest) ProtoMessage() {} - -func (x *AddFinalitySignatureRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[6] - 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 AddFinalitySignatureRequest.ProtoReflect.Descriptor instead. -func (*AddFinalitySignatureRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{6} -} - -func (x *AddFinalitySignatureRequest) GetBtcPk() string { - if x != nil { - return x.BtcPk - } - return "" -} - -func (x *AddFinalitySignatureRequest) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *AddFinalitySignatureRequest) GetAppHash() []byte { - if x != nil { - return x.AppHash - } - return nil -} - -type AddFinalitySignatureResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // hash of the successful Babylon 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"` - // the hex string of the local Bitcoin secp256k1 private key - LocalSkHex string `protobuf:"bytes,3,opt,name=local_sk_hex,json=localSkHex,proto3" json:"local_sk_hex,omitempty"` -} - -func (x *AddFinalitySignatureResponse) Reset() { - *x = AddFinalitySignatureResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddFinalitySignatureResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddFinalitySignatureResponse) ProtoMessage() {} - -func (x *AddFinalitySignatureResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[7] - 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 AddFinalitySignatureResponse.ProtoReflect.Descriptor instead. -func (*AddFinalitySignatureResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{7} -} - -func (x *AddFinalitySignatureResponse) GetTxHash() string { - if x != nil { - return x.TxHash - } - return "" -} - -func (x *AddFinalitySignatureResponse) GetExtractedSkHex() string { - if x != nil { - return x.ExtractedSkHex - } - return "" -} - -func (x *AddFinalitySignatureResponse) GetLocalSkHex() string { - if x != nil { - return x.LocalSkHex - } - return "" -} - -type QueryValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // btc_pk is hex string of the BTC secp256k1 public key of the validator encoded in BIP-340 spec - BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` -} - -func (x *QueryValidatorRequest) Reset() { - *x = QueryValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorRequest) ProtoMessage() {} - -func (x *QueryValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[8] - 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 QueryValidatorRequest.ProtoReflect.Descriptor instead. -func (*QueryValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{8} -} - -func (x *QueryValidatorRequest) GetBtcPk() string { - if x != nil { - return x.BtcPk - } - return "" -} - -type QueryValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Validator *ValidatorInfo `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"` -} - -func (x *QueryValidatorResponse) Reset() { - *x = QueryValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorResponse) ProtoMessage() {} - -func (x *QueryValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[9] - 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 QueryValidatorResponse.ProtoReflect.Descriptor instead. -func (*QueryValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{9} -} - -func (x *QueryValidatorResponse) GetValidator() *ValidatorInfo { - if x != nil { - return x.Validator - } - return nil -} - -type QueryValidatorListRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *QueryValidatorListRequest) Reset() { - *x = QueryValidatorListRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorListRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorListRequest) ProtoMessage() {} - -func (x *QueryValidatorListRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[10] - 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 QueryValidatorListRequest.ProtoReflect.Descriptor instead. -func (*QueryValidatorListRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{10} -} - -type QueryValidatorListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Validators []*ValidatorInfo `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"` // TODO add pagination in case the list gets large -} - -func (x *QueryValidatorListResponse) Reset() { - *x = QueryValidatorListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorListResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorListResponse) ProtoMessage() {} - -func (x *QueryValidatorListResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[11] - 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 QueryValidatorListResponse.ProtoReflect.Descriptor instead. -func (*QueryValidatorListResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{11} -} - -func (x *QueryValidatorListResponse) GetValidators() []*ValidatorInfo { - if x != nil { - return x.Validators - } - return nil -} - -type StoreValidator struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` - // btc_pk is the BTC secp256k1 PK of the validator 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 validator - Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - 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 *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,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"` - // chain_id is the identifier of the consumer chain that the validator 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"` - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,9,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_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,10,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` - // status defines the current validator status - Status ValidatorStatus `protobuf:"varint,11,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` -} - -func (x *StoreValidator) Reset() { - *x = StoreValidator{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StoreValidator) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StoreValidator) ProtoMessage() {} - -func (x *StoreValidator) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[12] - 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 StoreValidator.ProtoReflect.Descriptor instead. -func (*StoreValidator) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{12} -} - -func (x *StoreValidator) GetBabylonPk() []byte { - if x != nil { - return x.BabylonPk - } - return nil -} - -func (x *StoreValidator) GetBtcPk() []byte { - if x != nil { - return x.BtcPk - } - return nil -} - -func (x *StoreValidator) GetDescription() []byte { - if x != nil { - return x.Description - } - return nil -} - -func (x *StoreValidator) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -func (x *StoreValidator) GetPop() *ProofOfPossession { - if x != nil { - return x.Pop - } - return nil -} - -func (x *StoreValidator) GetKeyName() string { - if x != nil { - return x.KeyName - } - return "" -} - -func (x *StoreValidator) GetChainId() string { - if x != nil { - return x.ChainId - } - return "" -} - -func (x *StoreValidator) GetLastVotedHeight() uint64 { - if x != nil { - return x.LastVotedHeight - } - return 0 -} - -func (x *StoreValidator) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - -func (x *StoreValidator) GetLastProcessedHeight() uint64 { - if x != nil { - return x.LastProcessedHeight - } - return 0 -} - -func (x *StoreValidator) GetStatus() ValidatorStatus { - if x != nil { - return x.Status - } - return ValidatorStatus_CREATED -} - -// ValidatorInfo is the basic information of a validator mainly for external usage -type ValidatorInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this BTC validator - BabylonPkHex string `protobuf:"bytes,1,opt,name=babylon_pk_hex,json=babylonPkHex,proto3" json:"babylon_pk_hex,omitempty"` - // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator 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 validator - Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - 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"` - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,6,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` - // status defines the current validator status - Status ValidatorStatus `protobuf:"varint,7,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` -} - -func (x *ValidatorInfo) Reset() { - *x = ValidatorInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ValidatorInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValidatorInfo) ProtoMessage() {} - -func (x *ValidatorInfo) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[13] - 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 ValidatorInfo.ProtoReflect.Descriptor instead. -func (*ValidatorInfo) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{13} -} - -func (x *ValidatorInfo) GetBabylonPkHex() string { - if x != nil { - return x.BabylonPkHex - } - return "" -} - -func (x *ValidatorInfo) GetBtcPkHex() string { - if x != nil { - return x.BtcPkHex - } - return "" -} - -func (x *ValidatorInfo) GetDescription() []byte { - if x != nil { - return x.Description - } - return nil -} - -func (x *ValidatorInfo) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -func (x *ValidatorInfo) GetLastVotedHeight() uint64 { - if x != nil { - return x.LastVotedHeight - } - return 0 -} - -func (x *ValidatorInfo) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - -func (x *ValidatorInfo) GetStatus() ValidatorStatus { - if x != nil { - return x.Status - } - return ValidatorStatus_CREATED -} - -// ProofOfPossession is the proof of possession that a Babylon secp256k1 -// secret key and a Bitcoin secp256k1 secret key are held by the same -// person -type ProofOfPossession struct { - state protoimpl.MessageState - 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) - // the signature follows encoding in BIP-340 spec - BtcSig []byte `protobuf:"bytes,2,opt,name=btc_sig,json=btcSig,proto3" json:"btc_sig,omitempty"` -} - -func (x *ProofOfPossession) Reset() { - *x = ProofOfPossession{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProofOfPossession) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProofOfPossession) ProtoMessage() {} - -func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[14] - 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 ProofOfPossession.ProtoReflect.Descriptor instead. -func (*ProofOfPossession) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{14} -} - -func (x *ProofOfPossession) GetBabylonSig() []byte { - if x != nil { - return x.BabylonSig - } - return nil -} - -func (x *ProofOfPossession) GetBtcSig() []byte { - if x != nil { - return x.BtcSig - } - return nil -} - -type SchnorrRandPair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PubRand []byte `protobuf:"bytes,1,opt,name=pub_rand,json=pubRand,proto3" json:"pub_rand,omitempty"` - SecRand []byte `protobuf:"bytes,2,opt,name=sec_rand,json=secRand,proto3" json:"sec_rand,omitempty"` -} - -func (x *SchnorrRandPair) Reset() { - *x = SchnorrRandPair{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SchnorrRandPair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SchnorrRandPair) ProtoMessage() {} - -func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[15] - 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 SchnorrRandPair.ProtoReflect.Descriptor instead. -func (*SchnorrRandPair) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{15} -} - -func (x *SchnorrRandPair) GetPubRand() []byte { - if x != nil { - return x.PubRand - } - return nil -} - -func (x *SchnorrRandPair) GetSecRand() []byte { - if x != nil { - return x.SecRand - } - return nil -} - -var File_validators_proto protoreflect.FileDescriptor - -var file_validators_proto_rawDesc = []byte{ - 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xee, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, - 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, 0x02, 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, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 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, 0x06, 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, - 0x22, 0x30, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x62, - 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, - 0x50, 0x6b, 0x22, 0x51, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, - 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x62, 0x74, 0x63, 0x50, 0x6b, 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, 0x34, 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x67, 0x0a, 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, - 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, - 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, - 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, - 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, - 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x15, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xd3, 0x03, 0x0a, 0x0e, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 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, 0x0a, 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, - 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0xca, 0x02, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 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, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 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, 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, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 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, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 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, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 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, 0x4d, 0x0a, - 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, - 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x12, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x37, 0x5a, 0x35, 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, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_validators_proto_rawDescOnce sync.Once - file_validators_proto_rawDescData = file_validators_proto_rawDesc -) - -func file_validators_proto_rawDescGZIP() []byte { - file_validators_proto_rawDescOnce.Do(func() { - file_validators_proto_rawDescData = protoimpl.X.CompressGZIP(file_validators_proto_rawDescData) - }) - return file_validators_proto_rawDescData -} - -var file_validators_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_validators_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_validators_proto_goTypes = []interface{}{ - (ValidatorStatus)(0), // 0: proto.ValidatorStatus - (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest - (*GetInfoResponse)(nil), // 2: proto.GetInfoResponse - (*CreateValidatorRequest)(nil), // 3: proto.CreateValidatorRequest - (*CreateValidatorResponse)(nil), // 4: proto.CreateValidatorResponse - (*RegisterValidatorRequest)(nil), // 5: proto.RegisterValidatorRequest - (*RegisterValidatorResponse)(nil), // 6: proto.RegisterValidatorResponse - (*AddFinalitySignatureRequest)(nil), // 7: proto.AddFinalitySignatureRequest - (*AddFinalitySignatureResponse)(nil), // 8: proto.AddFinalitySignatureResponse - (*QueryValidatorRequest)(nil), // 9: proto.QueryValidatorRequest - (*QueryValidatorResponse)(nil), // 10: proto.QueryValidatorResponse - (*QueryValidatorListRequest)(nil), // 11: proto.QueryValidatorListRequest - (*QueryValidatorListResponse)(nil), // 12: proto.QueryValidatorListResponse - (*StoreValidator)(nil), // 13: proto.StoreValidator - (*ValidatorInfo)(nil), // 14: proto.ValidatorInfo - (*ProofOfPossession)(nil), // 15: proto.ProofOfPossession - (*SchnorrRandPair)(nil), // 16: proto.SchnorrRandPair -} -var file_validators_proto_depIdxs = []int32{ - 14, // 0: proto.QueryValidatorResponse.validator:type_name -> proto.ValidatorInfo - 14, // 1: proto.QueryValidatorListResponse.validators:type_name -> proto.ValidatorInfo - 15, // 2: proto.StoreValidator.pop:type_name -> proto.ProofOfPossession - 0, // 3: proto.StoreValidator.status:type_name -> proto.ValidatorStatus - 0, // 4: proto.ValidatorInfo.status:type_name -> proto.ValidatorStatus - 1, // 5: proto.BtcValidators.GetInfo:input_type -> proto.GetInfoRequest - 3, // 6: proto.BtcValidators.CreateValidator:input_type -> proto.CreateValidatorRequest - 5, // 7: proto.BtcValidators.RegisterValidator:input_type -> proto.RegisterValidatorRequest - 7, // 8: proto.BtcValidators.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest - 9, // 9: proto.BtcValidators.QueryValidator:input_type -> proto.QueryValidatorRequest - 11, // 10: proto.BtcValidators.QueryValidatorList:input_type -> proto.QueryValidatorListRequest - 2, // 11: proto.BtcValidators.GetInfo:output_type -> proto.GetInfoResponse - 4, // 12: proto.BtcValidators.CreateValidator:output_type -> proto.CreateValidatorResponse - 6, // 13: proto.BtcValidators.RegisterValidator:output_type -> proto.RegisterValidatorResponse - 8, // 14: proto.BtcValidators.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse - 10, // 15: proto.BtcValidators.QueryValidator:output_type -> proto.QueryValidatorResponse - 12, // 16: proto.BtcValidators.QueryValidatorList:output_type -> proto.QueryValidatorListResponse - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name -} - -func init() { file_validators_proto_init() } -func file_validators_proto_init() { - if File_validators_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_validators_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddFinalitySignatureRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddFinalitySignatureResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorListRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorListResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StoreValidator); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidatorInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProofOfPossession); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SchnorrRandPair); 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{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_validators_proto_rawDesc, - NumEnums: 1, - NumMessages: 16, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_validators_proto_goTypes, - DependencyIndexes: file_validators_proto_depIdxs, - EnumInfos: file_validators_proto_enumTypes, - MessageInfos: file_validators_proto_msgTypes, - }.Build() - File_validators_proto = out.File - file_validators_proto_rawDesc = nil - file_validators_proto_goTypes = nil - file_validators_proto_depIdxs = nil -} diff --git a/validator/proto/validators_grpc.pb.go b/validator/proto/validators_grpc.pb.go deleted file mode 100644 index 64ac1744..00000000 --- a/validator/proto/validators_grpc.pb.go +++ /dev/null @@ -1,310 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc (unknown) -// source: validators.proto - -package proto - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - BtcValidators_GetInfo_FullMethodName = "/proto.BtcValidators/GetInfo" - BtcValidators_CreateValidator_FullMethodName = "/proto.BtcValidators/CreateValidator" - BtcValidators_RegisterValidator_FullMethodName = "/proto.BtcValidators/RegisterValidator" - BtcValidators_AddFinalitySignature_FullMethodName = "/proto.BtcValidators/AddFinalitySignature" - BtcValidators_QueryValidator_FullMethodName = "/proto.BtcValidators/QueryValidator" - BtcValidators_QueryValidatorList_FullMethodName = "/proto.BtcValidators/QueryValidatorList" -) - -// BtcValidatorsClient is the client API for BtcValidators service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type BtcValidatorsClient interface { - // GetInfo returns the information of the daemon - GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) - // CreateValidator generates and saves a validator object - CreateValidator(ctx context.Context, in *CreateValidatorRequest, opts ...grpc.CallOption) (*CreateValidatorResponse, error) - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - RegisterValidator(ctx context.Context, in *RegisterValidatorRequest, opts ...grpc.CallOption) (*RegisterValidatorResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality - // signature for a block - AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) - // QueryValidator queries the validator - QueryValidator(ctx context.Context, in *QueryValidatorRequest, opts ...grpc.CallOption) (*QueryValidatorResponse, error) - // QueryValidatorList queries a list of validators - QueryValidatorList(ctx context.Context, in *QueryValidatorListRequest, opts ...grpc.CallOption) (*QueryValidatorListResponse, error) -} - -type btcValidatorsClient struct { - cc grpc.ClientConnInterface -} - -func NewBtcValidatorsClient(cc grpc.ClientConnInterface) BtcValidatorsClient { - return &btcValidatorsClient{cc} -} - -func (c *btcValidatorsClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) { - out := new(GetInfoResponse) - err := c.cc.Invoke(ctx, BtcValidators_GetInfo_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) CreateValidator(ctx context.Context, in *CreateValidatorRequest, opts ...grpc.CallOption) (*CreateValidatorResponse, error) { - out := new(CreateValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_CreateValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) RegisterValidator(ctx context.Context, in *RegisterValidatorRequest, opts ...grpc.CallOption) (*RegisterValidatorResponse, error) { - out := new(RegisterValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_RegisterValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) { - out := new(AddFinalitySignatureResponse) - err := c.cc.Invoke(ctx, BtcValidators_AddFinalitySignature_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) QueryValidator(ctx context.Context, in *QueryValidatorRequest, opts ...grpc.CallOption) (*QueryValidatorResponse, error) { - out := new(QueryValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_QueryValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) QueryValidatorList(ctx context.Context, in *QueryValidatorListRequest, opts ...grpc.CallOption) (*QueryValidatorListResponse, error) { - out := new(QueryValidatorListResponse) - err := c.cc.Invoke(ctx, BtcValidators_QueryValidatorList_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// BtcValidatorsServer is the server API for BtcValidators service. -// All implementations must embed UnimplementedBtcValidatorsServer -// for forward compatibility -type BtcValidatorsServer interface { - // GetInfo returns the information of the daemon - GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) - // CreateValidator generates and saves a validator object - CreateValidator(context.Context, *CreateValidatorRequest) (*CreateValidatorResponse, error) - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - RegisterValidator(context.Context, *RegisterValidatorRequest) (*RegisterValidatorResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality - // signature for a block - AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) - // QueryValidator queries the validator - QueryValidator(context.Context, *QueryValidatorRequest) (*QueryValidatorResponse, error) - // QueryValidatorList queries a list of validators - QueryValidatorList(context.Context, *QueryValidatorListRequest) (*QueryValidatorListResponse, error) - mustEmbedUnimplementedBtcValidatorsServer() -} - -// UnimplementedBtcValidatorsServer must be embedded to have forward compatible implementations. -type UnimplementedBtcValidatorsServer struct { -} - -func (UnimplementedBtcValidatorsServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") -} -func (UnimplementedBtcValidatorsServer) CreateValidator(context.Context, *CreateValidatorRequest) (*CreateValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) RegisterValidator(context.Context, *RegisterValidatorRequest) (*RegisterValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegisterValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddFinalitySignature not implemented") -} -func (UnimplementedBtcValidatorsServer) QueryValidator(context.Context, *QueryValidatorRequest) (*QueryValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) QueryValidatorList(context.Context, *QueryValidatorListRequest) (*QueryValidatorListResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryValidatorList not implemented") -} -func (UnimplementedBtcValidatorsServer) mustEmbedUnimplementedBtcValidatorsServer() {} - -// UnsafeBtcValidatorsServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to BtcValidatorsServer will -// result in compilation errors. -type UnsafeBtcValidatorsServer interface { - mustEmbedUnimplementedBtcValidatorsServer() -} - -func RegisterBtcValidatorsServer(s grpc.ServiceRegistrar, srv BtcValidatorsServer) { - s.RegisterService(&BtcValidators_ServiceDesc, srv) -} - -func _BtcValidators_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).GetInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_GetInfo_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).GetInfo(ctx, req.(*GetInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_CreateValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).CreateValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_CreateValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).CreateValidator(ctx, req.(*CreateValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_RegisterValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RegisterValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).RegisterValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_RegisterValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).RegisterValidator(ctx, req.(*RegisterValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_AddFinalitySignature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddFinalitySignatureRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).AddFinalitySignature(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_AddFinalitySignature_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).AddFinalitySignature(ctx, req.(*AddFinalitySignatureRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_QueryValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).QueryValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_QueryValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).QueryValidator(ctx, req.(*QueryValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_QueryValidatorList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryValidatorListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).QueryValidatorList(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_QueryValidatorList_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).QueryValidatorList(ctx, req.(*QueryValidatorListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// BtcValidators_ServiceDesc is the grpc.ServiceDesc for BtcValidators service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var BtcValidators_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "proto.BtcValidators", - HandlerType: (*BtcValidatorsServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetInfo", - Handler: _BtcValidators_GetInfo_Handler, - }, - { - MethodName: "CreateValidator", - Handler: _BtcValidators_CreateValidator_Handler, - }, - { - MethodName: "RegisterValidator", - Handler: _BtcValidators_RegisterValidator_Handler, - }, - { - MethodName: "AddFinalitySignature", - Handler: _BtcValidators_AddFinalitySignature_Handler, - }, - { - MethodName: "QueryValidator", - Handler: _BtcValidators_QueryValidator_Handler, - }, - { - MethodName: "QueryValidatorList", - Handler: _BtcValidators_QueryValidatorList_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "validators.proto", -} diff --git a/validator/service/app.go b/validator/service/app.go deleted file mode 100644 index 88551aeb..00000000 --- a/validator/service/app.go +++ /dev/null @@ -1,467 +0,0 @@ -package service - -import ( - "encoding/hex" - "fmt" - "github.com/babylonchain/btc-validator/util" - "strings" - "sync" - - sdkmath "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "go.uber.org/zap" - - valkr "github.com/babylonchain/btc-validator/keyring" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/eotsmanager/client" - valcfg "github.com/babylonchain/btc-validator/validator/config" - "github.com/babylonchain/btc-validator/validator/proto" - - valstore "github.com/babylonchain/btc-validator/validator/store" -) - -type ValidatorApp struct { - startOnce sync.Once - stopOnce sync.Once - - wg sync.WaitGroup - quit chan struct{} - - sentWg sync.WaitGroup - sentQuit chan struct{} - - eventWg sync.WaitGroup - eventQuit chan struct{} - - cc clientcontroller.ClientController - kr keyring.Keyring - vs *valstore.ValidatorStore - config *valcfg.Config - logger *zap.Logger - input *strings.Reader - - validatorManager *ValidatorManager - eotsManager eotsmanager.EOTSManager - - createValidatorRequestChan chan *createValidatorRequest - registerValidatorRequestChan chan *registerValidatorRequest - validatorRegisteredEventChan chan *validatorRegisteredEvent -} - -func NewValidatorAppFromConfig( - homePath string, - config *valcfg.Config, - logger *zap.Logger, -) (*ValidatorApp, error) { - cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.BTCNetParams, logger) - if err != nil { - return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.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) - if err != nil { - return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) - } - // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy - logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) - - return NewValidatorApp(homePath, config, cc, em, logger) -} - -func NewValidatorApp( - homePath string, - config *valcfg.Config, - cc clientcontroller.ClientController, - em eotsmanager.EOTSManager, - logger *zap.Logger, -) (*ValidatorApp, error) { - valStore, err := initStore(homePath, config) - if err != nil { - return nil, fmt.Errorf("failed to load store: %w", err) - } - - input := strings.NewReader("") - kr, err := valkr.CreateKeyring( - config.BabylonConfig.KeyDirectory, - config.BabylonConfig.ChainID, - config.BabylonConfig.KeyringBackend, - input, - ) - if err != nil { - return nil, fmt.Errorf("failed to create keyring: %w", err) - } - - vm, err := NewValidatorManager(valStore, config, cc, em, logger) - if err != nil { - return nil, fmt.Errorf("failed to create validator manager: %w", err) - } - - return &ValidatorApp{ - cc: cc, - vs: valStore, - kr: kr, - config: config, - logger: logger, - input: input, - validatorManager: vm, - eotsManager: em, - quit: make(chan struct{}), - sentQuit: make(chan struct{}), - eventQuit: make(chan struct{}), - createValidatorRequestChan: make(chan *createValidatorRequest), - registerValidatorRequestChan: make(chan *registerValidatorRequest), - validatorRegisteredEventChan: make(chan *validatorRegisteredEvent), - }, nil -} - -func initStore(homePath string, cfg *valcfg.Config) (*valstore.ValidatorStore, error) { - // Create the directory that will store the data - if err := util.MakeDirectory(valcfg.DataDir(homePath)); err != nil { - return nil, err - } - - return valstore.NewValidatorStore(valcfg.DBPath(homePath), cfg.DatabaseConfig.Name, cfg.DatabaseConfig.Backend) -} - -func (app *ValidatorApp) GetConfig() *valcfg.Config { - return app.config -} - -func (app *ValidatorApp) GetValidatorStore() *valstore.ValidatorStore { - return app.vs -} - -func (app *ValidatorApp) GetKeyring() keyring.Keyring { - return app.kr -} - -func (app *ValidatorApp) GetInput() *strings.Reader { - return app.input -} - -func (app *ValidatorApp) ListValidatorInstances() []*ValidatorInstance { - return app.validatorManager.ListValidatorInstances() -} - -// GetValidatorInstance returns the validator instance with the given Babylon public key -func (app *ValidatorApp) GetValidatorInstance(valPk *bbntypes.BIP340PubKey) (*ValidatorInstance, error) { - return app.validatorManager.GetValidatorInstance(valPk) -} - -func (app *ValidatorApp) RegisterValidator(valPkStr string) (*RegisterValidatorResponse, error) { - valPk, err := bbntypes.NewBIP340PubKeyFromHex(valPkStr) - if err != nil { - return nil, err - } - - validator, err := app.vs.GetStoreValidator(valPk.MustMarshal()) - if err != nil { - return nil, err - } - - if validator.Status != proto.ValidatorStatus_CREATED { - return nil, fmt.Errorf("validator is already registered") - } - - btcSig, err := bbntypes.NewBIP340Signature(validator.Pop.BtcSig) - if err != nil { - return nil, err - } - - pop := &bstypes.ProofOfPossession{ - BabylonSig: validator.Pop.BabylonSig, - BtcSig: btcSig.MustMarshal(), - BtcSigType: bstypes.BTCSigType_BIP340, - } - - commissionRate, err := sdkmath.LegacyNewDecFromStr(validator.Commission) - if err != nil { - return nil, err - } - - request := ®isterValidatorRequest{ - bbnPubKey: validator.GetBabylonPK(), - btcPubKey: validator.MustGetBIP340BTCPK(), - pop: pop, - description: validator.Description, - commission: &commissionRate, - errResponse: make(chan error, 1), - successResponse: make(chan *RegisterValidatorResponse, 1), - } - - app.registerValidatorRequestChan <- request - - select { - case err := <-request.errResponse: - return nil, err - case successResponse := <-request.successResponse: - return successResponse, nil - case <-app.quit: - return nil, fmt.Errorf("validator app is shutting down") - } -} - -// StartHandlingValidator starts a validator instance with the given Babylon public key -// Note: this should be called right after the validator is registered -func (app *ValidatorApp) StartHandlingValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { - return app.validatorManager.StartValidator(valPk, passphrase) -} - -// NOTE: this is not safe in production, so only used for testing purpose -func (app *ValidatorApp) getValPrivKey(valPk []byte) (*btcec.PrivateKey, error) { - record, err := app.eotsManager.KeyRecord(valPk, "") - if err != nil { - return nil, err - } - - return record.PrivKey, nil -} - -// Start starts only the validator daemon without any validator instances -func (app *ValidatorApp) Start() error { - var startErr error - app.startOnce.Do(func() { - app.logger.Info("Starting ValidatorApp") - - app.eventWg.Add(1) - go app.eventLoop() - - app.sentWg.Add(1) - go app.registrationLoop() - }) - - return startErr -} - -func (app *ValidatorApp) Stop() error { - var stopErr error - app.stopOnce.Do(func() { - app.logger.Info("Stopping ValidatorApp") - - // Always stop the submission loop first to not generate additional events and actions - app.logger.Debug("Stopping submission loop") - close(app.quit) - app.wg.Wait() - - app.logger.Debug("Stopping validators") - if err := app.validatorManager.Stop(); err != nil { - stopErr = err - 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.vs.Close(); err != nil { - stopErr = err - return - } - - app.logger.Debug("Stopping EOTS manager") - if err := app.eotsManager.Close(); err != nil { - stopErr = err - return - } - - app.logger.Debug("ValidatorApp successfully stopped") - - }) - return stopErr -} - -func (app *ValidatorApp) CreateValidator( - keyName, chainID, passPhrase, hdPath string, - description []byte, - commission *sdkmath.LegacyDec, -) (*CreateValidatorResult, error) { - - req := &createValidatorRequest{ - keyName: keyName, - chainID: chainID, - passPhrase: passPhrase, - hdPath: hdPath, - description: description, - commission: commission, - errResponse: make(chan error, 1), - successResponse: make(chan *createValidatorResponse, 1), - } - - app.createValidatorRequestChan <- req - - select { - case err := <-req.errResponse: - return nil, err - case successResponse := <-req.successResponse: - return &CreateValidatorResult{ - ValPk: successResponse.ValPk, - }, nil - case <-app.quit: - return nil, fmt.Errorf("validator app is shutting down") - } -} - -func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { - valPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) - if err != nil { - return nil, err - } - - valPk, err := bbntypes.NewBIP340PubKey(valPkBytes) - if err != nil { - return nil, err - } - - kr, err := valkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) - if err != nil { - return nil, err - } - - keyPair, err := kr.CreateChainKey(req.passPhrase, req.hdPath) - if err != nil { - return nil, fmt.Errorf("failed to create chain key for the validator: %w", err) - } - pk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} - - valRecord, err := app.eotsManager.KeyRecord(valPk.MustMarshal(), req.passPhrase) - if err != nil { - return nil, fmt.Errorf("failed to get validator record: %w", err) - } - - pop, err := kr.CreatePop(valRecord.PrivKey, req.passPhrase) - if err != nil { - return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) - } - - validator := valstore.NewStoreValidator(pk, valPk, req.keyName, req.chainID, pop, req.description, req.commission) - - if err := app.vs.SaveValidator(validator); err != nil { - return nil, fmt.Errorf("failed to save validator: %w", err) - } - - app.logger.Info("successfully created a validator", - zap.String("btc_pk", valPk.MarshalHex()), - zap.String("key_name", req.keyName), - ) - - return &createValidatorResponse{ - ValPk: valPk, - }, nil -} - -// main event loop for the validator app -func (app *ValidatorApp) eventLoop() { - defer app.eventWg.Done() - - for { - select { - case req := <-app.createValidatorRequestChan: - res, err := app.handleCreateValidatorRequest(req) - if err != nil { - req.errResponse <- err - continue - } - - req.successResponse <- &createValidatorResponse{ValPk: res.ValPk} - - case ev := <-app.validatorRegisteredEventChan: - valStored, err := app.vs.GetStoreValidator(ev.btcPubKey.MustMarshal()) - if err != nil { - // we always check if the validator is in the DB before sending the registration request - app.logger.Fatal( - "registered validator not found in DB", - zap.String("pk", ev.btcPubKey.MarshalHex()), - zap.Error(err), - ) - } - - // change the status of the validator to registered - err = app.vs.SetValidatorStatus(valStored, proto.ValidatorStatus_REGISTERED) - if err != nil { - app.logger.Fatal("failed to set validator status to REGISTERED", - zap.String("pk", ev.btcPubKey.MarshalHex()), - zap.Error(err), - ) - } - - // return to the caller - ev.successResponse <- &RegisterValidatorResponse{ - bbnPubKey: valStored.GetBabylonPK(), - btcPubKey: valStored.MustGetBIP340BTCPK(), - TxHash: ev.txHash, - } - - case <-app.eventQuit: - app.logger.Debug("exiting main event loop") - return - } - } -} - -func (app *ValidatorApp) registrationLoop() { - defer app.sentWg.Done() - for { - select { - case req := <-app.registerValidatorRequestChan: - // we won't do any retries here to not block the loop for more important messages. - // Most probably it fails due so some user error so we just return the error to the user. - // TODO: need to start passing context here to be able to cancel the request in case of app quiting - popBytes, err := req.pop.Marshal() - if err != nil { - req.errResponse <- err - continue - } - - res, err := app.cc.RegisterValidator( - req.bbnPubKey.Key, - req.btcPubKey.MustToBTCPK(), - popBytes, - req.commission, - req.description, - ) - - if err != nil { - app.logger.Error( - "failed to register validator", - zap.String("pk", req.btcPubKey.MarshalHex()), - zap.Error(err), - ) - req.errResponse <- err - continue - } - - app.logger.Info( - "successfully registered validator on babylon", - zap.String("btc_pk", req.btcPubKey.MarshalHex()), - zap.String("babylon_pk", hex.EncodeToString(req.bbnPubKey.Key)), - zap.String("txHash", res.TxHash), - ) - - app.validatorRegisteredEventChan <- &validatorRegisteredEvent{ - btcPubKey: req.btcPubKey, - bbnPubKey: req.bbnPubKey, - txHash: res.TxHash, - // 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: - app.logger.Debug("exiting registration loop") - return - } - } -} diff --git a/validator/service/client/rpcclient.go b/validator/service/client/rpcclient.go deleted file mode 100644 index e8793550..00000000 --- a/validator/service/client/rpcclient.go +++ /dev/null @@ -1,122 +0,0 @@ -package client - -import ( - "context" - "fmt" - - sdkmath "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/x/staking/types" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - "github.com/babylonchain/btc-validator/validator/proto" -) - -type ValidatorServiceGRpcClient struct { - client proto.BtcValidatorsClient -} - -func NewValidatorServiceGRpcClient(remoteAddr string) (*ValidatorServiceGRpcClient, func(), error) { - conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) - } - - cleanUp := func() { - conn.Close() - } - - return &ValidatorServiceGRpcClient{ - client: proto.NewBtcValidatorsClient(conn), - }, cleanUp, nil -} - -func (c *ValidatorServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInfoResponse, error) { - req := &proto.GetInfoRequest{} - res, err := c.client.GetInfo(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) RegisterValidator( - ctx context.Context, - valPk *bbntypes.BIP340PubKey, - passphrase string, -) (*proto.RegisterValidatorResponse, error) { - - req := &proto.RegisterValidatorRequest{BtcPk: valPk.MarshalHex(), Passphrase: passphrase} - res, err := c.client.RegisterValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) CreateValidator( - ctx context.Context, - keyName, chainID, passphrase, hdPath string, - description types.Description, - commission *sdkmath.LegacyDec, -) (*proto.CreateValidatorResponse, error) { - - descBytes, err := description.Marshal() - if err != nil { - return nil, err - } - - req := &proto.CreateValidatorRequest{ - KeyName: keyName, - ChainId: chainID, - Passphrase: passphrase, - HdPath: hdPath, - Description: descBytes, - Commission: commission.String(), - } - - res, err := c.client.CreateValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) AddFinalitySignature(ctx context.Context, valPk string, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { - req := &proto.AddFinalitySignatureRequest{ - BtcPk: valPk, - Height: height, - AppHash: lch, - } - - res, err := c.client.AddFinalitySignature(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) QueryValidatorList(ctx context.Context) (*proto.QueryValidatorListResponse, error) { - req := &proto.QueryValidatorListRequest{} - res, err := c.client.QueryValidatorList(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) QueryValidatorInfo(ctx context.Context, valPk *bbntypes.BIP340PubKey) (*proto.QueryValidatorResponse, error) { - req := &proto.QueryValidatorRequest{BtcPk: valPk.MarshalHex()} - res, err := c.client.QueryValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} diff --git a/validator/service/rpcserver.go b/validator/service/rpcserver.go deleted file mode 100644 index 9e0848d8..00000000 --- a/validator/service/rpcserver.go +++ /dev/null @@ -1,210 +0,0 @@ -package service - -import ( - "context" - "encoding/hex" - "fmt" - "sync" - "sync/atomic" - - "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - "google.golang.org/grpc" - - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/validator/proto" - "github.com/babylonchain/btc-validator/version" -) - -// rpcServer is the main RPC server for the BTC-Validator daemon that handles -// gRPC incoming requests. -type rpcServer struct { - started int32 - shutdown int32 - - proto.UnimplementedBtcValidatorsServer - - app *ValidatorApp - - quit chan struct{} - wg sync.WaitGroup -} - -// newRPCServer creates a new RPC sever from the set of input dependencies. -func newRPCServer( - v *ValidatorApp, -) *rpcServer { - - return &rpcServer{ - quit: make(chan struct{}), - app: v, - } -} - -// Start signals that the RPC server starts accepting requests. -func (r *rpcServer) Start() error { - if atomic.AddInt32(&r.started, 1) != 1 { - return nil - } - - return nil -} - -// Stop signals that the RPC server should attempt a graceful shutdown and -// cancel any outstanding requests. -func (r *rpcServer) Stop() error { - if atomic.AddInt32(&r.shutdown, 1) != 1 { - return nil - } - - close(r.quit) - - r.wg.Wait() - - return nil -} - -// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC -// server. -func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { - // Register the main RPC server. - proto.RegisterBtcValidatorsServer(grpcServer, r) - return nil -} - -// GetInfo returns general information relating to the active daemon -func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetInfoResponse, error) { - - return &proto.GetInfoResponse{ - Version: version.Version(), - }, nil -} - -// CreateValidator generates a validator object and saves it in the database -func (r *rpcServer) CreateValidator(ctx context.Context, req *proto.CreateValidatorRequest) ( - *proto.CreateValidatorResponse, error) { - - commissionRate, err := math.LegacyNewDecFromStr(req.Commission) - if err != nil { - return nil, err - } - - result, err := r.app.CreateValidator( - req.KeyName, - req.ChainId, - req.Passphrase, - req.HdPath, - req.Description, - &commissionRate, - ) - - if err != nil { - return nil, err - } - - return &proto.CreateValidatorResponse{ - BtcPk: result.ValPk.MarshalHex(), - }, nil - -} - -// RegisterValidator sends a transactions to Babylon to register a BTC validator -func (r *rpcServer) RegisterValidator(ctx context.Context, req *proto.RegisterValidatorRequest) ( - *proto.RegisterValidatorResponse, error) { - - txRes, err := r.app.RegisterValidator(req.BtcPk) - if err != nil { - return nil, fmt.Errorf("failed to register the validator to Babylon: %w", err) - } - - // the validator instance should be started right after registration - if err := r.app.StartHandlingValidator(txRes.btcPubKey, req.Passphrase); err != nil { - return nil, fmt.Errorf("failed to start the registered validator %s: %w", hex.EncodeToString(txRes.bbnPubKey.Key), err) - } - - return &proto.RegisterValidatorResponse{TxHash: txRes.TxHash}, nil -} - -// AddFinalitySignature adds a manually constructed finality signature to Babylon -// NOTE: this is only used for presentation/testing purposes -func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFinalitySignatureRequest) ( - *proto.AddFinalitySignatureResponse, error) { - - valPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) - if err != nil { - return nil, err - } - - v, err := r.app.GetValidatorInstance(valPk) - if err != nil { - return nil, err - } - - b := &types.BlockInfo{ - Height: req.Height, - Hash: req.AppHash, - } - - txRes, privKey, err := v.TestSubmitFinalitySignatureAndExtractPrivKey(b) - if err != nil { - return nil, err - } - - res := &proto.AddFinalitySignatureResponse{TxHash: txRes.TxHash} - - // if privKey is not empty, then this BTC validator - // has voted for a fork and will be slashed - if privKey != nil { - localPrivKey, err := r.app.getValPrivKey(valPk.MustMarshal()) - res.ExtractedSkHex = privKey.Key.String() - if err != nil { - return nil, err - } - localSkHex := localPrivKey.Key.String() - localSkNegateHex := localPrivKey.Key.Negate().String() - if res.ExtractedSkHex == localSkHex { - res.LocalSkHex = localSkHex - } else if res.ExtractedSkHex == localSkNegateHex { - res.LocalSkHex = localSkNegateHex - } else { - return nil, fmt.Errorf("the validator's BTC private key is extracted but does not match the local key,"+ - "extrated: %s, local: %s, local-negated: %s", - res.ExtractedSkHex, localSkHex, localSkNegateHex) - } - } - - return res, nil -} - -// QueryValidator queries the information of the validator -func (r *rpcServer) QueryValidator(ctx context.Context, req *proto.QueryValidatorRequest) ( - *proto.QueryValidatorResponse, error) { - - valPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) - if err != nil { - return nil, err - } - val, err := r.app.GetValidatorInstance(valPk) - if err != nil { - return nil, err - } - - valInfo := proto.NewValidatorInfo(val.GetStoreValidator()) - - return &proto.QueryValidatorResponse{Validator: valInfo}, nil -} - -// QueryValidatorList queries the information of a list of validators -func (r *rpcServer) QueryValidatorList(ctx context.Context, req *proto.QueryValidatorListRequest) ( - *proto.QueryValidatorListResponse, error) { - - vals := r.app.ListValidatorInstances() - - valsInfo := make([]*proto.ValidatorInfo, len(vals)) - for i, v := range vals { - valInfo := proto.NewValidatorInfo(v.GetStoreValidator()) - valsInfo[i] = valInfo - } - - return &proto.QueryValidatorListResponse{Validators: valsInfo}, nil -} diff --git a/validator/service/types.go b/validator/service/types.go deleted file mode 100644 index 3eaff467..00000000 --- a/validator/service/types.go +++ /dev/null @@ -1,201 +0,0 @@ -package service - -import ( - "sync" - - sdkmath "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "go.uber.org/zap" - - "github.com/babylonchain/btc-validator/validator/proto" - valstore "github.com/babylonchain/btc-validator/validator/store" -) - -type createValidatorResponse struct { - ValPk *bbntypes.BIP340PubKey -} -type createValidatorRequest struct { - keyName string - passPhrase string - hdPath string - chainID string - description []byte - commission *sdkmath.LegacyDec - errResponse chan error - successResponse chan *createValidatorResponse -} - -type registerValidatorRequest struct { - bbnPubKey *secp256k1.PubKey - btcPubKey *bbntypes.BIP340PubKey - // TODO we should have our own representation of PoP - pop *btcstakingtypes.ProofOfPossession - description []byte - commission *sdkmath.LegacyDec - errResponse chan error - successResponse chan *RegisterValidatorResponse -} - -type validatorRegisteredEvent struct { - bbnPubKey *secp256k1.PubKey - btcPubKey *bbntypes.BIP340PubKey - txHash string - successResponse chan *RegisterValidatorResponse -} - -type RegisterValidatorResponse struct { - bbnPubKey *secp256k1.PubKey - btcPubKey *bbntypes.BIP340PubKey - TxHash string -} - -type CreateValidatorResult struct { - ValPk *bbntypes.BIP340PubKey -} - -type valState struct { - mu sync.Mutex - v *proto.StoreValidator - s *valstore.ValidatorStore -} - -func (vs *valState) getStoreValidator() *proto.StoreValidator { - vs.mu.Lock() - defer vs.mu.Unlock() - return vs.v -} - -func (vs *valState) setStatus(s proto.ValidatorStatus) error { - vs.mu.Lock() - vs.v.Status = s - vs.mu.Unlock() - return vs.s.UpdateValidator(vs.v) -} - -func (vs *valState) setLastProcessedHeight(height uint64) error { - vs.mu.Lock() - vs.v.LastProcessedHeight = height - vs.mu.Unlock() - return vs.s.UpdateValidator(vs.v) -} - -func (vs *valState) setLastCommittedHeight(height uint64) error { - vs.mu.Lock() - vs.v.LastCommittedHeight = height - vs.mu.Unlock() - return vs.s.UpdateValidator(vs.v) -} - -func (vs *valState) setLastProcessedAndVotedHeight(height uint64) error { - vs.mu.Lock() - vs.v.LastVotedHeight = height - vs.v.LastProcessedHeight = height - vs.mu.Unlock() - return vs.s.UpdateValidator(vs.v) -} - -func (v *ValidatorInstance) GetStoreValidator() *proto.StoreValidator { - return v.state.getStoreValidator() -} - -func (v *ValidatorInstance) GetBabylonPk() *secp256k1.PubKey { - return v.state.getStoreValidator().GetBabylonPK() -} - -func (v *ValidatorInstance) GetBabylonPkHex() string { - return v.state.getStoreValidator().GetBabylonPkHexString() -} - -func (v *ValidatorInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { - return v.state.getStoreValidator().MustGetBIP340BTCPK() -} - -func (v *ValidatorInstance) MustGetBtcPk() *btcec.PublicKey { - return v.state.getStoreValidator().MustGetBTCPK() -} - -func (v *ValidatorInstance) GetBtcPkHex() string { - return v.GetBtcPkBIP340().MarshalHex() -} - -func (v *ValidatorInstance) GetStatus() proto.ValidatorStatus { - return v.state.getStoreValidator().Status -} - -func (v *ValidatorInstance) GetLastVotedHeight() uint64 { - return v.state.getStoreValidator().LastVotedHeight -} - -func (v *ValidatorInstance) GetLastProcessedHeight() uint64 { - return v.state.getStoreValidator().LastProcessedHeight -} - -func (v *ValidatorInstance) GetLastCommittedHeight() uint64 { - return v.state.getStoreValidator().LastCommittedHeight -} - -func (v *ValidatorInstance) GetChainID() []byte { - return []byte(v.state.getStoreValidator().ChainId) -} - -func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { - return v.state.setStatus(s) -} - -func (v *ValidatorInstance) MustSetStatus(s proto.ValidatorStatus) { - if err := v.SetStatus(s); err != nil { - v.logger.Fatal("failed to set validator status", - zap.String("pk", v.GetBtcPkHex()), zap.String("status", s.String())) - } -} - -func (v *ValidatorInstance) SetLastProcessedHeight(height uint64) error { - return v.state.setLastProcessedHeight(height) -} - -func (v *ValidatorInstance) MustSetLastProcessedHeight(height uint64) { - if err := v.SetLastProcessedHeight(height); err != nil { - v.logger.Fatal("failed to set last processed height", - zap.String("pk", v.GetBtcPkHex()), zap.Uint64("last_processed_height", height)) - } -} - -func (v *ValidatorInstance) SetLastCommittedHeight(height uint64) error { - return v.state.setLastCommittedHeight(height) -} - -func (v *ValidatorInstance) MustSetLastCommittedHeight(height uint64) { - if err := v.SetLastCommittedHeight(height); err != nil { - v.logger.Fatal("failed to set last committed height", - zap.String("pk", v.GetBtcPkHex()), zap.Uint64("last_committed_height", height)) - } -} - -func (v *ValidatorInstance) updateStateAfterFinalitySigSubmission(height uint64) error { - return v.state.setLastProcessedAndVotedHeight(height) -} - -func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { - if err := v.updateStateAfterFinalitySigSubmission(height); err != nil { - v.logger.Fatal("failed to update state after finality signature submitted", - zap.String("pk", v.GetBtcPkHex()), zap.Uint64("height", height)) - } -} - -func (v *ValidatorInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { - // TODO ignore pass phrase for now - record, err := v.em.KeyRecord(v.btcPk.MustMarshal(), v.passphrase) - if err != nil { - return nil, err - } - - return record.PrivKey, nil -} - -// only used for testing purposes -func (v *ValidatorInstance) BtcPrivKey() (*btcec.PrivateKey, error) { - return v.getEOTSPrivKey() -} diff --git a/validator/service/validator_manager.go b/validator/service/validator_manager.go deleted file mode 100644 index 34ed331f..00000000 --- a/validator/service/validator_manager.go +++ /dev/null @@ -1,344 +0,0 @@ -package service - -import ( - "errors" - "fmt" - "sync" - "time" - - "github.com/avast/retry-go/v4" - bbntypes "github.com/babylonchain/babylon/types" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "go.uber.org/atomic" - "go.uber.org/zap" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/eotsmanager" - "github.com/babylonchain/btc-validator/types" - valcfg "github.com/babylonchain/btc-validator/validator/config" - "github.com/babylonchain/btc-validator/validator/proto" - valstore "github.com/babylonchain/btc-validator/validator/store" -) - -const instanceTerminatingMsg = "terminating the validator instance due to critical error" - -type CriticalError struct { - err error - valBtcPk *bbntypes.BIP340PubKey -} - -func (ce *CriticalError) Error() string { - return fmt.Sprintf("critical err on validator %s: %s", ce.valBtcPk.MarshalHex(), ce.err.Error()) -} - -type ValidatorManager struct { - isStarted *atomic.Bool - - mu sync.Mutex - wg sync.WaitGroup - - // running validator instances map keyed by the hex string of the BTC public key - vals map[string]*ValidatorInstance - - // needed for initiating validator instances - vs *valstore.ValidatorStore - config *valcfg.Config - cc clientcontroller.ClientController - em eotsmanager.EOTSManager - logger *zap.Logger - - criticalErrChan chan *CriticalError - - quit chan struct{} -} - -func NewValidatorManager(vs *valstore.ValidatorStore, - config *valcfg.Config, - cc clientcontroller.ClientController, - em eotsmanager.EOTSManager, - logger *zap.Logger, -) (*ValidatorManager, error) { - return &ValidatorManager{ - vals: make(map[string]*ValidatorInstance), - criticalErrChan: make(chan *CriticalError), - isStarted: atomic.NewBool(false), - vs: vs, - config: config, - cc: cc, - em: em, - logger: logger, - quit: make(chan struct{}), - }, nil -} - -// monitorCriticalErr takes actions when it receives critical errors from a validator instance -// if the validator is slashed, it will be terminated and the program keeps running in case -// new validators join -// otherwise, the program will panic -func (vm *ValidatorManager) monitorCriticalErr() { - defer vm.wg.Done() - - var criticalErr *CriticalError - for { - select { - case criticalErr = <-vm.criticalErrChan: - vi, err := vm.GetValidatorInstance(criticalErr.valBtcPk) - if err != nil { - panic(fmt.Errorf("failed to get the validator instance: %w", err)) - } - if errors.Is(criticalErr.err, btcstakingtypes.ErrBTCValAlreadySlashed) { - vm.setValidatorSlashed(vi) - vm.logger.Debug("the validator has been slashed", - zap.String("pk", criticalErr.valBtcPk.MarshalHex())) - continue - } - vi.logger.Fatal(instanceTerminatingMsg, - zap.String("pk", criticalErr.valBtcPk.MarshalHex()), zap.Error(criticalErr.err)) - case <-vm.quit: - return - } - } -} - -// monitorStatusUpdate periodically check the status of each managed validators and update -// it accordingly. We update the status by querying the latest voting power and the slashed_height. -// In particular, we perform the following status transitions (REGISTERED, ACTIVE, INACTIVE, SLASHED): -// 1. if power == 0 and slashed_height == 0, if status == ACTIVE, change to INACTIVE, otherwise remain the same -// 2. if power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the validator instance -// 3. if power > 0 (slashed_height must > 0), set status to ACTIVE -// NOTE: once error occurs, we log and continue as the status update is not critical to the entire program -func (vm *ValidatorManager) monitorStatusUpdate() { - defer vm.wg.Done() - - if vm.config.StatusUpdateInterval == 0 { - vm.logger.Info("the status update is disabled") - return - } - - statusUpdateTicker := time.NewTicker(vm.config.StatusUpdateInterval) - defer statusUpdateTicker.Stop() - - for { - select { - case <-statusUpdateTicker.C: - latestBlock, err := vm.getLatestBlockWithRetry() - if err != nil { - vm.logger.Debug("failed to get the latest block", zap.Error(err)) - continue - } - vals := vm.ListValidatorInstances() - for _, v := range vals { - oldStatus := v.GetStatus() - power, err := v.GetVotingPowerWithRetry(latestBlock.Height) - if err != nil { - vm.logger.Debug( - "failed to get the voting power", - zap.String("val_btc_pk", v.GetBtcPkHex()), - zap.Uint64("height", latestBlock.Height), - zap.Error(err), - ) - continue - } - // power > 0 (slashed_height must > 0), set status to ACTIVE - if power > 0 { - if oldStatus != proto.ValidatorStatus_ACTIVE { - v.MustSetStatus(proto.ValidatorStatus_ACTIVE) - vm.logger.Debug( - "the validator status is changed to ACTIVE", - zap.String("val_btc_pk", v.GetBtcPkHex()), - zap.String("old_status", oldStatus.String()), - zap.Uint64("power", power), - ) - } - continue - } - slashed, err := v.GetValidatorSlashedWithRetry() - if err != nil { - vm.logger.Debug( - "failed to get the slashed height", - zap.String("val_btc_pk", v.GetBtcPkHex()), - zap.Error(err), - ) - continue - } - // power == 0 and slashed == true, set status to SLASHED and stop and remove the validator instance - if slashed { - vm.setValidatorSlashed(v) - vm.logger.Debug( - "the validator is slashed", - zap.String("val_btc_pk", v.GetBtcPkHex()), - zap.String("old_status", oldStatus.String()), - ) - continue - } - // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE - if oldStatus == proto.ValidatorStatus_ACTIVE { - v.MustSetStatus(proto.ValidatorStatus_INACTIVE) - vm.logger.Debug( - "the validator status is changed to INACTIVE", - zap.String("val_btc_pk", v.GetBtcPkHex()), - zap.String("old_status", oldStatus.String()), - ) - } - } - case <-vm.quit: - return - } - } -} - -func (vm *ValidatorManager) setValidatorSlashed(vi *ValidatorInstance) { - vi.MustSetStatus(proto.ValidatorStatus_SLASHED) - if err := vm.removeValidatorInstance(vi.GetBtcPkBIP340()); err != nil { - panic(fmt.Errorf("failed to terminate a slashed validator %s: %w", vi.GetBtcPkHex(), err)) - } -} - -func (vm *ValidatorManager) StartValidator(valPk *bbntypes.BIP340PubKey, passphrase string) error { - if !vm.isStarted.Load() { - vm.isStarted.Store(true) - - vm.wg.Add(1) - go vm.monitorCriticalErr() - - vm.wg.Add(1) - go vm.monitorStatusUpdate() - } - - if vm.numOfRunningValidators() >= int(vm.config.MaxNumValidators) { - return fmt.Errorf("reaching maximum number of running validators %v", vm.config.MaxNumValidators) - } - - if err := vm.addValidatorInstance(valPk, passphrase); err != nil { - return err - } - - return nil -} - -func (vm *ValidatorManager) Stop() error { - if !vm.isStarted.Swap(false) { - return fmt.Errorf("the validator manager has already stopped") - } - - var stopErr error - - for _, v := range vm.vals { - if !v.IsRunning() { - continue - } - if err := v.Stop(); err != nil { - stopErr = err - break - } - } - - close(vm.quit) - vm.wg.Wait() - - return stopErr -} - -func (vm *ValidatorManager) ListValidatorInstances() []*ValidatorInstance { - vm.mu.Lock() - defer vm.mu.Unlock() - - valsList := make([]*ValidatorInstance, 0, len(vm.vals)) - for _, v := range vm.vals { - valsList = append(valsList, v) - } - - return valsList -} - -func (vm *ValidatorManager) GetValidatorInstance(valPk *bbntypes.BIP340PubKey) (*ValidatorInstance, error) { - vm.mu.Lock() - defer vm.mu.Unlock() - - keyHex := valPk.MarshalHex() - v, exists := vm.vals[keyHex] - if !exists { - return nil, fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) - } - - return v, nil -} - -func (vm *ValidatorManager) removeValidatorInstance(valPk *bbntypes.BIP340PubKey) error { - vm.mu.Lock() - defer vm.mu.Unlock() - - keyHex := valPk.MarshalHex() - v, exists := vm.vals[keyHex] - if !exists { - return fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) - } - if v.IsRunning() { - if err := v.Stop(); err != nil { - return fmt.Errorf("failed to stop the validator instance %s", keyHex) - } - } - - delete(vm.vals, keyHex) - return nil -} - -func (vm *ValidatorManager) numOfRunningValidators() int { - vm.mu.Lock() - defer vm.mu.Unlock() - - return len(vm.vals) -} - -// addValidatorInstance creates a validator instance, starts it and adds it into the validator manager -func (vm *ValidatorManager) addValidatorInstance( - pk *bbntypes.BIP340PubKey, - passphrase string, -) error { - vm.mu.Lock() - defer vm.mu.Unlock() - - pkHex := pk.MarshalHex() - if _, exists := vm.vals[pkHex]; exists { - return fmt.Errorf("validator instance already exists") - } - - valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.cc, vm.em, passphrase, vm.criticalErrChan, vm.logger) - if err != nil { - return fmt.Errorf("failed to create validator %s instance: %w", pkHex, err) - } - - if err := valIns.Start(); err != nil { - return fmt.Errorf("failed to start validator %s instance: %w", pkHex, err) - } - - vm.vals[pkHex] = valIns - - return nil -} - -func (vm *ValidatorManager) getLatestBlockWithRetry() (*types.BlockInfo, error) { - var ( - latestBlock *types.BlockInfo - err error - ) - - if err := retry.Do(func() error { - latestBlock, err = vm.cc.QueryBestBlock() - if err != nil { - return err - } - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - vm.logger.Debug( - "failed to query the consumer chain for the latest block", - zap.Uint("attempt", n+1), - zap.Uint("max_attempts", RtyAttNum), - zap.Error(err), - ) - })); err != nil { - return nil, err - } - - return latestBlock, nil -} diff --git a/validator/store/valstore.go b/validator/store/valstore.go deleted file mode 100644 index ae1ece03..00000000 --- a/validator/store/valstore.go +++ /dev/null @@ -1,210 +0,0 @@ -package store - -import ( - "fmt" - "math" - - sdkmath "cosmossdk.io/math" - "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - gproto "google.golang.org/protobuf/proto" - - "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/validator/proto" -) - -const ( - validatorPrefix = "validator" -) - -func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des []byte, com *sdkmath.LegacyDec) *proto.StoreValidator { - return &proto.StoreValidator{ - KeyName: keyName, - BabylonPk: babylonPk.Bytes(), - BtcPk: btcPk.MustMarshal(), - Pop: &proto.ProofOfPossession{ - BabylonSig: pop.BabylonSig, - BtcSig: pop.BtcSig, - }, - ChainId: chainID, - Status: proto.ValidatorStatus_CREATED, - Description: des, - Commission: com.String(), - } -} - -type ValidatorStore struct { - s store.Store -} - -func NewValidatorStore(dbPath string, dbName string, dbBackend string) (*ValidatorStore, error) { - s, err := openStore(dbPath, dbName, dbBackend) - if err != nil { - return nil, err - } - - return &ValidatorStore{s: s}, nil -} - -func getValidatorKey(pk []byte) []byte { - return append([]byte(validatorPrefix), pk...) -} - -func (vs *ValidatorStore) getValidatorListKey() []byte { - return []byte(validatorPrefix) -} - -func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { - k := getValidatorKey(val.BtcPk) - v, err := gproto.Marshal(val) - if err != nil { - return fmt.Errorf("failed to marshal the created validator object: %w", err) - } - - if err := vs.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the created validator object: %w", err) - } - - return nil -} - -func (vs *ValidatorStore) UpdateValidator(val *proto.StoreValidator) error { - k := getValidatorKey(val.BtcPk) - exists, err := vs.s.Exists(k) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("the validator does not exist") - } - - v, err := gproto.Marshal(val) - if err != nil { - return err - } - - if err := vs.s.Put(k, v); err != nil { - return err - } - - return nil -} - -func (vs *ValidatorStore) SetValidatorStatus(val *proto.StoreValidator, status proto.ValidatorStatus) error { - val.Status = status - return vs.UpdateValidator(val) -} - -func (vs *ValidatorStore) GetStoreValidator(pk []byte) (*proto.StoreValidator, error) { - k := getValidatorKey(pk) - valsBytes, err := vs.s.Get(k) - if err != nil { - return nil, err - } - - val := new(proto.StoreValidator) - err = gproto.Unmarshal(valsBytes, val) - if err != nil { - panic(fmt.Errorf("unable to unmarshal validator object: %w", err)) - } - - return val, nil -} - -func (vs *ValidatorStore) ListValidators() ([]*proto.StoreValidator, error) { - k := vs.getValidatorListKey() - valsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - valsList := make([]*proto.StoreValidator, len(valsBytes)) - for i := 0; i < len(valsBytes); i++ { - val := new(proto.StoreValidator) - err := gproto.Unmarshal(valsBytes[i].Value, val) - if err != nil { - panic(fmt.Errorf("failed to unmarshal validator from the database: %w", err)) - } - valsList[i] = val - } - - return valsList, nil -} - -// ListRegisteredValidators returns a list of validators whose status is more than CREATED -// but less than SLASHED -func (vs *ValidatorStore) ListRegisteredValidators() ([]*proto.StoreValidator, error) { - k := vs.getValidatorListKey() - valsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - valsList := make([]*proto.StoreValidator, 0) - for i := 0; i < len(valsBytes); i++ { - val := new(proto.StoreValidator) - err := gproto.Unmarshal(valsBytes[i].Value, val) - if err != nil { - panic(fmt.Errorf("failed to unmarshal validator from the database: %w", err)) - } - if val.Status > proto.ValidatorStatus_CREATED && val.Status < proto.ValidatorStatus_SLASHED { - valsList = append(valsList, val) - } - } - - return valsList, nil -} - -func (vs *ValidatorStore) GetEarliestActiveValidatorVotedHeight() (uint64, error) { - registeredValidators, err := vs.ListRegisteredValidators() - if err != nil { - return 0, err - } - - if len(registeredValidators) == 0 { - return 0, nil - } - - earliestHeight := uint64(math.MaxUint64) - activeValsCnt := 0 - for _, val := range registeredValidators { - // Note there might be a delay between the validator being active on Babylon - // and this program capturing that. However, given that we only care - // about the `LastVotedHeight` of the validator, other parts of the program - // ensure that when this value is set, the validator is stored as ACTIVE. - // TODO: Another option would be to query here for the - // active status of each validator although this might prove inefficient. - if val.Status != proto.ValidatorStatus_ACTIVE { - continue - } - activeValsCnt += 1 - if earliestHeight > val.LastVotedHeight { - earliestHeight = val.LastVotedHeight - } - } - // If there are no active validators, return 0 - if activeValsCnt == 0 { - return 0, nil - } - return earliestHeight, nil -} - -func (vs *ValidatorStore) Close() error { - if err := vs.s.Close(); err != nil { - return err - } - - return 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") - } -} diff --git a/validator/store/valstore_test.go b/validator/store/valstore_test.go deleted file mode 100644 index 6cde8a53..00000000 --- a/validator/store/valstore_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package store_test - -import ( - "math/rand" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/testutil" - valstore "github.com/babylonchain/btc-validator/validator/store" -) - -// FuzzValidators tests save and list validators properly -func FuzzValidatorStore(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - 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 := valstore.NewValidatorStore(dbPath, dbcfg.Name, dbcfg.Backend) - require.NoError(t, err) - - defer func() { - err := os.RemoveAll(dbPath) - require.NoError(t, err) - }() - - validator := testutil.GenRandomValidator(r, t) - err = vs.SaveValidator(validator) - require.NoError(t, err) - - valList, err := vs.ListValidators() - require.NoError(t, err) - require.Equal(t, validator.BtcPk, valList[0].BtcPk) - - actualVal, err := vs.GetStoreValidator(validator.BtcPk) - require.NoError(t, err) - require.Equal(t, validator.BabylonPk, actualVal.BabylonPk) - require.Equal(t, validator.BtcPk, actualVal.BtcPk) - require.Equal(t, validator.KeyName, actualVal.KeyName) - }) -} diff --git a/version/version.go b/version/version.go index ca3888d5..17f641b9 100644 --- a/version/version.go +++ b/version/version.go @@ -52,17 +52,17 @@ const ( // defaultAgentName is the default name of the software that is added as // the first part of the user agent string. - defaultAgentName = "vald" + defaultAgentName = "fpd" ) // agentName stores the name of the software that is added as the first part of -// the user agent string. This defaults to the value "vald" when being run as -// a standalone component but can be overwritten by LiT for example when vald +// the user agent string. This defaults to the value "fpd" when being run as +// a standalone component but can be overwritten by LiT for example when fpd // is integrated into the UI. var agentName = defaultAgentName // SetAgentName overwrites the default agent name which can be used to identify -// the software vald is bundled in (for example LiT). This function panics if +// the software fpd is bundled in (for example LiT). This function panics if // the agent name contains characters outside of the allowed semantic alphabet. func SetAgentName(newAgentName string) { for _, r := range newAgentName { From deedf91c233956a9378f44ac9538902086ea7190 Mon Sep 17 00:00:00 2001 From: Lei Yang Date: Fri, 15 Dec 2023 07:16:57 -0500 Subject: [PATCH 36/66] chore: fix minor issues in the documentation --- README.md | 39 +++++++++++++++++++++++++++++---------- docs/eots.md | 4 ++-- docs/finality-provider.md | 4 ++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9b476acd..dac7c0d5 100644 --- a/README.md +++ b/README.md @@ -59,30 +59,35 @@ $ git checkout #### Building and installing the binary -```bash -# cd into the project directory -$ cd finality-provider +At the top-level directory of the project -# installs the compiled binaries to your -# $GOPATH/bin directory allowing access -# from anywhere on your system +```bash $ make install ``` -The above will produce the following binaries: +The above command will build and install the following binaries to +`$GOPATH/bin`: - `eotsd`: The daemon program for the EOTS manager. - `fpd`: The daemon program for the finality-provider. - `fpcli`: The CLI tool for interacting with the finality-provider daemon. -To build locally, +If your shell cannot find the installed binaries, make sure `$GOPATH/bin` is in +the `$PATH` of your shell. Usually these commands will do the job + +```bash +export PATH=$HOME/go/bin:$PATH +echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.profile +``` + +To build without installing, ```bash -$ cd finality-provider # cd into the project directory $ make build ``` -The above will lead to a build directory having the following structure: +The above command will put the built binaries in a build directory with the +following structure: ```bash $ ls build ├── eotsd @@ -90,6 +95,20 @@ $ ls build └── fpd ``` +If Go complains that it cannot retrieve some of the dependencies, one reason +could be that these repositories are private. Try following the instructions +[here](https://go.dev/doc/faq#git_https). + +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 diff --git a/docs/eots.md b/docs/eots.md index 880206c3..41110e61 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -87,7 +87,7 @@ To see the complete list of configuration options, check the `eotsd.conf` file. You can start the EOTS daemon using the following command: ```bash -$ eotsd --home /path/to/eotsd/home +$ eotsd start --home /path/to/eotsd/home ``` This will start the rpc server at the address specified in the configuration under @@ -95,7 +95,7 @@ the `RpcListener` field. It can also be overridden with custom address using the `--rpclistener` flag. ```bash -$ eotsd --rpclistener 'localhost:8081' +$ eotsd start --rpclistener 'localhost:8081' time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager Daemon is fully active!" diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 8a12a13b..6dad9f83 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -93,7 +93,7 @@ To see the complete list of configuration options, check the `fpd.conf` file. You can start the finality provider daemon using the following command: ```bash -$ fpd --home /path/to/fpd/home +$ fpd start --home /path/to/fpd/home ``` This will start the RPC server at the address specified in the configuration under @@ -101,7 +101,7 @@ the `RawRPCListeners` field. A custom address can also be specified using the `--rpclisten` flag. ```bash -$ fpd --rpclisten 'localhost:8082' +$ fpd start --rpclisten 'localhost:8082' time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" time="2023-11-26T16:37:00-05:00" level=info msg="Starting Finality Provider App" From bc95a74a0e125488a71e57071d942e0227ac9bd9 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 18 Dec 2023 21:18:55 +0800 Subject: [PATCH 37/66] feat: Add key management (#181) --- covenant/covenant.go | 7 +- docs/finality-provider.md | 31 +++-- finality-provider/cmd/fpcli/daemoncmd.go | 27 ++-- finality-provider/cmd/fpd/flags.go | 18 ++- finality-provider/cmd/fpd/init.go | 8 +- finality-provider/cmd/fpd/keys.go | 124 +++++++++++++++++++ finality-provider/cmd/fpd/main.go | 1 + finality-provider/config/config.go | 2 +- finality-provider/service/app.go | 47 +++++-- finality-provider/service/fp_manager_test.go | 12 +- itest/test_manager.go | 6 +- keyring/keyringcontroller.go | 12 +- keyring/keyringcontroller_test.go | 7 +- testutil/datagen.go | 11 +- types/chainkey.go | 24 ++++ types/key.go | 8 -- 16 files changed, 282 insertions(+), 63 deletions(-) create mode 100644 finality-provider/cmd/fpd/keys.go create mode 100644 types/chainkey.go delete mode 100644 types/key.go diff --git a/covenant/covenant.go b/covenant/covenant.go index cfee5f6c..de0d8e2a 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -2,12 +2,13 @@ package covenant import ( "fmt" - "github.com/avast/retry-go/v4" - "github.com/btcsuite/btcd/btcec/v2" "strings" "sync" "time" + "github.com/avast/retry-go/v4" + "github.com/btcsuite/btcd/btcec/v2" + "go.uber.org/zap" "github.com/babylonchain/finality-provider/keyring" @@ -345,7 +346,7 @@ func (ce *CovenantEmulator) covenantSigSubmissionLoop() { } -func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.KeyPair, error) { +func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.ChainKeyInfo, error) { sdkCtx, err := keyring.CreateClientCtx( keyringDir, chainID, ) diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 6dad9f83..8b982d2d 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -47,17 +47,17 @@ $ ls /path/to/fpd/home/ If the `--home` flag is not specified, then the default home directory will be used. For different operating systems, those are: -- **MacOS** `~/Library/Application Support/Fpd` +- **MacOS** `~/Users//Library/Application Support/Fpd` - **Linux** `~/.Fpd` - **Windows** `C:\Users\\AppData\Local\Fpd` Below are some important parameters of the `fpd.conf` file. **Note**: -The finality provider daemon requires the existence of a keyring that contains -an account with Babylon token funds to pay for transactions. -The configuration below requires to point to the path where this keyring is stored -and specify the account name under the `KeyDirectory` and `Key` config values respectively. +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. ```bash # Address of the EOTS Daemon @@ -88,7 +88,23 @@ KeyDirectory = /path/to/fpd/home To see the complete list of configuration options, check the `fpd.conf` file. -## 3. Starting the Finality Provider Daemon +## 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 bond +with the EOTS key of the finality provider you want to create in [step 5](#5-create-and-register-a-finality-provider). + +Use the following command to add the key: + +```bash +$ fpd keys add --key-name my-finality-provider --chain-id chain-test +``` + +After executing the above command, the key name will be saved in the config file +created in [step](#2-configuration). + +## 4. Starting the Finality Provider Daemon You can start the finality provider daemon using the following command: @@ -114,7 +130,7 @@ time="2023-11-26T16:37:00-05:00" level=info msg="Finality Provider Daemon is ful All the available CLI options can be viewed using the `--help` flag. These options can also be set in the configuration file. -## 4. Create and Register a Finality Provider +## 5. Create and Register a Finality Provider A finality provider named `my-finality-provider` can be created in the internal storage ([bolt db](https://github.com/etcd-io/bbolt)) @@ -122,6 +138,7 @@ through the `fpcli create-finality-provider` command. This finality provider is associated with a BTC public key which serves as its unique identifier and a Babylon account to which staking rewards will be directed. +The key name must be the same as the key added in [step](#3-add-key-for-the-consumer-chain). ```bash $ fpcli create-finality-provider --key-name my-finality-provider \ diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index c3a9fdff..6bbeed72 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -17,7 +17,7 @@ import ( const ( fpdDaemonAddressFlag = "daemon-address" - keyNameFlag = "key-name" + homeFlag = "home" fpBTCPkFlag = "btc-pk" blockHeightFlag = "height" appHashFlag = "app-hash" @@ -86,9 +86,9 @@ var createFpDaemonCmd = cli.Command{ Value: defaultFpdDaemonAddress, }, cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the finality provider key", - Required: true, + Name: homeFlag, + Usage: "The home path of the finality provider daemon (fpd)", + Value: fpcfg.DefaultFpdDir, }, cli.StringFlag{ Name: chainIdFlag, @@ -144,12 +144,23 @@ func createFpDaemon(ctx *cli.Context) error { commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) if err != nil { - return err + return fmt.Errorf("invalid commission rate: %w", err) } description, err := getDescriptionFromContext(ctx) if err != nil { - return err + 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)) + 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") } client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) @@ -160,7 +171,7 @@ func createFpDaemon(ctx *cli.Context) error { info, err := client.CreateFinalityProvider( context.Background(), - ctx.String(keyNameFlag), + keyName, ctx.String(chainIdFlag), ctx.String(passphraseFlag), ctx.String(hdPathFlag), @@ -268,7 +279,7 @@ var registerFpDaemonCmd = cli.Command{ Name: "register-finality-provider", ShortName: "rfp", Usage: "Register a created finality provider to Babylon.", - UsageText: fmt.Sprintf("register-finality-provider --%s [key-name]", keyNameFlag), + UsageText: fmt.Sprintf("register-finality-provider --%s [btc-pk]", fpBTCPkFlag), Flags: []cli.Flag{ cli.StringFlag{ Name: fpdDaemonAddressFlag, diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/flags.go index 687cfa4e..fe764289 100644 --- a/finality-provider/cmd/fpd/flags.go +++ b/finality-provider/cmd/fpd/flags.go @@ -1,10 +1,18 @@ package main +import "github.com/cosmos/cosmos-sdk/crypto/keyring" + const ( - homeFlag = "home" - forceFlag = "force" - passphraseFlag = "passphrase" - fpPkFlag = "finality-provider-pk" + homeFlag = "home" + forceFlag = "force" + passphraseFlag = "passphrase" + fpPkFlag = "finality-provider-pk" + keyNameFlag = "key-name" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + keyringBackendFlag = "keyring-backend" - defaultPassphrase = "" + defaultKeyringBackend = keyring.BackendTest + defaultHdPath = "" + defaultPassphrase = "" ) diff --git a/finality-provider/cmd/fpd/init.go b/finality-provider/cmd/fpd/init.go index 99d3cc0b..b9cc999f 100644 --- a/finality-provider/cmd/fpd/init.go +++ b/finality-provider/cmd/fpd/init.go @@ -2,11 +2,13 @@ package main import ( "fmt" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" - "github.com/babylonchain/finality-provider/util" + "path/filepath" + "github.com/jessevdk/go-flags" "github.com/urfave/cli" - "path/filepath" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/util" ) var initCommand = cli.Command{ diff --git a/finality-provider/cmd/fpd/keys.go b/finality-provider/cmd/fpd/keys.go new file mode 100644 index 00000000..7cf82a1e --- /dev/null +++ b/finality-provider/cmd/fpd/keys.go @@ -0,0 +1,124 @@ +package main + +import ( + "encoding/json" + "fmt" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" +) + +type KeyOutput struct { + Name string `json:"name" yaml:"name"` + Address string `json:"address" yaml:"address"` + Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"` +} + +var keysCommands = []cli.Command{ + { + Name: "keys", + Usage: "Command sets of managing keys for interacting the consumer chain.", + Category: "Daemon commands", + Subcommands: []cli.Command{ + addKeyCmd, + }, + }, +} + +var addKeyCmd = cli.Command{ + Name: "add", + Usage: "Add a key to the consumer chain's keyring. This will change the config file in place", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to the keyring directory", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: keyNameFlag, + Required: true, + }, + cli.StringFlag{ + Name: chainIdFlag, + Usage: "The identifier of the consumer chain", + Required: true, + }, + cli.StringFlag{ + Name: keyringBackendFlag, + Usage: "Select keyring's backend", + Value: defaultKeyringBackend, + }, + 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: addKey, +} + +func addKey(ctx *cli.Context) error { + homePath := ctx.String(homeFlag) + chainID := ctx.String(chainIdFlag) + keyName := ctx.String(keyNameFlag) + backend := ctx.String(keyringBackendFlag) + passphrase := ctx.String(passphraseFlag) + 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) + } + + keyInfo, err := service.CreateChainKey( + homePath, + chainID, + keyName, + backend, + passphrase, + hdPath, + ) + if err != nil { + return fmt.Errorf("failed to create the chain key: %w", err) + } + + addr, err := keyInfo.GetValAddress() + if err != nil { + return err + } + printRespJSON( + KeyOutput{ + Name: keyName, + Address: addr.String(), + Mnemonic: keyInfo.Mnemonic, + }, + ) + + // write the updated config into the config file + cfg.BabylonConfig.Key = keyName + cfg.BabylonConfig.KeyringBackend = keyBackend + fileParser := flags.NewParser(cfg, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(fpcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} + +func printRespJSON(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("New key for the consumer chain is created "+ + "(mnemonic should be kept in a safe place for recovery):\n%s\n", jsonBytes) +} diff --git a/finality-provider/cmd/fpd/main.go b/finality-provider/cmd/fpd/main.go index 569b0521..1594b07c 100644 --- a/finality-provider/cmd/fpd/main.go +++ b/finality-provider/cmd/fpd/main.go @@ -17,6 +17,7 @@ func main() { app.Name = "fpd" app.Usage = "Finality Provider Daemon (fpd)." app.Commands = append(app.Commands, startCommand, initCommand) + app.Commands = append(app.Commands, keysCommands...) if err := app.Run(os.Args); err != nil { fatal(err) diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index b666703e..dc8fd540 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -46,7 +46,7 @@ const ( var ( // C:\Users\\AppData\Local\ on Windows // ~/.fpd on Linux - // ~/Library/Application Support/Fpd on MacOS + // ~/Users//Library/Application Support/Fpd on MacOS DefaultFpdDir = btcutil.AppDataDir("fpd", false) defaultBTCNetParams = chaincfg.SimNetParams diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 42f7eb48..89ec0ae9 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -3,10 +3,12 @@ package service import ( "encoding/hex" "fmt" - "github.com/babylonchain/finality-provider/util" "strings" "sync" + "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/util" + sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" @@ -316,38 +318,38 @@ func (app *FinalityProviderApp) CreateFinalityProvider( } func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createFinalityProviderRequest) (*createFinalityProviderResponse, error) { - fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) + // 1. check if the chain key exists + kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) if err != nil { return nil, err } - - fpPk, err := bbntypes.NewBIP340PubKey(fpPkBytes) + chainSk, err := kr.GetChainPrivKey(req.passPhrase) if err != nil { - return nil, err + return nil, fmt.Errorf("the chain key does not exist, should create the chain key first: %w", err) } + chainPk := &secp256k1.PubKey{Key: chainSk.PubKey().Bytes()} - kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) + // 2. create EOTS key + fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) if err != nil { return nil, err } - - keyPair, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + fpPk, err := bbntypes.NewBIP340PubKey(fpPkBytes) if err != nil { - return nil, fmt.Errorf("failed to create chain key for the finality-provider: %w", err) + return nil, err } - pk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} - fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), req.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) if err != nil { return nil, fmt.Errorf("failed to create proof-of-possession of the finality-provider: %w", err) } - fp := fpstore.NewStoreFinalityProvider(pk, fpPk, req.keyName, req.chainID, pop, req.description, req.commission) + fp := fpstore.NewStoreFinalityProvider(chainPk, fpPk, req.keyName, req.chainID, pop, req.description, req.commission) if err := app.fps.SaveFinalityProvider(fp); err != nil { return nil, fmt.Errorf("failed to save finality-provider: %w", err) @@ -355,6 +357,7 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF 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), ) @@ -363,6 +366,26 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF }, nil } +func CreateChainKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.ChainKeyInfo, error) { + sdkCtx, err := fpkr.CreateClientCtx( + keyringDir, chainID, + ) + if err != nil { + return nil, err + } + + krController, err := fpkr.NewChainKeyringController( + sdkCtx, + keyName, + backend, + ) + if err != nil { + return nil, err + } + + return krController.CreateChainKey(passphrase, hdPath) +} + // main event loop for the finality-provider app func (app *FinalityProviderApp) eventLoop() { defer app.eventWg.Done() diff --git a/finality-provider/service/fp_manager_test.go b/finality-provider/service/fp_manager_test.go index 841cecd7..4c8d827a 100644 --- a/finality-provider/service/fp_manager_test.go +++ b/finality-provider/service/fp_manager_test.go @@ -1,8 +1,6 @@ package service_test import ( - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" - "github.com/babylonchain/finality-provider/util" "math/rand" "os" "path/filepath" @@ -10,17 +8,21 @@ 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" - fpstore "github.com/babylonchain/finality-provider/finality-provider/store" "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" "github.com/babylonchain/finality-provider/finality-provider/proto" @@ -132,9 +134,9 @@ func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc c require.NoError(t, err) btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - keyPair, err := kc.CreateChainKey(passphrase, hdPath) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) - bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} + 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) diff --git a/itest/test_manager.go b/itest/test_manager.go index 4da76eae..9a3eddb4 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -1,7 +1,6 @@ package e2etest import ( - "github.com/btcsuite/btcd/btcec/v2" "math/rand" "os" "path/filepath" @@ -11,6 +10,8 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcec/v2" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" @@ -160,6 +161,9 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser commission := sdkmath.LegacyZeroDec() desc, err := newDescription(moniker).Marshal() require.NoError(t, err) + cfg := app.GetConfig() + _, 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) _, err = app.RegisterFinalityProvider(res.FpPk.MarshalHex()) diff --git a/keyring/keyringcontroller.go b/keyring/keyringcontroller.go index f5d141af..c5167324 100644 --- a/keyring/keyringcontroller.go +++ b/keyring/keyringcontroller.go @@ -70,7 +70,7 @@ func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { return kc.kr } -func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*types.KeyPair, error) { +func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*types.ChainKeyInfo, error) { keyringAlgos, _ := kc.kr.SupportedAlgorithms() algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) if err != nil { @@ -88,9 +88,6 @@ func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*ty return nil, err } - // TODO use a better way to remind the user to keep it - fmt.Printf("Generated mnemonic for the finality provider %s is:\n%s\n", kc.fpName, mnemonic) - // we need to repeat the passphrase to mock the reentry kc.input.Reset(passphrase + "\n" + passphrase) record, err := kc.kr.NewAccount(kc.fpName, mnemonic, passphrase, hdPath, algo) @@ -103,7 +100,12 @@ func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*ty switch v := privKey.(type) { case *sdksecp256k1.PrivKey: sk, pk := btcec.PrivKeyFromBytes(v.Key) - return &types.KeyPair{PublicKey: pk, PrivateKey: sk}, nil + return &types.ChainKeyInfo{ + Name: kc.fpName, + PublicKey: pk, + PrivateKey: sk, + Mnemonic: mnemonic, + }, nil default: return nil, fmt.Errorf("unsupported key type in keyring") } diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go index 1a8c6e57..d63c8a71 100644 --- a/keyring/keyringcontroller_test.go +++ b/keyring/keyringcontroller_test.go @@ -1,12 +1,13 @@ package keyring_test import ( - "go.uber.org/zap" "math/rand" "os" "path/filepath" "testing" + "go.uber.org/zap" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" "github.com/babylonchain/babylon/types" @@ -52,9 +53,9 @@ func FuzzCreatePoP(f *testing.F) { require.NoError(t, err) btcPk, err := types.NewBIP340PubKey(btcPkBytes) require.NoError(t, err) - keyPair, err := kc.CreateChainKey(passphrase, hdPath) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath) require.NoError(t, err) - bbnPk := &secp256k1.PubKey{Key: keyPair.PublicKey.SerializeCompressed()} + 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) diff --git a/testutil/datagen.go b/testutil/datagen.go index e842c53b..9fe0c07e 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -2,12 +2,15 @@ package testutil import ( "encoding/hex" - eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "math/rand" "testing" "time" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" @@ -128,6 +131,10 @@ func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.Finality 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) + require.NoError(t, err) + res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) diff --git a/types/chainkey.go b/types/chainkey.go new file mode 100644 index 00000000..b5af543b --- /dev/null +++ b/types/chainkey.go @@ -0,0 +1,24 @@ +package types + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ChainKeyInfo struct { + Name string + Mnemonic string + PublicKey *btcec.PublicKey + PrivateKey *btcec.PrivateKey +} + +func (ki *ChainKeyInfo) GetValAddress() (sdk.ValAddress, error) { + if ki.PublicKey == nil { + return nil, fmt.Errorf("empty public key") + } + pk := secp256k1.PubKey{Key: ki.PublicKey.SerializeCompressed()} + return pk.Address().Bytes(), nil +} diff --git a/types/key.go b/types/key.go deleted file mode 100644 index b73dcb9d..00000000 --- a/types/key.go +++ /dev/null @@ -1,8 +0,0 @@ -package types - -import "github.com/btcsuite/btcd/btcec/v2" - -type KeyPair struct { - PublicKey *btcec.PublicKey - PrivateKey *btcec.PrivateKey -} From 4132719597f5e7d3b3805f9a5db2a324f5add653 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 20 Dec 2023 17:01:39 +0800 Subject: [PATCH 38/66] chore: Add `key-name` flag back to `create-finality-provider` cmd (#185) --- docs/finality-provider.md | 5 +++-- finality-provider/cmd/fpcli/daemoncmd.go | 14 ++++++++++++-- finality-provider/service/app.go | 7 ++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 8b982d2d..09c61357 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -92,8 +92,7 @@ To see the complete list of configuration options, check the `fpd.conf` file. 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 bond -with the EOTS key of the finality provider you want to create in [step 5](#5-create-and-register-a-finality-provider). +This key will be also used to pay for fees of transactions to the consumer chain. Use the following command to add the key: @@ -152,6 +151,8 @@ The finality provider can be registered with Babylon through the `register-finality-provider` command. The output contains the hash of the Babylon finality provider registration transaction. +Note that if the `key-name` is not specified, the `Key` field of config specified in [step](#3-add-key-for-the-consumer-chain) +will be used. ```bash $ fpcli register-finality-provider \ diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index 6bbeed72..9d321a66 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -17,6 +17,7 @@ import ( const ( fpdDaemonAddressFlag = "daemon-address" + keyNameFlag = "key-name" homeFlag = "home" fpBTCPkFlag = "btc-pk" blockHeightFlag = "height" @@ -85,6 +86,10 @@ var createFpDaemonCmd = cli.Command{ Usage: "Full address of the finality provider daemon in format tcp://:", Value: defaultFpdDaemonAddress, }, + 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)", @@ -158,9 +163,14 @@ func createFpDaemon(ctx *cli.Context) error { if err != nil { return fmt.Errorf("failed to load config from %s: %w", fpcfg.ConfigFile(ctx.String(homeFlag)), err) } - keyName := cfg.BabylonConfig.Key + + keyName := ctx.String(keyNameFlag) + // if key name is not specified, we use the key of the config if keyName == "" { - return fmt.Errorf("the key in config is empty") + keyName = cfg.BabylonConfig.Key + if keyName == "" { + return fmt.Errorf("the key in config is empty") + } } client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 89ec0ae9..7ddd865e 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -325,7 +325,12 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF } chainSk, err := kr.GetChainPrivKey(req.passPhrase) if err != nil { - return nil, fmt.Errorf("the chain key does not exist, should create the chain key first: %w", err) + // the chain key does not exist, should create the chain key first + keyInfo, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + if err != nil { + return nil, fmt.Errorf("failed to create chain key %s: %w", req.keyName, err) + } + chainSk = &secp256k1.PrivKey{Key: keyInfo.PrivateKey.Serialize()} } chainPk := &secp256k1.PubKey{Key: chainSk.PubKey().Bytes()} From e90645a877b7c886937132c82a722a680f72598c Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 21 Dec 2023 15:26:07 +0800 Subject: [PATCH 39/66] chore: Add `start --all` for `fpd` (#188) --- finality-provider/cmd/fpd/flags.go | 1 + finality-provider/cmd/fpd/start.go | 19 ++++++++++++++---- finality-provider/service/app.go | 4 ++++ finality-provider/service/fp_manager.go | 26 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/flags.go index fe764289..886f434b 100644 --- a/finality-provider/cmd/fpd/flags.go +++ b/finality-provider/cmd/fpd/flags.go @@ -5,6 +5,7 @@ import "github.com/cosmos/cosmos-sdk/crypto/keyring" const ( homeFlag = "home" forceFlag = "force" + allFlag = "all" passphraseFlag = "passphrase" fpPkFlag = "finality-provider-pk" keyNameFlag = "key-name" diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go index dbc46524..ef46afbe 100644 --- a/finality-provider/cmd/fpd/start.go +++ b/finality-provider/cmd/fpd/start.go @@ -2,12 +2,14 @@ package main import ( "fmt" + "path/filepath" + "github.com/babylonchain/babylon/types" - "github.com/babylonchain/finality-provider/log" - "github.com/babylonchain/finality-provider/util" "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" - "path/filepath" + + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/service" @@ -23,6 +25,10 @@ var startCommand = cli.Command{ Usage: "The pass phrase used to decrypt the private key", Value: defaultPassphrase, }, + cli.BoolFlag{ + Name: allFlag, + Usage: "Start all the managed finality providers", + }, cli.StringFlag{ Name: homeFlag, Usage: "The path to the finality-provider home directory", @@ -44,6 +50,7 @@ func start(ctx *cli.Context) error { homePath = util.CleanAndExpandPath(homePath) passphrase := ctx.String(passphraseFlag) fpPkStr := ctx.String(fpPkFlag) + all := ctx.Bool(allFlag) cfg, err := fpcfg.LoadConfig(homePath) if err != nil { @@ -66,7 +73,7 @@ func start(ctx *cli.Context) error { return fmt.Errorf("failed to start the finality-provider app: %w", err) } - if fpPkStr != "" { + if !all && fpPkStr != "" { // start the finality-provider instance with the given public key fpPk, err := types.NewBIP340PubKeyFromHex(fpPkStr) if err != nil { @@ -75,6 +82,10 @@ func start(ctx *cli.Context) error { if err := fpApp.StartHandlingFinalityProvider(fpPk, passphrase); err != nil { return fmt.Errorf("failed to start the finality-provider instance %s: %w", fpPkStr, err) } + } else if all { + if err := fpApp.StartHandlingAll(); err != nil { + return err + } } // Hook interceptor for os signals. diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 7ddd865e..5d1aea0c 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -217,6 +217,10 @@ func (app *FinalityProviderApp) StartHandlingFinalityProvider(fpPk *bbntypes.BIP return app.fpManager.StartFinalityProvider(fpPk, passphrase) } +func (app *FinalityProviderApp) StartHandlingAll() error { + return app.fpManager.StartAll() +} + // NOTE: this is not safe in production, so only used for testing purpose func (app *FinalityProviderApp) getFpPrivKey(fpPk []byte) (*btcec.PrivateKey, error) { record, err := app.eotsManager.KeyRecord(fpPk, "") diff --git a/finality-provider/service/fp_manager.go b/finality-provider/service/fp_manager.go index c1d176b4..a045592e 100644 --- a/finality-provider/service/fp_manager.go +++ b/finality-provider/service/fp_manager.go @@ -216,6 +216,32 @@ func (fpm *FinalityProviderManager) StartFinalityProvider(fpPk *bbntypes.BIP340P return nil } +func (fpm *FinalityProviderManager) StartAll() error { + if !fpm.isStarted.Load() { + fpm.isStarted.Store(true) + + fpm.wg.Add(1) + go fpm.monitorCriticalErr() + + fpm.wg.Add(1) + go fpm.monitorStatusUpdate() + } + + registeredFps, err := fpm.fps.ListRegisteredFinalityProviders() + 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 { + return err + } + } + + return nil +} + func (fpm *FinalityProviderManager) Stop() error { if !fpm.isStarted.Swap(false) { return fmt.Errorf("the finality-provider manager has already stopped") From 5891f21cd080deb49e6a21f0ce3927fc9a9ee033 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 22 Dec 2023 19:23:06 +0800 Subject: [PATCH 40/66] chore: Improve output of finality provider (#189) --- eotsmanager/proto/eotsmanager.pb.go | 2 +- finality-provider/cmd/fpcli/daemoncmd.go | 4 +- finality-provider/proto/finality_providers.go | 23 +- .../proto/finality_providers.pb.go | 527 +++++++++++------- .../proto/finality_providers.proto | 16 +- finality-provider/service/app.go | 6 +- finality-provider/service/rpcserver.go | 16 +- finality-provider/service/types.go | 4 +- itest/test_manager.go | 8 +- testutil/datagen.go | 3 +- 10 files changed, 374 insertions(+), 235 deletions(-) diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index 844ed8e6..0be2f1d2 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.28.0 +// protoc-gen-go v1.31.0 // protoc (unknown) // source: eotsmanager.proto diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index 9d321a66..8acdaccc 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -193,7 +193,7 @@ func createFpDaemon(ctx *cli.Context) error { return err } - printRespJSON(info) + printRespJSON(info.FinalityProvider) return nil } @@ -280,7 +280,7 @@ func fpInfoDaemon(ctx *cli.Context) error { return err } - printRespJSON(resp) + printRespJSON(resp.FinalityProvider) return nil } diff --git a/finality-provider/proto/finality_providers.go b/finality-provider/proto/finality_providers.go index d43dcb46..57be9c44 100644 --- a/finality-provider/proto/finality_providers.go +++ b/finality-provider/proto/finality_providers.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/x/staking/types" ) func (sfp *StoreFinalityProvider) GetBabylonPK() *secp256k1.PubKey { @@ -33,13 +34,23 @@ func (sfp *StoreFinalityProvider) MustGetBIP340BTCPK() *bbn.BIP340PubKey { return bbn.NewBIP340PubKeyFromBTCPK(btcPK) } -func NewFinalityProviderInfo(sfp *StoreFinalityProvider) *FinalityProviderInfo { +func NewFinalityProviderInfo(sfp *StoreFinalityProvider) (*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(), - Description: sfp.Description, + BabylonPkHex: sfp.GetBabylonPkHexString(), + BtcPkHex: sfp.MustGetBIP340BTCPK().MarshalHex(), + Description: &Description{ + Moniker: des.Moniker, + Identity: des.Identity, + Website: des.Website, + SecurityContact: des.SecurityContact, + Details: des.Details, + }, LastVotedHeight: sfp.LastVotedHeight, LastCommittedHeight: sfp.LastCommittedHeight, - Status: sfp.Status, - } + Status: sfp.Status.String(), + }, nil } diff --git a/finality-provider/proto/finality_providers.pb.go b/finality-provider/proto/finality_providers.pb.go index a0e64a01..47acbdc3 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.28.0 +// protoc-gen-go v1.31.0 // protoc (unknown) // source: finality_providers.proto @@ -25,18 +25,19 @@ 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 -// delegated stake) -// - Active - created and registered to Babylon with stake to vote -// - Inactive - created and registered to Babylon with no stake to vote. -// Finality Provider was already active. +// - Created - created and managed by finality provider client, not registered to +// babylon yet +// - Registered - created and registered to Babylon, 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. +// Finality Provider was already active. +// // Valid State Transactions: -// - Created -> Registered -// - Registered -> Active -// - Active -> Inactive -// - Inactive -> Active +// - Created -> Registered +// - Registered -> Active +// - Active -> Inactive +// - Inactive -> Active type FinalityProviderStatus int32 const ( @@ -281,8 +282,7 @@ type CreateFinalityProviderResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // btc_pk is the hex string of 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"` + FinalityProvider *FinalityProviderInfo `protobuf:"bytes,1,opt,name=finality_provider,json=finalityProvider,proto3" json:"finality_provider,omitempty"` } func (x *CreateFinalityProviderResponse) Reset() { @@ -317,11 +317,11 @@ func (*CreateFinalityProviderResponse) Descriptor() ([]byte, []int) { return file_finality_providers_proto_rawDescGZIP(), []int{3} } -func (x *CreateFinalityProviderResponse) GetBtcPk() string { +func (x *CreateFinalityProviderResponse) GetFinalityProvider() *FinalityProviderInfo { if x != nil { - return x.BtcPk + return x.FinalityProvider } - return "" + return nil } type RegisterFinalityProviderRequest struct { @@ -892,7 +892,7 @@ type FinalityProviderInfo struct { // 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 []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + 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 @@ -901,7 +901,7 @@ type FinalityProviderInfo struct { // to which the finality provider committed a randomness pair LastCommittedHeight uint64 `protobuf:"varint,6,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` // status defines the current finality provider status - Status FinalityProviderStatus `protobuf:"varint,7,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` } func (x *FinalityProviderInfo) Reset() { @@ -950,7 +950,7 @@ func (x *FinalityProviderInfo) GetBtcPkHex() string { return "" } -func (x *FinalityProviderInfo) GetDescription() []byte { +func (x *FinalityProviderInfo) GetDescription() *Description { if x != nil { return x.Description } @@ -978,11 +978,91 @@ func (x *FinalityProviderInfo) GetLastCommittedHeight() uint64 { return 0 } -func (x *FinalityProviderInfo) GetStatus() FinalityProviderStatus { +func (x *FinalityProviderInfo) GetStatus() string { if x != nil { return x.Status } - return FinalityProviderStatus_CREATED + return "" +} + +// Description defines description fields for a finality provider +type Description struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` + Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` + Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty"` + Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` +} + +func (x *Description) Reset() { + *x = Description{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Description) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Description) ProtoMessage() {} + +func (x *Description) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[14] + 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 Description.ProtoReflect.Descriptor instead. +func (*Description) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{14} +} + +func (x *Description) GetMoniker() string { + if x != nil { + return x.Moniker + } + return "" +} + +func (x *Description) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +func (x *Description) GetWebsite() string { + if x != nil { + return x.Website + } + return "" +} + +func (x *Description) GetSecurityContact() string { + if x != nil { + return x.SecurityContact + } + return "" +} + +func (x *Description) GetDetails() string { + if x != nil { + return x.Details + } + return "" } // ProofOfPossession is the proof of possession that a Babylon secp256k1 @@ -1003,7 +1083,7 @@ type ProofOfPossession struct { func (x *ProofOfPossession) Reset() { *x = ProofOfPossession{} if protoimpl.UnsafeEnabled { - mi := &file_finality_providers_proto_msgTypes[14] + mi := &file_finality_providers_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1016,7 +1096,7 @@ func (x *ProofOfPossession) String() string { func (*ProofOfPossession) ProtoMessage() {} func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { - mi := &file_finality_providers_proto_msgTypes[14] + mi := &file_finality_providers_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1029,7 +1109,7 @@ func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { // Deprecated: Use ProofOfPossession.ProtoReflect.Descriptor instead. func (*ProofOfPossession) Descriptor() ([]byte, []int) { - return file_finality_providers_proto_rawDescGZIP(), []int{14} + return file_finality_providers_proto_rawDescGZIP(), []int{15} } func (x *ProofOfPossession) GetBabylonSig() []byte { @@ -1058,7 +1138,7 @@ type SchnorrRandPair struct { func (x *SchnorrRandPair) Reset() { *x = SchnorrRandPair{} if protoimpl.UnsafeEnabled { - mi := &file_finality_providers_proto_msgTypes[15] + mi := &file_finality_providers_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1071,7 +1151,7 @@ func (x *SchnorrRandPair) String() string { func (*SchnorrRandPair) ProtoMessage() {} func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { - mi := &file_finality_providers_proto_msgTypes[15] + mi := &file_finality_providers_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1084,7 +1164,7 @@ func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { // Deprecated: Use SchnorrRandPair.ProtoReflect.Descriptor instead. func (*SchnorrRandPair) Descriptor() ([]byte, []int) { - return file_finality_providers_proto_rawDescGZIP(), []int{15} + return file_finality_providers_proto_rawDescGZIP(), []int{16} } func (x *SchnorrRandPair) GetPubRand() []byte { @@ -1131,168 +1211,181 @@ var file_finality_providers_proto_rawDesc = []byte{ 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, 0x22, - 0x37, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x6a, 0x0a, 0x1e, 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, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x58, 0x0a, 0x1f, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, - 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, - 0x50, 0x6b, 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, 0x3b, 0x0a, 0x20, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, - 0x67, 0x0a, 0x1b, 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, 0x12, 0x15, - 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x61, 0x70, 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x61, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, - 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x35, - 0x0a, 0x1c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x65, 0x12, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x58, 0x0a, 0x1f, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, + 0x62, 0x74, 0x63, 0x50, 0x6b, 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, 0x3b, 0x0a, 0x20, 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, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, + 0x73, 0x68, 0x22, 0x67, 0x0a, 0x1b, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, + 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, 0x17, 0x0a, 0x07, + 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, + 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, + 0x78, 0x22, 0x35, 0x0a, 0x1c, 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, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 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, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 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, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x20, 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, 0x22, 0x6f, 0x0a, 0x21, 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, 0x4a, 0x0a, 0x12, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 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, 0xe1, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, + 0x0b, 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, 0xcd, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, + 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, 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, 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, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 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, 0x10, - 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x22, 0x22, 0x0a, 0x20, 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, 0x22, 0x6f, 0x0a, 0x21, 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, 0x4a, 0x0a, 0x12, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 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, 0xe1, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, 0x0b, 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, 0xd8, 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, 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, - 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x35, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 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, 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, 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, + 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, 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, 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, + 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, 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, + 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, 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, 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, + 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, 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 ( @@ -1308,7 +1401,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, 16) +var file_finality_providers_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_finality_providers_proto_goTypes = []interface{}{ (FinalityProviderStatus)(0), // 0: proto.FinalityProviderStatus (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest @@ -1325,32 +1418,34 @@ var file_finality_providers_proto_goTypes = []interface{}{ (*QueryFinalityProviderListResponse)(nil), // 12: proto.QueryFinalityProviderListResponse (*StoreFinalityProvider)(nil), // 13: proto.StoreFinalityProvider (*FinalityProviderInfo)(nil), // 14: proto.FinalityProviderInfo - (*ProofOfPossession)(nil), // 15: proto.ProofOfPossession - (*SchnorrRandPair)(nil), // 16: proto.SchnorrRandPair + (*Description)(nil), // 15: proto.Description + (*ProofOfPossession)(nil), // 16: proto.ProofOfPossession + (*SchnorrRandPair)(nil), // 17: proto.SchnorrRandPair } var file_finality_providers_proto_depIdxs = []int32{ - 14, // 0: proto.QueryFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo - 14, // 1: proto.QueryFinalityProviderListResponse.finality_providers:type_name -> proto.FinalityProviderInfo - 15, // 2: proto.StoreFinalityProvider.pop:type_name -> proto.ProofOfPossession - 0, // 3: proto.StoreFinalityProvider.status:type_name -> proto.FinalityProviderStatus - 0, // 4: proto.FinalityProviderInfo.status:type_name -> proto.FinalityProviderStatus - 1, // 5: proto.FinalityProviders.GetInfo:input_type -> proto.GetInfoRequest - 3, // 6: proto.FinalityProviders.CreateFinalityProvider:input_type -> proto.CreateFinalityProviderRequest - 5, // 7: proto.FinalityProviders.RegisterFinalityProvider:input_type -> proto.RegisterFinalityProviderRequest - 7, // 8: proto.FinalityProviders.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest - 9, // 9: proto.FinalityProviders.QueryFinalityProvider:input_type -> proto.QueryFinalityProviderRequest - 11, // 10: proto.FinalityProviders.QueryFinalityProviderList:input_type -> proto.QueryFinalityProviderListRequest - 2, // 11: proto.FinalityProviders.GetInfo:output_type -> proto.GetInfoResponse - 4, // 12: proto.FinalityProviders.CreateFinalityProvider:output_type -> proto.CreateFinalityProviderResponse - 6, // 13: proto.FinalityProviders.RegisterFinalityProvider:output_type -> proto.RegisterFinalityProviderResponse - 8, // 14: proto.FinalityProviders.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse - 10, // 15: proto.FinalityProviders.QueryFinalityProvider:output_type -> proto.QueryFinalityProviderResponse - 12, // 16: proto.FinalityProviders.QueryFinalityProviderList:output_type -> proto.QueryFinalityProviderListResponse - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 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 + 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 } func init() { file_finality_providers_proto_init() } @@ -1528,7 +1623,7 @@ func file_finality_providers_proto_init() { } } file_finality_providers_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProofOfPossession); i { + switch v := v.(*Description); i { case 0: return &v.state case 1: @@ -1540,6 +1635,18 @@ func file_finality_providers_proto_init() { } } file_finality_providers_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProofOfPossession); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SchnorrRandPair); i { case 0: return &v.state @@ -1558,7 +1665,7 @@ func file_finality_providers_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_finality_providers_proto_rawDesc, NumEnums: 1, - NumMessages: 16, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/finality-provider/proto/finality_providers.proto b/finality-provider/proto/finality_providers.proto index 0ef3b8a7..5ee37ec9 100644 --- a/finality-provider/proto/finality_providers.proto +++ b/finality-provider/proto/finality_providers.proto @@ -60,8 +60,7 @@ message CreateFinalityProviderRequest { } message CreateFinalityProviderResponse { - // btc_pk is the hex string of BTC secp256k1 public key of the finality provider encoded in BIP-340 spec - string btc_pk = 1; + FinalityProviderInfo finality_provider = 1; } message RegisterFinalityProviderRequest { @@ -149,7 +148,7 @@ message FinalityProviderInfo { // 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 - bytes description = 3; + Description description = 3; // commission defines the commission rate for the finality provider string commission = 4 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", @@ -161,7 +160,16 @@ message FinalityProviderInfo { // to which the finality provider committed a randomness pair uint64 last_committed_height = 6; // status defines the current finality provider status - FinalityProviderStatus status = 7; + string status = 7; +} + +// Description defines description fields for a finality provider +message Description { + string moniker = 1; + string identity = 2; + string website = 3; + string security_contact = 4; + string details = 5; } // ProofOfPossession is the proof of possession that a Babylon secp256k1 diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 5d1aea0c..3a4f1646 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -314,7 +314,7 @@ func (app *FinalityProviderApp) CreateFinalityProvider( return nil, err case successResponse := <-req.successResponse: return &CreateFinalityProviderResult{ - FpPk: successResponse.FpPk, + StoreFp: successResponse.StoreFp, }, nil case <-app.quit: return nil, fmt.Errorf("finality-provider app is shutting down") @@ -371,7 +371,7 @@ func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createF ) return &createFinalityProviderResponse{ - FpPk: fpPk, + StoreFp: fp, }, nil } @@ -408,7 +408,7 @@ func (app *FinalityProviderApp) eventLoop() { continue } - req.successResponse <- &createFinalityProviderResponse{FpPk: res.FpPk} + req.successResponse <- &createFinalityProviderResponse{StoreFp: res.StoreFp} case ev := <-app.finalityProviderRegisteredEventChan: fpStored, err := app.fps.GetStoreFinalityProvider(ev.btcPubKey.MustMarshal()) diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go index 77438fb8..a2948746 100644 --- a/finality-provider/service/rpcserver.go +++ b/finality-provider/service/rpcserver.go @@ -102,8 +102,12 @@ 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{ - BtcPk: result.FpPk.MarshalHex(), + FinalityProvider: fpInfo, }, nil } @@ -189,7 +193,10 @@ func (r *rpcServer) QueryFinalityProvider(ctx context.Context, req *proto.QueryF return nil, err } - fpInfo := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + if err != nil { + return nil, err + } return &proto.QueryFinalityProviderResponse{FinalityProvider: fpInfo}, nil } @@ -202,7 +209,10 @@ func (r *rpcServer) QueryFinalityProviderList(ctx context.Context, req *proto.Qu fpsInfo := make([]*proto.FinalityProviderInfo, len(fps)) for i, fp := range fps { - fpInfo := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + if err != nil { + return nil, err + } fpsInfo[i] = fpInfo } diff --git a/finality-provider/service/types.go b/finality-provider/service/types.go index 59ebf46e..58b77664 100644 --- a/finality-provider/service/types.go +++ b/finality-provider/service/types.go @@ -15,7 +15,7 @@ import ( ) type createFinalityProviderResponse struct { - FpPk *bbntypes.BIP340PubKey + StoreFp *proto.StoreFinalityProvider } type createFinalityProviderRequest struct { keyName string @@ -53,7 +53,7 @@ type RegisterFinalityProviderResponse struct { } type CreateFinalityProviderResult struct { - FpPk *bbntypes.BIP340PubKey + StoreFp *proto.StoreFinalityProvider } type fpState struct { diff --git a/itest/test_manager.go b/itest/test_manager.go index 9a3eddb4..17880e5b 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -166,11 +166,13 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser require.NoError(t, err) res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, desc, &commission) require.NoError(t, err) - _, err = app.RegisterFinalityProvider(res.FpPk.MarshalHex()) + fpPk, err := bbntypes.NewBIP340PubKey(res.StoreFp.BtcPk) require.NoError(t, err) - err = app.StartHandlingFinalityProvider(res.FpPk, passphrase) + _, err = app.RegisterFinalityProvider(fpPk.MarshalHex()) require.NoError(t, err) - fpIns, err := app.GetFinalityProviderInstance(res.FpPk) + err = app.StartHandlingFinalityProvider(fpPk, passphrase) + require.NoError(t, err) + fpIns, err := app.GetFinalityProviderInstance(fpPk) require.NoError(t, err) require.True(t, fpIns.IsRunning()) require.NoError(t, err) diff --git a/testutil/datagen.go b/testutil/datagen.go index 9fe0c07e..ace81e60 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -138,7 +138,8 @@ func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.Finality res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) - storedFp, err := app.GetFinalityProviderStore().GetStoreFinalityProvider(res.FpPk.MustMarshal()) + fpPk := res.StoreFp.BtcPk + storedFp, err := app.GetFinalityProviderStore().GetStoreFinalityProvider(fpPk) require.NoError(t, err) return storedFp From e5257ecc1e367a3823dcf904564b8c6ba1ee9207 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 3 Jan 2024 14:01:17 +0800 Subject: [PATCH 41/66] chore: replace local last committed height with remote query (#192) --- clientcontroller/babylon.go | 37 ++- clientcontroller/interface.go | 6 +- finality-provider/proto/finality_providers.go | 5 +- .../proto/finality_providers.pb.go | 221 ++++++++---------- .../proto/finality_providers.proto | 12 +- finality-provider/service/fp_instance.go | 81 +++++-- finality-provider/service/fp_instance_test.go | 10 +- finality-provider/service/fp_manager_test.go | 1 + finality-provider/service/types.go | 22 -- itest/e2e_test.go | 2 +- itest/test_manager.go | 6 +- testutil/datagen.go | 7 + testutil/mocks/babylon.go | 30 +++ testutil/utils.go | 9 + 14 files changed, 259 insertions(+), 190 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 86c5996f..5d66d0c0 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -4,9 +4,10 @@ import ( "context" "encoding/hex" "fmt" - "github.com/btcsuite/btcd/btcec/v2" "time" + "github.com/btcsuite/btcd/btcec/v2" + "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" @@ -414,6 +415,40 @@ func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types. 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) { + pagination := &sdkquery.PageRequest{ + // NOTE: the count is limited by pagination queries + Limit: count, + Reverse: true, + } + + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) + defer cancel() + + clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} + + queryClient := finalitytypes.NewQueryClient(clientCtx) + + queryRequest := &finalitytypes.QueryListPublicRandomnessRequest{ + Pagination: pagination, + FpBtcPkHex: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk).MarshalHex(), + } + + res, err := queryClient.ListPublicRandomness(ctx, queryRequest) + if err != nil { + return nil, fmt.Errorf("failed to query committed public randomness: %v", err) + } + + committedPubRand := make(map[uint64]*btcec.FieldVal, len(res.PubRandMap)) + for k, v := range res.PubRandMap { + committedPubRand[k] = v.ToFieldVal() + } + + return committedPubRand, nil +} + func (bc *BabylonController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { if endHeight < startHeight { return nil, fmt.Errorf("the startHeight %v should not be higher than the endHeight %v", startHeight, endHeight) diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index a51c7d53..54fc2bda 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -1,8 +1,9 @@ package clientcontroller import ( - "cosmossdk.io/math" "fmt" + + "cosmossdk.io/math" "github.com/btcsuite/btcd/chaincfg" "go.uber.org/zap" @@ -60,6 +61,9 @@ type FinalityProviderAPIs 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) diff --git a/finality-provider/proto/finality_providers.go b/finality-provider/proto/finality_providers.go index 57be9c44..975535c0 100644 --- a/finality-provider/proto/finality_providers.go +++ b/finality-provider/proto/finality_providers.go @@ -49,8 +49,7 @@ func NewFinalityProviderInfo(sfp *StoreFinalityProvider) (*FinalityProviderInfo, SecurityContact: des.SecurityContact, Details: des.Details, }, - LastVotedHeight: sfp.LastVotedHeight, - LastCommittedHeight: sfp.LastCommittedHeight, - Status: sfp.Status.String(), + 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 47acbdc3..01c48ce6 100644 --- a/finality-provider/proto/finality_providers.pb.go +++ b/finality-provider/proto/finality_providers.pb.go @@ -762,14 +762,11 @@ type StoreFinalityProvider struct { 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"` - // last_committed_height defines the height of the last Babylon block - // to which the finality provider committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,9,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_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,10,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` + LastProcessedHeight uint64 `protobuf:"varint,9,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` // status defines the current finality provider status - Status FinalityProviderStatus `protobuf:"varint,11,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` + Status FinalityProviderStatus `protobuf:"varint,10,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` } func (x *StoreFinalityProvider) Reset() { @@ -860,13 +857,6 @@ func (x *StoreFinalityProvider) GetLastVotedHeight() uint64 { return 0 } -func (x *StoreFinalityProvider) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - func (x *StoreFinalityProvider) GetLastProcessedHeight() uint64 { if x != nil { return x.LastProcessedHeight @@ -897,11 +887,8 @@ type FinalityProviderInfo struct { 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"` - // last_committed_height defines the height of the last Babylon block - // to which the finality provider committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,6,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` // status defines the current finality provider status - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` } func (x *FinalityProviderInfo) Reset() { @@ -971,13 +958,6 @@ func (x *FinalityProviderInfo) GetLastVotedHeight() uint64 { return 0 } -func (x *FinalityProviderInfo) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - func (x *FinalityProviderInfo) GetStatus() string { if x != nil { return x.Status @@ -1261,7 +1241,7 @@ 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, 0xe1, 0x03, 0x0a, 0x15, 0x53, 0x74, 0x6f, + 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, @@ -1282,110 +1262,103 @@ var file_finality_providers_proto_rawDesc = []byte{ 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, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, + 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, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 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, 0x0a, 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, - 0x0b, 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, 0xcd, 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, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, - 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, 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, 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, + 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, + 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, 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, 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, + 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, 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, 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, + 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, + 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 ( diff --git a/finality-provider/proto/finality_providers.proto b/finality-provider/proto/finality_providers.proto index 5ee37ec9..484e706f 100644 --- a/finality-provider/proto/finality_providers.proto +++ b/finality-provider/proto/finality_providers.proto @@ -131,14 +131,11 @@ message StoreFinalityProvider { string chain_id = 7; // last_voted_height defines the height of the last voted Babylon block uint64 last_voted_height = 8; - // last_committed_height defines the height of the last Babylon block - // to which the finality provider committed a randomness pair - uint64 last_committed_height = 9; // last_processed_height defines the height of the last successfully processed block // even though the vote is not cast - uint64 last_processed_height = 10; + uint64 last_processed_height = 9; // status defines the current finality provider status - FinalityProviderStatus status = 11; + FinalityProviderStatus status = 10; } // FinalityProviderInfo is the basic information of a finality provider mainly for external usage @@ -156,11 +153,8 @@ message FinalityProviderInfo { ]; // last_voted_height defines the height of the last voted Babylon block uint64 last_voted_height = 5; - // last_committed_height defines the height of the last Babylon block - // to which the finality provider committed a randomness pair - uint64 last_committed_height = 6; // status defines the current finality provider status - string status = 7; + string status = 6; } // Description defines description fields for a finality provider diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go index ce9f74b5..1a852321 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -281,7 +281,6 @@ func (fp *FinalityProviderInstance) randomnessCommitmentLoop() { fp.logger.Info( "successfully committed public randomness to the consumer chain", zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("last_committed_height", fp.GetLastCommittedHeight()), zap.String("tx_hash", txRes.TxHash), ) } @@ -338,7 +337,11 @@ func (fp *FinalityProviderInstance) tryFastSync(targetBlock *types.BlockInfo) (* return nil, fmt.Errorf("the finality-provider %s is already in sync", fp.GetBtcPkHex()) } - if fp.GetLastCommittedHeight() <= fp.GetLastVotedHeight() { + lastCommittedHeight, err := fp.GetLastCommittedHeight() + if err != nil { + return nil, err + } + if lastCommittedHeight <= fp.GetLastVotedHeight() { if err := fp.SetLastProcessedHeight(targetBlock.Height); err != nil { return nil, err } @@ -403,17 +406,6 @@ func (fp *FinalityProviderInstance) shouldSubmitFinalitySignature(b *types.Block return false, nil } - // check last committed height - if fp.GetLastCommittedHeight() < b.Height { - fp.logger.Debug( - "public rand is not committed, skip voting", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("block_height", b.Height), - zap.Uint64("last_committed_height", fp.GetLastCommittedHeight()), - ) - return false, nil - } - power, err := fp.GetVotingPowerWithRetry(b.Height) if err != nil { return false, err @@ -562,7 +554,10 @@ func (fp *FinalityProviderInstance) retryCommitPubRandUntilBlockFinalized(target // 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 := fp.GetLastCommittedHeight() + lastCommittedHeight, err := fp.GetLastCommittedHeight() + if err != nil { + return nil, err + } var startHeight uint64 if lastCommittedHeight == uint64(0) { @@ -577,7 +572,7 @@ func (fp *FinalityProviderInstance) CommitPubRand(tipBlock *types.BlockInfo) (*t "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", fp.GetLastCommittedHeight()), + zap.Uint64("last_committed_height", lastCommittedHeight), ) return nil, nil } @@ -620,10 +615,6 @@ func (fp *FinalityProviderInstance) CommitPubRand(tipBlock *types.BlockInfo) (*t return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) } - newLastCommittedHeight := startHeight + uint64(len(pubRandList)-1) - - fp.MustSetLastCommittedHeight(newLastCommittedHeight) - return res, nil } @@ -716,9 +707,13 @@ func (fp *FinalityProviderInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.S // 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 - if fp.GetLastCommittedHeight() < b.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", - fp.GetLastCommittedHeight(), b.Height) + lastCommittedHeight, b.Height) } eotsSig, err := fp.signEotsSig(b) @@ -785,6 +780,50 @@ 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 { diff --git a/finality-provider/service/fp_instance_test.go b/finality-provider/service/fp_instance_test.go index 6cf19ac7..dc180f8b 100644 --- a/finality-provider/service/fp_instance_test.go +++ b/finality-provider/service/fp_instance_test.go @@ -28,10 +28,10 @@ func FuzzCommitPubRandList(f *testing.F) { startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()). + Return(uint64(0), nil).AnyTimes() app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). - Return(uint64(0), nil).AnyTimes() fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) require.NoError(t, err) @@ -42,10 +42,6 @@ func FuzzCommitPubRandList(f *testing.F) { res, err := fpIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - - // check the last_committed_height - numPubRand := app.GetConfig().NumPubRand - require.Equal(t, startingBlock.Height+numPubRand, fpIns.GetStoreFinalityProvider().LastCommittedHeight) }) } @@ -107,7 +103,7 @@ func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc cli // create finality-provider app with randomized config fpHomeDir := filepath.Join(t.TempDir(), "fp-home") fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) - fpCfg.NumPubRand = uint64(25) + fpCfg.NumPubRand = testutil.TestPubRandNum fpCfg.PollerConfig.AutoChainScanningMode = false fpCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, cc, em, logger) diff --git a/finality-provider/service/fp_manager_test.go b/finality-provider/service/fp_manager_test.go index 4c8d827a..ce57cf8f 100644 --- a/finality-provider/service/fp_manager_test.go +++ b/finality-provider/service/fp_manager_test.go @@ -59,6 +59,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() votingPower := uint64(r.Intn(2)) mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() diff --git a/finality-provider/service/types.go b/finality-provider/service/types.go index 58b77664..b2aa907b 100644 --- a/finality-provider/service/types.go +++ b/finality-provider/service/types.go @@ -82,13 +82,6 @@ func (fps *fpState) setLastProcessedHeight(height uint64) error { return fps.s.UpdateFinalityProvider(fps.fp) } -func (fps *fpState) setLastCommittedHeight(height uint64) error { - fps.mu.Lock() - fps.fp.LastCommittedHeight = height - fps.mu.Unlock() - return fps.s.UpdateFinalityProvider(fps.fp) -} - func (fps *fpState) setLastProcessedAndVotedHeight(height uint64) error { fps.mu.Lock() fps.fp.LastVotedHeight = height @@ -133,10 +126,6 @@ func (fp *FinalityProviderInstance) GetLastProcessedHeight() uint64 { return fp.state.getStoreFinalityProvider().LastProcessedHeight } -func (fp *FinalityProviderInstance) GetLastCommittedHeight() uint64 { - return fp.state.getStoreFinalityProvider().LastCommittedHeight -} - func (fp *FinalityProviderInstance) GetChainID() []byte { return []byte(fp.state.getStoreFinalityProvider().ChainId) } @@ -163,17 +152,6 @@ func (fp *FinalityProviderInstance) MustSetLastProcessedHeight(height uint64) { } } -func (fp *FinalityProviderInstance) SetLastCommittedHeight(height uint64) error { - return fp.state.setLastCommittedHeight(height) -} - -func (fp *FinalityProviderInstance) MustSetLastCommittedHeight(height uint64) { - if err := fp.SetLastCommittedHeight(height); err != nil { - fp.logger.Fatal("failed to set last committed height", - zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("last_committed_height", height)) - } -} - func (fp *FinalityProviderInstance) updateStateAfterFinalitySigSubmission(height uint64) error { return fp.state.setLastProcessedAndVotedHeight(height) } diff --git a/itest/e2e_test.go b/itest/e2e_test.go index cfb11d4b..493bdf0c 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -4,12 +4,12 @@ package e2etest import ( - "github.com/btcsuite/btcd/btcec/v2" "math/rand" "testing" "time" "github.com/babylonchain/babylon/testutil/datagen" + "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" "github.com/babylonchain/finality-provider/finality-provider/service" diff --git a/itest/test_manager.go b/itest/test_manager.go index 17880e5b..9c983781 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -236,7 +236,11 @@ func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.FinalityProviderInstance) { require.Eventually(t, func() bool { - return fpIns.GetLastCommittedHeight() > 0 + lastCommittedHeight, err := fpIns.GetLastCommittedHeight() + if err != nil { + return false + } + return lastCommittedHeight > 0 }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("public randomness is successfully committed") diff --git a/testutil/datagen.go b/testutil/datagen.go index ace81e60..36fefc06 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/babylonchain/babylon/crypto/eots" "github.com/cosmos/cosmos-sdk/crypto/keyring" eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" @@ -47,6 +48,12 @@ 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 { // generate BTC key pair btcSK, btcPK, err := datagen.GenRandomBTCKeyPair(r) diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 21ffc81b..aa7c58aa 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -156,6 +156,21 @@ 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) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryLastCommittedPublicRand", fpPk, count) + ret0, _ := ret[0].(map[uint64]*btcec.FieldVal) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryLastCommittedPublicRand indicates an expected call of QueryLastCommittedPublicRand. +func (mr *MockClientControllerMockRecorder) QueryLastCommittedPublicRand(fpPk, count interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastCommittedPublicRand", reflect.TypeOf((*MockClientController)(nil).QueryLastCommittedPublicRand), fpPk, count) +} + // QueryLatestFinalizedBlocks mocks base method. func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() @@ -389,6 +404,21 @@ func (mr *MockFinalityProviderAPIsMockRecorder) QueryFinalityProviderVotingPower return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) } +// QueryLastCommittedPublicRand mocks base method. +func (m *MockFinalityProviderAPIs) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QueryLastCommittedPublicRand", fpPk, count) + ret0, _ := ret[0].(map[uint64]*btcec.FieldVal) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// QueryLastCommittedPublicRand indicates an expected call of QueryLastCommittedPublicRand. +func (mr *MockFinalityProviderAPIsMockRecorder) QueryLastCommittedPublicRand(fpPk, count interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastCommittedPublicRand", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryLastCommittedPublicRand), fpPk, count) +} + // QueryLatestFinalizedBlocks mocks base method. func (m *MockFinalityProviderAPIs) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() diff --git a/testutil/utils.go b/testutil/utils.go index ca3b8808..f464616f 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -5,12 +5,15 @@ import ( "testing" sdkmath "cosmossdk.io/math" + "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/babylonchain/finality-provider/testutil/mocks" "github.com/babylonchain/finality-provider/types" ) +const TestPubRandNum = 25 + func EmptyDescription() []byte { return []byte("empty description") } @@ -41,6 +44,12 @@ func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, curr mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() mockClientController.EXPECT().QueryStakingParams().Return(params, nil).AnyTimes() + o1 := mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() + lastCommittedHeight := startHeight + TestPubRandNum + lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) + lastCommittedPubRandMap[lastCommittedHeight] = GenPublicRand(r, t).ToFieldVal() + o2 := mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() + gomock.InOrder(o1, o2) return mockClientController } From a7b6433deb36927ec55d3231c9fb550deb919eaa Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 4 Jan 2024 09:16:36 +0800 Subject: [PATCH 42/66] chore: Clean up cli usage (#194) --- docs/eots.md | 12 ++-- docs/finality-provider.md | 53 ++++++++-------- eotsmanager/client/rpcclient.go | 10 ++- eotsmanager/cmd/eotsd/flags.go | 5 +- eotsmanager/cmd/eotsd/init.go | 10 +-- eotsmanager/cmd/eotsd/start.go | 26 ++++++-- eotsmanager/config/config.go | 16 ++--- finality-provider/cmd/fpcli/daemoncmd.go | 77 +++--------------------- finality-provider/cmd/fpcli/flags.go | 23 +++++++ finality-provider/cmd/fpcli/main.go | 24 +++----- finality-provider/cmd/fpd/flags.go | 1 + finality-provider/cmd/fpd/init.go | 2 +- finality-provider/cmd/fpd/keys.go | 6 +- finality-provider/cmd/fpd/start.go | 17 +++++- finality-provider/config/config.go | 6 +- finality-provider/proto/buf.lock | 4 +- finality-provider/proto/buf.yaml | 2 +- finality-provider/service/app.go | 2 +- 18 files changed, 152 insertions(+), 144 deletions(-) create mode 100644 finality-provider/cmd/fpcli/flags.go diff --git a/docs/eots.md b/docs/eots.md index 41110e61..005964ae 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -55,7 +55,7 @@ $ ls /path/to/eotsd/home/ If the `--home` flag is not specified, then the default home location will be used. For different operating systems, those are: -- **MacOS** `~/Library/Application Support/Eotsd` +- **MacOS** `~/Users//Library/Application Support/Eotsd` - **Linux** `~/.Eotsd` - **Windows** `C:\Users\\AppData\Local\Eotsd` @@ -63,7 +63,7 @@ Below are some of the important parameters in the `eotsd.conf` file. ```bash # Default address to listen for RPC connections -RpcListener = localhost:15813 +RpcListener = 127.0.0.1:15813 # Type of keyring to use, # supported backends - (os|file|kwallet|pass|test|memory) @@ -91,13 +91,13 @@ $ eotsd start --home /path/to/eotsd/home ``` This will start the rpc server at the address specified in the configuration under -the `RpcListener` field. It can also be overridden with custom address using -the `--rpclistener` flag. +the `RpcListener` field, which has a default value of `127.0.0.1:15813`. +You can also specify a custom address using the `--rpc-listener` flag. ```bash -$ eotsd start --rpclistener 'localhost:8081' +$ eotsd start -time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening on 127.0.0.1:8081" +time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:15813"}" time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager Daemon is fully active!" ``` diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 09c61357..9cab3649 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -60,7 +60,7 @@ and will be specified along with the `KeyringBackend` field in the next [step](# So we can ignore the setting of the two fields in this step. ```bash -# Address of the EOTS Daemon +# RPC Address of the EOTS Daemon EOTSManagerAddress = 127.0.0.1:15813 # Babylon specific parameters @@ -69,10 +69,10 @@ EOTSManagerAddress = 127.0.0.1:15813 ChainID = chain-test # Babylon node RPC endpoint -RPCAddr = http://localhost:26657 +RPCAddr = http://127.0.0.1:26657 # Babylon node gRPC endpoint -GRPCAddr = https://localhost:9090 +GRPCAddr = https://127.0.0.1:9090 # Name of the key in the keyring to use for signing transactions Key = @@ -112,17 +112,16 @@ $ fpd start --home /path/to/fpd/home ``` This will start the RPC server at the address specified in the configuration under -the `RawRPCListeners` field. A custom address can also be specified using -the `--rpclisten` flag. +the `RpcListener` field, which has a default value of `127.0.0.1:15812`. +You can also specify a custom address using the `--rpc-listener` flag. ```bash -$ fpd start --rpclisten 'localhost:8082' +$ fpd start --rpc-listener '127.0.0.1:8088' -time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager at 127.0.0.1:8081" -time="2023-11-26T16:37:00-05:00" level=info msg="Starting Finality Provider App" -time="2023-11-26T16:37:00-05:00" level=info msg="Version: 0.2.2-alpha commit=, build=production, logging=default, debuglevel=info" +time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager {"address": "127.0.0.1:15813"}" +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 on 127.0.0.1:8082" +time="2023-11-26T16:37:00-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:15812"}" time="2023-11-26T16:37:00-05:00" level=info msg="Finality Provider Daemon is fully active!" ``` @@ -141,9 +140,14 @@ The key name must be the same as the key added in [step](#3-add-key-for-the-cons ```bash $ fpcli create-finality-provider --key-name my-finality-provider \ - --chain-id chain-test --passphrase mypassphrase + --chain-id chain-test --moniker my-name { - "btc_pk": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786" + "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", + "btc_pk_hex": "d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63", + "description": { + "moniker": "my-name" + }, + "status": "CREATED" } ``` @@ -156,7 +160,7 @@ will be used. ```bash $ fpcli register-finality-provider \ - --btc-pk 903fab42070622c551b188c983ce05a31febcab300244daf7d752aba + --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 { "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" } @@ -167,24 +171,25 @@ we can check the finality providers that are managed by the daemon and their sta These can be listed through the `fpcli list-finality-providers` command. The `status` field can receive the following values: -- `1`: The finality provider is active and has received no delegations yet -- `2`: The finality provider is active and has staked BTC tokens -- `3`: The finality provider is inactive (i.e. had staked BTC tokens in the past but not - anymore OR has been slashed) +- `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 +- `SLASHED`: The finality provider is slashed due to malicious behavior -The `last_committed_height` field is the Babylon height up to which the finality provider -has committed EOTS randomness - ```bash $ fpcli list-finality-providers { "finality-providers": [ ... { - "babylon_pk_hex": "0251259b5c88d6ac79d86615220a8111ebb238047df0689357274f004fba3e5a89", - "btc_pk_hex": "903fab42070622c551b188c983ce05a31febcab300244daf7d752aba2173e786", - "last_committed_height": 265, - "status": 1 + "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", + "btc_pk_hex": "d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63", + "description": { + "moniker": "my-name" + }, + "last_vote_height": 1 + "status": "REGISTERED" } ] } diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 47879a03..585e9daf 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -27,10 +27,16 @@ func NewEOTSManagerGRpcClient(remoteAddr string) (*EOTSManagerGRpcClient, error) return nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) } - return &EOTSManagerGRpcClient{ + gClient := &EOTSManagerGRpcClient{ client: proto.NewEOTSManagerClient(conn), conn: conn, - }, nil + } + + if err := gClient.Ping(); err != nil { + return nil, fmt.Errorf("the EOTS manager server is not responding: %w", err) + } + + return gClient, nil } func (c *EOTSManagerGRpcClient) Ping() error { diff --git a/eotsmanager/cmd/eotsd/flags.go b/eotsmanager/cmd/eotsd/flags.go index 6a3ede77..5f0b2033 100644 --- a/eotsmanager/cmd/eotsd/flags.go +++ b/eotsmanager/cmd/eotsd/flags.go @@ -1,6 +1,7 @@ package main const ( - homeFlag = "home" - forceFlag = "force" + homeFlag = "home" + forceFlag = "force" + rpcListenerFlag = "rpc-listener" ) diff --git a/eotsmanager/cmd/eotsd/init.go b/eotsmanager/cmd/eotsd/init.go index 757083c6..faf0389a 100644 --- a/eotsmanager/cmd/eotsd/init.go +++ b/eotsmanager/cmd/eotsd/init.go @@ -2,16 +2,18 @@ package main import ( "fmt" - eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" - "github.com/babylonchain/finality-provider/util" + "path/filepath" + "github.com/jessevdk/go-flags" "github.com/urfave/cli" - "path/filepath" + + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/util" ) var initCommand = cli.Command{ Name: "init", - Usage: "Initialize eotsd home directory.", + Usage: "Initialize the eotsd home directory.", Flags: []cli.Flag{ cli.StringFlag{ Name: homeFlag, diff --git a/eotsmanager/cmd/eotsd/start.go b/eotsmanager/cmd/eotsd/start.go index 702f571f..b8abf061 100644 --- a/eotsmanager/cmd/eotsd/start.go +++ b/eotsmanager/cmd/eotsd/start.go @@ -2,26 +2,33 @@ package main import ( "fmt" + "net" + "path/filepath" + + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + "github.com/babylonchain/finality-provider/eotsmanager" "github.com/babylonchain/finality-provider/eotsmanager/config" eotsservice "github.com/babylonchain/finality-provider/eotsmanager/service" "github.com/babylonchain/finality-provider/log" "github.com/babylonchain/finality-provider/util" - "github.com/lightningnetwork/lnd/signal" - "github.com/urfave/cli" - "path/filepath" ) var startCommand = cli.Command{ Name: "start", - Usage: "eotsd start", + Usage: "Start the Extractable One Time Signature Daemon.", Description: "Start the Extractable One Time Signature Daemon.", Flags: []cli.Flag{ cli.StringFlag{ Name: homeFlag, - Usage: "The path to the eots home directory", + Usage: "The path to the eotsd home directory", Value: config.DefaultEOTSDir, }, + cli.StringFlag{ + Name: rpcListenerFlag, + Usage: "The address that the RPC server listens to", + }, }, Action: startFn, } @@ -38,6 +45,15 @@ func startFn(ctx *cli.Context) error { return fmt.Errorf("failed to load config at %s: %w", homePath, err) } + rpcListener := ctx.String(rpcListenerFlag) + if rpcListener != "" { + _, err := net.ResolveTCPAddr("tcp", rpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", rpcListener, err) + } + cfg.RpcListener = rpcListener + } + logger, err := log.NewRootLoggerWithFile(config.LogFile(homePath), cfg.LogLevel) if err != nil { return fmt.Errorf("failed to load the logger") diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index f7ae10aa..a6ed128d 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -2,14 +2,16 @@ package config import ( "fmt" - "github.com/babylonchain/finality-provider/config" - "github.com/babylonchain/finality-provider/util" - "github.com/btcsuite/btcd/btcutil" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/jessevdk/go-flags" "net" "path/filepath" "strconv" + + "github.com/btcsuite/btcd/btcutil" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/jessevdk/go-flags" + + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/util" ) const ( @@ -30,7 +32,7 @@ var ( // ~/Library/Application Support/Eotsd on MacOS DefaultEOTSDir = btcutil.AppDataDir("eotsd", false) - defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) + defaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) ) type Config struct { @@ -39,7 +41,7 @@ type Config struct { DatabaseConfig *config.DatabaseConfig - RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` } // LoadConfig initializes and parses the config using a config file and command diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index 8acdaccc..10f23103 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "strconv" "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" @@ -15,50 +14,19 @@ import ( dc "github.com/babylonchain/finality-provider/finality-provider/service/client" ) -const ( - fpdDaemonAddressFlag = "daemon-address" - keyNameFlag = "key-name" - homeFlag = "home" - fpBTCPkFlag = "btc-pk" - blockHeightFlag = "height" - appHashFlag = "app-hash" - passphraseFlag = "passphrase" - hdPathFlag = "hd-path" - chainIdFlag = "chain-id" - defaultPassphrase = "" - defaultHdPath = "" - - // flags for description - monikerFlag = "moniker" - identityFlag = "identity" - websiteFlag = "website" - securityContractFlag = "security-contract" - detailsFlag = "details" - - commissionRateFlag = "commission" -) - var ( - defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) - defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" + defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" ) var getDaemonInfoCmd = cli.Command{ Name: "get-info", ShortName: "gi", Usage: "Get information of the running daemon.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, - }, - Action: getInfo, + Action: getInfo, } func getInfo(ctx *cli.Context) error { - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -81,11 +49,6 @@ var createFpDaemonCmd = cli.Command{ ShortName: "cfp", Usage: "Create a finality provider object and save it in database.", Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, cli.StringFlag{ Name: keyNameFlag, Usage: "The unique name of the finality provider key", @@ -145,7 +108,7 @@ var createFpDaemonCmd = cli.Command{ } func createFpDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) if err != nil { @@ -215,18 +178,11 @@ var lsFpDaemonCmd = cli.Command{ Name: "list-finality-providers", ShortName: "ls", Usage: "List finality providers stored in the database.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, - }, - Action: lsFpDaemon, + Action: lsFpDaemon, } func lsFpDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -248,11 +204,6 @@ var fpInfoDaemonCmd = cli.Command{ ShortName: "fpi", Usage: "Show the information of the finality provider.", Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, cli.StringFlag{ Name: fpBTCPkFlag, Usage: "The hex string of the BTC public key", @@ -263,7 +214,7 @@ var fpInfoDaemonCmd = cli.Command{ } func fpInfoDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -291,11 +242,6 @@ var registerFpDaemonCmd = cli.Command{ Usage: "Register a created finality provider to Babylon.", UsageText: fmt.Sprintf("register-finality-provider --%s [btc-pk]", fpBTCPkFlag), Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, cli.StringFlag{ Name: fpBTCPkFlag, Usage: "The hex string of the finality provider BTC public key", @@ -317,7 +263,7 @@ func registerFp(ctx *cli.Context) error { return fmt.Errorf("invalid BTC public key: %w", err) } - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -342,11 +288,6 @@ var addFinalitySigDaemonCmd = cli.Command{ Usage: "Send a finality signature to the consumer chain. This command should only be used for presentation/testing purposes", UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", fpBTCPkFlag), Flags: []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "Full address of the finality provider daemon in format tcp://:", - Value: defaultFpdDaemonAddress, - }, cli.StringFlag{ Name: fpBTCPkFlag, Usage: "The hex string of the BTC public key", @@ -367,7 +308,7 @@ var addFinalitySigDaemonCmd = cli.Command{ } func addFinalitySig(ctx *cli.Context) error { - daemonAddress := ctx.String(fpdDaemonAddressFlag) + daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err diff --git a/finality-provider/cmd/fpcli/flags.go b/finality-provider/cmd/fpcli/flags.go new file mode 100644 index 00000000..81170016 --- /dev/null +++ b/finality-provider/cmd/fpcli/flags.go @@ -0,0 +1,23 @@ +package main + +const ( + fpdDaemonAddressFlag = "daemon-address" + keyNameFlag = "key-name" + homeFlag = "home" + fpBTCPkFlag = "btc-pk" + blockHeightFlag = "height" + appHashFlag = "app-hash" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + defaultPassphrase = "" + defaultHdPath = "" + + // flags for description + monikerFlag = "moniker" + identityFlag = "identity" + websiteFlag = "website" + securityContractFlag = "security-contract" + detailsFlag = "details" + commissionRateFlag = "commission" +) diff --git a/finality-provider/cmd/fpcli/main.go b/finality-provider/cmd/fpcli/main.go index 906f1d96..fbc0141f 100644 --- a/finality-provider/cmd/fpcli/main.go +++ b/finality-provider/cmd/fpcli/main.go @@ -3,12 +3,18 @@ package main import ( "encoding/json" "fmt" - "github.com/babylonchain/finality-provider/config" "os" + "strconv" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/urfave/cli" ) +var ( + defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) +) + func fatal(err error) { fmt.Fprintf(os.Stderr, "[fpd] %v\n", err) os.Exit(1) @@ -24,25 +30,15 @@ func printRespJSON(resp interface{}) { fmt.Printf("%s\n", jsonBytes) } -const ( - dbTypeFlag = "db-type" - dbNameFlag = "db-name" -) - func main() { app := cli.NewApp() app.Name = "fpcli" app.Usage = "Control plane for the Finality Provider Daemon (fpd)." app.Flags = []cli.Flag{ cli.StringFlag{ - Name: dbTypeFlag, - Usage: "The type of the database", - Value: config.DefaultBackend, - }, - cli.StringFlag{ - Name: dbNameFlag, - Usage: "The name of the database bucket", - Value: config.DefaultDBName, + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, }, } diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/flags.go index 886f434b..0a942a35 100644 --- a/finality-provider/cmd/fpd/flags.go +++ b/finality-provider/cmd/fpd/flags.go @@ -12,6 +12,7 @@ const ( hdPathFlag = "hd-path" chainIdFlag = "chain-id" keyringBackendFlag = "keyring-backend" + rpcListenerFlag = "rpc-listener" defaultKeyringBackend = keyring.BackendTest defaultHdPath = "" diff --git a/finality-provider/cmd/fpd/init.go b/finality-provider/cmd/fpd/init.go index b9cc999f..6216eef7 100644 --- a/finality-provider/cmd/fpd/init.go +++ b/finality-provider/cmd/fpd/init.go @@ -13,7 +13,7 @@ import ( var initCommand = cli.Command{ Name: "init", - Usage: "Initialize a finality-provider home directory", + Usage: "Initialize a finality-provider home directory.", Flags: []cli.Flag{ cli.StringFlag{ Name: homeFlag, diff --git a/finality-provider/cmd/fpd/keys.go b/finality-provider/cmd/fpd/keys.go index 7cf82a1e..989a9729 100644 --- a/finality-provider/cmd/fpd/keys.go +++ b/finality-provider/cmd/fpd/keys.go @@ -20,8 +20,8 @@ type KeyOutput struct { var keysCommands = []cli.Command{ { Name: "keys", - Usage: "Command sets of managing keys for interacting the consumer chain.", - Category: "Daemon commands", + Usage: "Command sets of managing keys for interacting with the consumer chain.", + Category: "Key management", Subcommands: []cli.Command{ addKeyCmd, }, @@ -30,7 +30,7 @@ var keysCommands = []cli.Command{ var addKeyCmd = cli.Command{ Name: "add", - Usage: "Add a key to the consumer chain's keyring. This will change the config file in place", + Usage: "Add a key to the consumer chain's keyring. Note that this will change the config file in place.", Flags: []cli.Flag{ cli.StringFlag{ Name: homeFlag, diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go index ef46afbe..934df27b 100644 --- a/finality-provider/cmd/fpd/start.go +++ b/finality-provider/cmd/fpd/start.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "net" "path/filepath" "github.com/babylonchain/babylon/types" @@ -17,7 +18,7 @@ import ( var startCommand = cli.Command{ Name: "start", - Usage: "fpd start", + Usage: "Start the finality-provider app", Description: "Start the finality-provider app. Note that eotsd should be started beforehand", Flags: []cli.Flag{ cli.StringFlag{ @@ -38,6 +39,10 @@ var startCommand = cli.Command{ Name: fpPkFlag, Usage: "The public key of the finality-provider to start", }, + cli.StringFlag{ + Name: rpcListenerFlag, + Usage: "The address that the RPC server listens to", + }, }, Action: start, } @@ -48,8 +53,10 @@ func start(ctx *cli.Context) error { return err } homePath = util.CleanAndExpandPath(homePath) + passphrase := ctx.String(passphraseFlag) fpPkStr := ctx.String(fpPkFlag) + rpcListener := ctx.String(rpcListenerFlag) all := ctx.Bool(allFlag) cfg, err := fpcfg.LoadConfig(homePath) @@ -57,6 +64,14 @@ func start(ctx *cli.Context) error { return fmt.Errorf("failed to load configuration: %w", err) } + if rpcListener != "" { + _, err := net.ResolveTCPAddr("tcp", rpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", rpcListener, err) + } + cfg.RpcListener = rpcListener + } + logger, err := log.NewRootLoggerWithFile(fpcfg.LogFile(homePath), cfg.LogLevel) if err != nil { return fmt.Errorf("failed to initialize the logger") diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index dc8fd540..8f4a26f2 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -51,7 +51,7 @@ var ( defaultBTCNetParams = chaincfg.SimNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) - defaultRpcListener = "localhost:" + strconv.Itoa(DefaultRPCPort) + DefaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) ) // Config is the main config for the fpd cli command @@ -83,7 +83,7 @@ type Config struct { BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` - RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., localhost:1234"` + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` } func DefaultConfigWithHome(homePath string) Config { @@ -112,7 +112,7 @@ func DefaultConfigWithHome(homePath string) Config { BitcoinNetwork: defaultBitcoinNetwork, BTCNetParams: defaultBTCNetParams, EOTSManagerAddress: defaultEOTSManagerAddress, - RpcListener: defaultRpcListener, + RpcListener: DefaultRpcListener, MaxNumFinalityProviders: defaultMaxNumFinalityProviders, } diff --git a/finality-provider/proto/buf.lock b/finality-provider/proto/buf.lock index 7a2810e6..bdb2a63a 100644 --- a/finality-provider/proto/buf.lock +++ b/finality-provider/proto/buf.lock @@ -9,8 +9,8 @@ deps: - remote: buf.build owner: cosmos repository: cosmos-sdk - commit: 954f7b05f38440fc8250134b15adec47 - digest: shake256:2ab4404fd04a7d1d52df0e2d0f2d477a3d83ffd88d876957bf3fedfd702c8e52833d65b3ce1d89a3c5adf2aab512616b0e4f51d8463f07eda9a8a3317ee3ac54 + commit: 5a6ab7bc14314acaa912d5e53aef1c2f + digest: shake256:02c00c73493720055f9b57553a35b5550023a3c1914123b247956288a78fb913aff70e66552777ae14d759467e119079d484af081264a5dd607a94d9fbc8116b - remote: buf.build owner: cosmos repository: gogo-proto diff --git a/finality-provider/proto/buf.yaml b/finality-provider/proto/buf.yaml index 0e7c3e91..baa1a86c 100644 --- a/finality-provider/proto/buf.yaml +++ b/finality-provider/proto/buf.yaml @@ -1,7 +1,7 @@ version: v1 name: buf.build/babylonchain/btc-finality-provider deps: - - buf.build/cosmos/cosmos-sdk:v0.47.0 + - buf.build/cosmos/cosmos-sdk:v0.50.0 - buf.build/cosmos/cosmos-proto:1935555c206d4afb9e94615dfd0fad31 - buf.build/googleapis/googleapis:8d7204855ec14631a499bd7393ce1970 - buf.build/cosmos/gogo-proto:a14993478f40695898ed8a86931094b6656e8a5d diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index 3a4f1646..e5edb7f9 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -72,7 +72,7 @@ func NewFinalityProviderAppFromConfig( if err != nil { return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) } - // TODO add retry mechanism and ping to ensure the EOTS manager daemon is healthy + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) return NewFinalityProviderApp(homePath, config, cc, em, logger) From 34a9ad5141d43b7c8454e5e1c61f0688bda38f69 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 5 Jan 2024 14:14:28 +0800 Subject: [PATCH 43/66] chore: Bump Babylon version and add unbonding time validation (#190) --- clientcontroller/babylon.go | 1 + covenant/covenant.go | 23 ++++++++++++++----- finality-provider/cmd/fpcli/daemoncmd.go | 6 ++--- finality-provider/service/client/rpcclient.go | 4 ++-- go.mod | 4 ++-- go.sum | 8 +++---- itest/e2e_test.go | 4 +++- testutil/datagen.go | 2 +- tools/go.mod | 4 ++-- tools/go.sum | 8 +++---- types/params.go | 13 +++++++++++ 11 files changed, 52 insertions(+), 25 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 5d66d0c0..daa79c6d 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -128,6 +128,7 @@ func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) SlashingAddress: slashingAddress, CovenantQuorum: stakingParamRes.Params.CovenantQuorum, SlashingRate: stakingParamRes.Params.SlashingRate, + MinUnbondingTime: stakingParamRes.Params.MinUnbondingTime, }, nil } diff --git a/covenant/covenant.go b/covenant/covenant.go index de0d8e2a..a9e5fa93 100644 --- a/covenant/covenant.go +++ b/covenant/covenant.go @@ -124,7 +124,18 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, nil } - // 2. check staking tx and slashing tx are valid + // 2. check unbonding time (staking time from unbonding tx) is larger than min unbonding time + // which is larger value from: + // - MinUnbondingTime + // - CheckpointFinalizationTimeout + unbondingTime := btcDel.BtcUndelegation.UnbondingTime + minUnbondingTime := ce.params.MinUnbondingTime + if unbondingTime <= minUnbondingTime { + return nil, fmt.Errorf("unbonding time %d must be larger than %d", + unbondingTime, minUnbondingTime) + } + + // 3. check staking tx and slashing tx are valid stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.StakingTxHex) if err != nil { return nil, err @@ -152,7 +163,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, fmt.Errorf("invalid txs in the delegation: %w", err) } - // 3. Check unbonding transaction + // 4. Check unbonding transaction unbondingSlashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err @@ -189,7 +200,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) } - // 4. sign covenant staking sigs + // 5. sign covenant staking sigs covenantPrivKey, err := ce.getPrivKey() if err != nil { return nil, fmt.Errorf("failed to get Covenant private key: %w", err) @@ -232,7 +243,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add covSigs = append(covSigs, covenantSig.MustMarshal()) } - // 5. sign covenant unbonding sig + // 6. sign covenant unbonding sig stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() if err != nil { return nil, err @@ -248,7 +259,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) } - // 6. sign covenant unbonding slashing sig + // 7. sign covenant unbonding slashing sig slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) if err != nil { return nil, err @@ -278,7 +289,7 @@ func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*Add covSlashingSigs = append(covSlashingSigs, covenantSig.MustMarshal()) } - // 7. submit covenant sigs + // 8. submit covenant sigs res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs, covenantUnbondingSignature, covSlashingSigs) if err != nil { diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index 10f23103..bf71fcd7 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -2,11 +2,11 @@ package main import ( "context" + "encoding/hex" "fmt" "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" - "github.com/babylonchain/babylon/x/checkpointing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/urfave/cli" @@ -320,13 +320,13 @@ func addFinalitySig(ctx *cli.Context) error { return err } - lch, err := types.NewAppHashFromHex(ctx.String(appHashFlag)) + appHash, err := hex.DecodeString(ctx.String(appHashFlag)) if err != nil { return err } res, err := rpcClient.AddFinalitySignature( - context.Background(), fpPk.MarshalHex(), ctx.Uint64(blockHeightFlag), lch) + context.Background(), fpPk.MarshalHex(), ctx.Uint64(blockHeightFlag), appHash) if err != nil { return err } diff --git a/finality-provider/service/client/rpcclient.go b/finality-provider/service/client/rpcclient.go index afd68858..13e2677e 100644 --- a/finality-provider/service/client/rpcclient.go +++ b/finality-provider/service/client/rpcclient.go @@ -86,11 +86,11 @@ func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider( return res, nil } -func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature(ctx context.Context, fpPk string, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { +func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature(ctx context.Context, fpPk string, height uint64, appHash []byte) (*proto.AddFinalitySignatureResponse, error) { req := &proto.AddFinalitySignatureRequest{ BtcPk: fpPk, Height: height, - AppHash: lch, + AppHash: appHash, } res, err := c.client.AddFinalitySignature(ctx, req) diff --git a/go.mod b/go.mod index 3763a9de..9f01999e 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // 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.1 // indirect + github.com/cometbft/cometbft v0.38.2 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect @@ -238,7 +238,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 5ce19912..3fa65613 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,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-private v0.0.0-20231213105136-11792cad8a84 h1:fFlLF+rl6Buwb3eYgIoUQ4JkYdNMMTk9ihoznTTw2hk= -github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= +github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 h1:PhcQKkrFX2F+NJHgzQUquLAB3hjvZ5ojEnilf/lZycI= +github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a h1:IwntCUOlcsczQfl4P72ckqGf09coMdM42LvAG1aM+mg= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a/go.mod h1:dnUVCa5yHq2giiSpBpXx7W3CbJuuMabvQi3hG81AAtM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -377,8 +377,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.1 h1:hflfGk/VrPapfHco3rgCqn2YpOglAqJshSdyrM2zSLk= -github.com/cometbft/cometbft v0.38.1/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= +github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= +github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 493bdf0c..150d6eda 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/babylonchain/babylon/testutil/datagen" "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" @@ -86,7 +88,7 @@ func TestDoubleSigning(t *testing.T) { r := rand.New(rand.NewSource(time.Now().UnixNano())) b := &types.BlockInfo{ Height: finalizedBlocks[0].Height, - Hash: datagen.GenRandomAppHash(r), + Hash: datagen.GenRandomByteArray(r, 32), } _, extractedKey, err := fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) diff --git a/testutil/datagen.go b/testutil/datagen.go index 36fefc06..91caa006 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -124,7 +124,7 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { for i := startHeight; i <= endHeight; i++ { b := &types.BlockInfo{ Height: i, - Hash: datagen.GenRandomAppHash(r), + Hash: datagen.GenRandomByteArray(r, 32), } blocks = append(blocks, b) } diff --git a/tools/go.mod b/tools/go.mod index 5cc29ef9..c7260602 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -56,7 +56,7 @@ require ( github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // 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.0 // indirect + github.com/cometbft/cometbft v0.38.2 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.0 // indirect @@ -212,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index 52d832dd..389fcbb9 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84 h1:fFlLF+rl6Buwb3eYgIoUQ4JkYdNMMTk9ihoznTTw2hk= -github.com/babylonchain/babylon-private v0.0.0-20231213105136-11792cad8a84/go.mod h1:6wqL7SJBWltXMNXgFsvavB1bR5Fft0yChfRLamBtrAY= +github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 h1:PhcQKkrFX2F+NJHgzQUquLAB3hjvZ5ojEnilf/lZycI= +github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= 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= @@ -368,8 +368,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.0 h1:ogKnpiPX7gxCvqTEF4ly25/wAxUqf181t30P3vqdpdc= -github.com/cometbft/cometbft v0.38.0/go.mod h1:5Jz0Z8YsHSf0ZaAqGvi/ifioSdVFPtEGrm8Y9T/993k= +github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= +github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= diff --git a/types/params.go b/types/params.go index 44294200..4c71c227 100644 --- a/types/params.go +++ b/types/params.go @@ -26,4 +26,17 @@ type StakingParams struct { // The staked amount to be slashed, expressed as a decimal (e.g., 0.5 for 50%). SlashingRate sdkmath.LegacyDec + + // The minimum time for unbonding transaction timelock in BTC blocks + MinUnbondingTime uint32 +} + +// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from: +// - MinUnbondingTime +// - CheckpointFinalizationTimeout +func (p *StakingParams) MinimumUnbondingTime() uint64 { + return sdkmath.Max[uint64]( + uint64(p.MinUnbondingTime), + p.FinalizationTimeoutBlocks, + ) } From bd05f3e3c33563f004b6792014a97abadae9412e Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 8 Jan 2024 20:52:55 +0800 Subject: [PATCH 44/66] chore: Remove global flag (#198) --- finality-provider/cmd/fpcli/daemoncmd.go | 46 ++++++++++++++++++++---- finality-provider/cmd/fpcli/main.go | 7 ---- itest/e2e_test.go | 2 -- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go index bf71fcd7..f058764a 100644 --- a/finality-provider/cmd/fpcli/daemoncmd.go +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -23,10 +23,17 @@ var getDaemonInfoCmd = cli.Command{ ShortName: "gi", Usage: "Get information of the running daemon.", Action: getInfo, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + }, } func getInfo(ctx *cli.Context) error { - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -49,6 +56,11 @@ var createFpDaemonCmd = cli.Command{ ShortName: "cfp", Usage: "Create a finality provider object and save it in database.", Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, cli.StringFlag{ Name: keyNameFlag, Usage: "The unique name of the finality provider key", @@ -108,7 +120,7 @@ var createFpDaemonCmd = cli.Command{ } func createFpDaemon(ctx *cli.Context) error { - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) if err != nil { @@ -179,10 +191,17 @@ var lsFpDaemonCmd = cli.Command{ ShortName: "ls", Usage: "List finality providers stored in the database.", Action: lsFpDaemon, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + }, } func lsFpDaemon(ctx *cli.Context) error { - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -204,6 +223,11 @@ var fpInfoDaemonCmd = cli.Command{ ShortName: "fpi", Usage: "Show the information of the finality provider.", 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", @@ -214,7 +238,7 @@ var fpInfoDaemonCmd = cli.Command{ } func fpInfoDaemon(ctx *cli.Context) error { - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -242,6 +266,11 @@ var registerFpDaemonCmd = cli.Command{ Usage: "Register a created finality provider to Babylon.", UsageText: fmt.Sprintf("register-finality-provider --%s [btc-pk]", fpBTCPkFlag), 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 finality provider BTC public key", @@ -263,7 +292,7 @@ func registerFp(ctx *cli.Context) error { return fmt.Errorf("invalid BTC public key: %w", err) } - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -288,6 +317,11 @@ var addFinalitySigDaemonCmd = cli.Command{ Usage: "Send a finality signature to the consumer chain. This command should only be used for presentation/testing purposes", UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", fpBTCPkFlag), 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", @@ -308,7 +342,7 @@ var addFinalitySigDaemonCmd = cli.Command{ } func addFinalitySig(ctx *cli.Context) error { - daemonAddress := ctx.GlobalString(fpdDaemonAddressFlag) + daemonAddress := ctx.String(fpdDaemonAddressFlag) rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err diff --git a/finality-provider/cmd/fpcli/main.go b/finality-provider/cmd/fpcli/main.go index fbc0141f..b3a7acb2 100644 --- a/finality-provider/cmd/fpcli/main.go +++ b/finality-provider/cmd/fpcli/main.go @@ -34,13 +34,6 @@ func main() { app := cli.NewApp() app.Name = "fpcli" app.Usage = "Control plane for the Finality Provider Daemon (fpd)." - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: fpdDaemonAddressFlag, - Usage: "The RPC server address of fpd", - Value: defaultFpdDaemonAddress, - }, - } app.Commands = append(app.Commands, getDaemonInfoCmd, diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 150d6eda..222a3561 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -8,8 +8,6 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/babylonchain/babylon/testutil/datagen" "github.com/btcsuite/btcd/btcec/v2" "github.com/stretchr/testify/require" From 1ed601a8d53fedce06ac5f57c7d2d0540b631e63 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 9 Jan 2024 09:39:17 +0800 Subject: [PATCH 45/66] chore: Remove covenant legacy (#195) --- Dockerfile | 1 - clientcontroller/babylon.go | 272 ----------- clientcontroller/interface.go | 27 +- covenant/cmd/covd/flags.go | 18 - covenant/cmd/covd/init.go | 56 --- covenant/cmd/covd/key.go | 96 ---- covenant/cmd/covd/main.go | 24 - covenant/cmd/covd/start.go | 77 ---- covenant/config/config.go | 133 ------ covenant/covenant.go | 431 ------------------ covenant/covenant_test.go | 188 -------- covenant/service/server.go | 59 --- covenant/types.go | 5 - finality-provider/cmd/fpcli/main.go | 4 +- finality-provider/cmd/fpd/start.go | 5 +- finality-provider/config/config.go | 4 +- finality-provider/service/app.go | 9 +- finality-provider/service/app_test.go | 4 +- finality-provider/service/fastsync_test.go | 6 +- finality-provider/service/fp_instance_test.go | 4 +- finality-provider/service/fp_manager_test.go | 1 + go.mod | 3 +- go.sum | 6 +- itest/e2e_test.go | 2 +- itest/test_manager.go | 100 ++-- testutil/datagen.go | 35 -- testutil/mocks/babylon.go | 301 ------------ testutil/utils.go | 3 +- tools/go.mod | 2 +- tools/go.sum | 4 +- types/delegation.go | 102 ----- types/params.go | 42 -- 32 files changed, 89 insertions(+), 1935 deletions(-) delete mode 100644 covenant/cmd/covd/flags.go delete mode 100644 covenant/cmd/covd/init.go delete mode 100644 covenant/cmd/covd/key.go delete mode 100644 covenant/cmd/covd/main.go delete mode 100644 covenant/cmd/covd/start.go delete mode 100644 covenant/config/config.go delete mode 100644 covenant/covenant.go delete mode 100644 covenant/covenant_test.go delete mode 100644 covenant/service/server.go delete mode 100644 covenant/types.go delete mode 100644 types/delegation.go delete mode 100644 types/params.go diff --git a/Dockerfile b/Dockerfile index 6e0efcde..db458b66 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,6 @@ RUN apk add bash curl jq COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpd /bin/fpd COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpcli /bin/fpcli -COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/covd /bin/covd COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/eotsd /bin/eotsd WORKDIR /home/finality-provider diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index daa79c6d..5c8aad08 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -2,7 +2,6 @@ package clientcontroller import ( "context" - "encoding/hex" "fmt" "time" @@ -16,7 +15,6 @@ import ( 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/btcutil" "github.com/btcsuite/btcd/chaincfg" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -94,44 +92,6 @@ func (bc *BabylonController) GetKeyAddress() sdk.AccAddress { return addr } -func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) { - // query btc checkpoint params - ckptParamRes, err := bc.bbnClient.QueryClient.BTCCheckpointParams() - if err != nil { - return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err) - } - - // query btc staking params - stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParams() - if err != nil { - return nil, fmt.Errorf("failed to query staking params: %v", err) - } - - covenantPks := make([]*btcec.PublicKey, 0, len(stakingParamRes.Params.CovenantPks)) - for _, pk := range stakingParamRes.Params.CovenantPks { - covPk, err := pk.ToBTCPK() - if err != nil { - return nil, fmt.Errorf("invalid covenant public key") - } - covenantPks = append(covenantPks, covPk) - } - slashingAddress, err := btcutil.DecodeAddress(stakingParamRes.Params.SlashingAddress, bc.btcParams) - if err != nil { - return nil, err - } - - return &types.StakingParams{ - ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, - FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, - MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), - CovenantPks: covenantPks, - SlashingAddress: slashingAddress, - CovenantQuorum: stakingParamRes.Params.CovenantQuorum, - SlashingRate: stakingParamRes.Params.SlashingRate, - MinUnbondingTime: stakingParamRes.Params.MinUnbondingTime, - }, nil -} - func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxResponse, error) { return bc.reliablySendMsgs([]sdk.Msg{msg}) } @@ -213,34 +173,6 @@ func (bc *BabylonController) CommitPubRandList( return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -// SubmitCovenantSigs submits the Covenant signature via a MsgAddCovenantSig to Babylon if the daemon runs in Covenant mode -// it returns tx hash and error -func (bc *BabylonController) SubmitCovenantSigs( - covPk *btcec.PublicKey, - stakingTxHash string, - slashingSigs [][]byte, - unbondingSig *schnorr.Signature, - unbondingSlashingSigs [][]byte, -) (*types.TxResponse, error) { - bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) - - msg := &btcstakingtypes.MsgAddCovenantSigs{ - Signer: bc.mustGetTxSigner(), - Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), - StakingTxHash: stakingTxHash, - SlashingTxSigs: slashingSigs, - UnbondingTxSig: bip340UnbondingSig, - SlashingUnbondingTxSigs: unbondingSlashingSigs, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err - } - - return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil -} - // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon func (bc *BabylonController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { msg := &finalitytypes.MsgAddFinalitySig{ @@ -285,31 +217,6 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, bloc return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { - return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) -} - -// queryDelegationsWithStatus queries BTC delegations that need a Covenant signature -// 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) ([]*types.Delegation, error) { - pagination := &sdkquery.PageRequest{ - Limit: limit, - } - - res, err := bc.bbnClient.QueryClient.BTCDelegations(status, pagination) - if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %v", err) - } - - dels := make([]*types.Delegation, 0, len(res.BtcDelegations)) - for _, d := range res.BtcDelegations { - dels = append(dels, ConvertDelegationType(d)) - } - - return dels, nil -} - func (bc *BabylonController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { ctx, cancel := getContextWithCancel(bc.cfg.Timeout) defer cancel() @@ -330,75 +237,6 @@ func (bc *BabylonController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) return slashed, nil } -func (bc *BabylonController) getNDelegations( - fpBtcPk *bbntypes.BIP340PubKey, - startKey []byte, - n uint64, -) ([]*types.Delegation, []byte, error) { - pagination := &sdkquery.PageRequest{ - Key: startKey, - Limit: n, - } - - res, err := bc.bbnClient.QueryClient.FinalityProviderDelegations(fpBtcPk.MarshalHex(), pagination) - - if err != nil { - return nil, nil, fmt.Errorf("failed to query BTC delegations: %v", err) - } - - var delegations []*types.Delegation - - for _, dels := range res.BtcDelegatorDelegations { - for _, d := range dels.Dels { - delegations = append(delegations, ConvertDelegationType(d)) - } - } - - var nextKey []byte - - if res.Pagination != nil && res.Pagination.NextKey != nil { - nextKey = res.Pagination.NextKey - } - - return delegations, nextKey, nil -} - -func (bc *BabylonController) getNFinalityProviderDelegationsMatchingCriteria( - fpBtcPk *bbntypes.BIP340PubKey, - n uint64, - match func(*types.Delegation) bool, -) ([]*types.Delegation, error) { - batchSize := 100 - var delegations []*types.Delegation - var startKey []byte - - for { - dels, nextKey, err := bc.getNDelegations(fpBtcPk, startKey, uint64(batchSize)) - if err != nil { - return nil, err - } - - for _, del := range dels { - if match(del) { - delegations = append(delegations, del) - } - } - - if len(delegations) >= int(n) || len(nextKey) == 0 { - break - } - - startKey = nextKey - } - - if len(delegations) > int(n) { - // only return requested number of delegations - return delegations[:n], nil - } else { - return delegations, nil - } -} - // QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height func (bc *BabylonController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { res, err := bc.bbnClient.QueryClient.FinalityProviderPowerAtHeight( @@ -558,106 +396,6 @@ func (bc *BabylonController) Close() error { return bc.bbnClient.Stop() } -func ConvertDelegationType(del *btcstakingtypes.BTCDelegation) *types.Delegation { - var ( - stakingTxHex string - slashingTxHex string - covenantSigs []*types.CovenantAdaptorSigInfo - undelegation *types.Undelegation - ) - - if del.StakingTx == nil { - panic(fmt.Errorf("staking tx should not be empty in delegation")) - } - - if del.SlashingTx == nil { - panic(fmt.Errorf("slashing tx should not be empty in delegation")) - } - - stakingTxHex = hex.EncodeToString(del.StakingTx) - - slashingTxHex = del.SlashingTx.ToHexStr() - - for _, s := range del.CovenantSigs { - covSigInfo := &types.CovenantAdaptorSigInfo{ - Pk: s.CovPk.MustToBTCPK(), - Sigs: s.AdaptorSigs, - } - covenantSigs = append(covenantSigs, covSigInfo) - } - - if del.BtcUndelegation != nil { - undelegation = ConvertUndelegationType(del.BtcUndelegation) - } - - fpBtcPks := make([]*btcec.PublicKey, 0, len(del.FpBtcPkList)) - for _, fp := range del.FpBtcPkList { - fpBtcPks = append(fpBtcPks, fp.MustToBTCPK()) - } - - return &types.Delegation{ - BtcPk: del.BtcPk.MustToBTCPK(), - FpBtcPks: fpBtcPks, - TotalSat: del.TotalSat, - StartHeight: del.StartHeight, - EndHeight: del.EndHeight, - StakingTxHex: stakingTxHex, - SlashingTxHex: slashingTxHex, - CovenantSigs: covenantSigs, - BtcUndelegation: undelegation, - } -} - -func ConvertUndelegationType(undel *btcstakingtypes.BTCUndelegation) *types.Undelegation { - var ( - unbondingTxHex string - slashingTxHex string - covenantSlashingSigs []*types.CovenantAdaptorSigInfo - covenantUnbondingSigs []*types.CovenantSchnorrSigInfo - ) - - if undel.UnbondingTx == nil { - panic(fmt.Errorf("staking tx should not be empty in undelegation")) - } - - if undel.SlashingTx == nil { - panic(fmt.Errorf("slashing tx should not be empty in undelegation")) - } - - unbondingTxHex = hex.EncodeToString(undel.UnbondingTx) - - slashingTxHex = undel.SlashingTx.ToHexStr() - - for _, unbondingSig := range undel.CovenantUnbondingSigList { - sig, err := unbondingSig.Sig.ToBTCSig() - if err != nil { - panic(err) - } - sigInfo := &types.CovenantSchnorrSigInfo{ - Pk: unbondingSig.Pk.MustToBTCPK(), - Sig: sig, - } - covenantUnbondingSigs = append(covenantUnbondingSigs, sigInfo) - } - - for _, s := range undel.CovenantSlashingSigs { - covSigInfo := &types.CovenantAdaptorSigInfo{ - Pk: s.CovPk.MustToBTCPK(), - Sigs: s.AdaptorSigs, - } - covenantSlashingSigs = append(covenantSlashingSigs, covSigInfo) - } - - return &types.Undelegation{ - UnbondingTxHex: unbondingTxHex, - SlashingTxHex: slashingTxHex, - CovenantSlashingSigs: covenantSlashingSigs, - CovenantUnbondingSigs: covenantUnbondingSigs, - UnbondingTime: undel.UnbondingTime, - DelegatorUnbondingSig: undel.DelegatorUnbondingSig, - } -} - // Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) CreateBTCDelegation( delBabylonPk *secp256k1.PubKey, @@ -773,16 +511,6 @@ func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo return res.Header, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryFinalityProviderDelegations(fpBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*types.Delegation, error) { - return bc.getNFinalityProviderDelegationsMatchingCriteria( - fpBtcPk, - max, - // fitlering function which always returns true as we want all delegations - func(*types.Delegation) bool { return true }, - ) -} - // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { ctx, cancel := getContextWithCancel(bc.cfg.Timeout) diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 54fc2bda..10d7fb2e 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -4,11 +4,10 @@ import ( "fmt" "cosmossdk.io/math" - "github.com/btcsuite/btcd/chaincfg" - "go.uber.org/zap" - "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" "github.com/babylonchain/finality-provider/types" @@ -19,17 +18,7 @@ const ( ) type ClientController interface { - FinalityProviderAPIs - - CovenantAPIs - - QueryStakingParams() (*types.StakingParams, error) - Close() error -} - -// FinalityProviderAPIs contains interfaces needed when the program is running in the finality provider mode -type FinalityProviderAPIs interface { // RegisterFinalityProvider registers a finality provider to the consumer chain // it returns tx hash and error RegisterFinalityProvider( @@ -76,18 +65,8 @@ type FinalityProviderAPIs interface { // QueryActivatedHeight returns the activated height of the consumer chain // error will be returned if the consumer chain has not been activated QueryActivatedHeight() (uint64, error) -} -// CovenantAPIs contains interfaces needed when the program is running in the covenant mode -type CovenantAPIs interface { - // SubmitCovenantSigs submits Covenant signatures to the consumer chain, each corresponding to - // a finality provider that the delegation is (re-)staked to - // it returns tx hash and error - SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, - sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) - - // QueryPendingDelegations queries BTC delegations that are in status of pending - QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) + Close() error } func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { diff --git a/covenant/cmd/covd/flags.go b/covenant/cmd/covd/flags.go deleted file mode 100644 index 58bea109..00000000 --- a/covenant/cmd/covd/flags.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import "github.com/cosmos/cosmos-sdk/crypto/keyring" - -const ( - homeFlag = "home" - forceFlag = "force" - keyNameFlag = "key-name" - passphraseFlag = "passphrase" - hdPathFlag = "hd-path" - chainIdFlag = "chain-id" - keyringBackendFlag = "keyring-backend" - - defaultChainID = "chain-test" - defaultKeyringBackend = keyring.BackendTest - defaultPassphrase = "" - defaultHdPath = "" -) diff --git a/covenant/cmd/covd/init.go b/covenant/cmd/covd/init.go deleted file mode 100644 index 830a95b0..00000000 --- a/covenant/cmd/covd/init.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "fmt" - covcfg "github.com/babylonchain/finality-provider/covenant/config" - "github.com/babylonchain/finality-provider/util" - "github.com/jessevdk/go-flags" - "github.com/urfave/cli" - "path/filepath" -) - -var initCommand = cli.Command{ - Name: "init", - Usage: "Initialize a covenant home directory.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: homeFlag, - Usage: "Path to where the home directory will be initialized", - Value: covcfg.DefaultCovenantDir, - }, - cli.BoolFlag{ - Name: forceFlag, - Usage: "Override existing configuration", - Required: false, - }, - }, - Action: initHome, -} - -func initHome(c *cli.Context) error { - homePath, err := filepath.Abs(c.String(homeFlag)) - if err != nil { - return err - } - // ensure the directory exists - homePath = util.CleanAndExpandPath(homePath) - force := c.Bool(forceFlag) - - if util.FileExists(homePath) && !force { - return fmt.Errorf("home path %s already exists", homePath) - } - - if err := util.MakeDirectory(homePath); err != nil { - return err - } - // Create log directory - logDir := covcfg.LogDir(homePath) - if err := util.MakeDirectory(logDir); err != nil { - return err - } - - defaultConfig := covcfg.DefaultConfigWithHomePath(homePath) - fileParser := flags.NewParser(&defaultConfig, flags.Default) - - return flags.NewIniParser(fileParser).WriteFile(covcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) -} diff --git a/covenant/cmd/covd/key.go b/covenant/cmd/covd/key.go deleted file mode 100644 index baefe391..00000000 --- a/covenant/cmd/covd/key.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "github.com/babylonchain/babylon/types" - "github.com/babylonchain/finality-provider/covenant" - covcfg "github.com/babylonchain/finality-provider/covenant/config" - "github.com/urfave/cli" -) - -type covenantKey struct { - Name string `json:"name"` - PublicKey string `json:"public-key"` -} - -var createKeyCommand = cli.Command{ - Name: "create-key", - ShortName: "ck", - Usage: "Create a Covenant account in the keyring.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: chainIdFlag, - Usage: "The chainID of the consumer chain", - Value: defaultChainID, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the Covenant key", - 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: "Select keyring's backend", - Value: defaultKeyringBackend, - }, - cli.StringFlag{ - Name: homeFlag, - Usage: "The home directory for the covenant", - Value: covcfg.DefaultCovenantDir, - }, - }, - Action: createKey, -} - -func createKey(ctx *cli.Context) error { - homePath := ctx.String(homeFlag) - chainID := ctx.String(chainIdFlag) - keyName := ctx.String(keyNameFlag) - backend := ctx.String(keyringBackendFlag) - passphrase := ctx.String(passphraseFlag) - hdPath := ctx.String(hdPathFlag) - - keyPair, err := covenant.CreateCovenantKey( - homePath, - chainID, - keyName, - backend, - passphrase, - hdPath, - ) - - if err != nil { - return fmt.Errorf("failed to create covenant key: %w", err) - } - - bip340Key := types.NewBIP340PubKeyFromBTCPK(keyPair.PublicKey) - printRespJSON( - &covenantKey{ - Name: ctx.String(keyNameFlag), - PublicKey: bip340Key.MarshalHex(), - }, - ) - - return err -} - -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/covenant/cmd/covd/main.go b/covenant/cmd/covd/main.go deleted file mode 100644 index d14fce5f..00000000 --- a/covenant/cmd/covd/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/urfave/cli" -) - -func fatal(err error) { - fmt.Fprintf(os.Stderr, "[covd] %v\n", err) - os.Exit(1) -} - -func main() { - app := cli.NewApp() - app.Name = "covd" - app.Usage = "Covenant Emulator Daemon (covd)." - app.Commands = append(app.Commands, startCommand, initCommand, createKeyCommand) - - if err := app.Run(os.Args); err != nil { - fatal(err) - } -} diff --git a/covenant/cmd/covd/start.go b/covenant/cmd/covd/start.go deleted file mode 100644 index 31e8e577..00000000 --- a/covenant/cmd/covd/start.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "fmt" - "github.com/babylonchain/finality-provider/eotsmanager/config" - "github.com/babylonchain/finality-provider/log" - "github.com/babylonchain/finality-provider/util" - "path/filepath" - - "github.com/lightningnetwork/lnd/signal" - "github.com/urfave/cli" - - "github.com/babylonchain/finality-provider/clientcontroller" - "github.com/babylonchain/finality-provider/covenant" - covcfg "github.com/babylonchain/finality-provider/covenant/config" - covsrv "github.com/babylonchain/finality-provider/covenant/service" -) - -var startCommand = cli.Command{ - Name: "start", - Usage: "covd start", - Description: "Start the Covenant Emulator Daemon. Note that the Covenant should be created beforehand", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: passphraseFlag, - Usage: "The pass phrase used to encrypt the keys", - Value: defaultPassphrase, - }, - cli.StringFlag{ - Name: homeFlag, - Usage: "The path to the covenant home directory", - Value: covcfg.DefaultCovenantDir, - }, - }, - Action: start, -} - -func start(ctx *cli.Context) error { - homePath, err := filepath.Abs(ctx.String(homeFlag)) - if err != nil { - return err - } - homePath = util.CleanAndExpandPath(homePath) - - cfg, err := covcfg.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") - } - - bbnClient, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) - if err != nil { - return fmt.Errorf("failed to create rpc client for the consumer chain: %w", err) - } - - ce, err := covenant.NewCovenantEmulator(cfg, bbnClient, ctx.String(passphraseFlag), logger) - if err != nil { - return fmt.Errorf("failed to start the covenant emulator: %w", err) - } - - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - return err - } - - srv := covsrv.NewCovenantServer(logger, ce, shutdownInterceptor) - if err != nil { - return fmt.Errorf("failed to create covenant server: %w", err) - } - - return srv.RunUntilShutdown() -} diff --git a/covenant/config/config.go b/covenant/config/config.go deleted file mode 100644 index b918e158..00000000 --- a/covenant/config/config.go +++ /dev/null @@ -1,133 +0,0 @@ -package config - -import ( - "fmt" - "github.com/babylonchain/finality-provider/util" - "path/filepath" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/jessevdk/go-flags" - - "github.com/babylonchain/finality-provider/config" -) - -const ( - defaultLogLevel = "debug" - defaultLogFilename = "covd.log" - defaultConfigFileName = "covd.conf" - defaultCovenantKeyName = "covenant-key" - defaultQueryInterval = 15 * time.Second - defaultDelegationLimit = uint64(100) - defaultBitcoinNetwork = "simnet" - defaultLogDirname = "logs" -) - -var ( - // DefaultCovenantDir specifies the default home directory for the covenant: - // C:\Users\\AppData\Local\ on Windows - // ~/.covd on Linux - // ~/Library/Application Support/Covd on MacOS - DefaultCovenantDir = btcutil.AppDataDir("covd", false) - - defaultBTCNetParams = chaincfg.SimNetParams -) - -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"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` - DelegationLimit uint64 `long:"delegationlimit" description:"The maximum number of delegations that the Covenant processes each time"` - BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` - - BTCNetParams chaincfg.Params - - BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` -} - -// LoadConfig initializes and parses the config using a config file and command -// line options. -// -// The configuration proceeds as follows: -// 1. Start with a default config with sane settings -// 2. Pre-parse the command line to check for an alternative config file -// 3. Load configuration file overwriting defaults with any specified options -// 4. Parse CLI options and overwrite/add any specified options -func LoadConfig(homePath string) (*Config, error) { - // The home directory is required to have a configuration file with a specific name - // under it. - cfgFile := ConfigFile(homePath) - if !util.FileExists(cfgFile) { - return nil, fmt.Errorf("specified config file does "+ - "not exist in %s", cfgFile) - } - - // If there are issues parsing the config file, return an error - var cfg Config - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(cfgFile) - if err != nil { - return nil, err - } - - // Make sure everything we just loaded makes sense. - if err := cfg.Validate(); err != nil { - return nil, err - } - - return &cfg, nil -} - -// Validate check the given configuration to be sane. This makes sure no -// illegal values or combination of values are set. All file system paths are -// normalized. The cleaned up config is returned on success. -func (cfg *Config) Validate() error { - switch cfg.BitcoinNetwork { - case "mainnet": - cfg.BTCNetParams = chaincfg.MainNetParams - case "testnet": - cfg.BTCNetParams = chaincfg.TestNet3Params - case "regtest": - cfg.BTCNetParams = chaincfg.RegressionNetParams - case "simnet": - cfg.BTCNetParams = chaincfg.SimNetParams - case "signet": - cfg.BTCNetParams = chaincfg.SigNetParams - default: - return fmt.Errorf("unsupported Bitcoin network: %s", cfg.BitcoinNetwork) - } - - return nil -} - -func ConfigFile(homePath string) string { - return filepath.Join(homePath, defaultConfigFileName) -} - -func LogDir(homePath string) string { - return filepath.Join(homePath, defaultLogDirname) -} - -func DefaultConfigWithHomePath(homePath string) Config { - bbnCfg := config.DefaultBBNConfig() - bbnCfg.Key = defaultCovenantKeyName - bbnCfg.KeyDirectory = homePath - cfg := Config{ - LogLevel: defaultLogLevel, - QueryInterval: defaultQueryInterval, - DelegationLimit: defaultDelegationLimit, - BitcoinNetwork: defaultBitcoinNetwork, - BTCNetParams: defaultBTCNetParams, - BabylonConfig: &bbnCfg, - } - - if err := cfg.Validate(); err != nil { - panic(err) - } - - return cfg -} - -func DefaultConfig() Config { - return DefaultConfigWithHomePath(DefaultCovenantDir) -} diff --git a/covenant/covenant.go b/covenant/covenant.go deleted file mode 100644 index a9e5fa93..00000000 --- a/covenant/covenant.go +++ /dev/null @@ -1,431 +0,0 @@ -package covenant - -import ( - "fmt" - "strings" - "sync" - "time" - - "github.com/avast/retry-go/v4" - "github.com/btcsuite/btcd/btcec/v2" - - "go.uber.org/zap" - - "github.com/babylonchain/finality-provider/keyring" - - "github.com/babylonchain/babylon/btcstaking" - asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" - bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcutil" - - "github.com/babylonchain/finality-provider/clientcontroller" - covcfg "github.com/babylonchain/finality-provider/covenant/config" - "github.com/babylonchain/finality-provider/types" -) - -var ( - // TODO: Maybe configurable? - RtyAttNum = uint(5) - RtyAtt = retry.Attempts(RtyAttNum) - RtyDel = retry.Delay(time.Millisecond * 400) - RtyErr = retry.LastErrorOnly(true) -) - -type CovenantEmulator struct { - startOnce sync.Once - stopOnce sync.Once - - wg sync.WaitGroup - quit chan struct{} - - pk *btcec.PublicKey - - cc clientcontroller.ClientController - kc *keyring.ChainKeyringController - - config *covcfg.Config - params *types.StakingParams - logger *zap.Logger - - // input is used to pass passphrase to the keyring - input *strings.Reader - passphrase string -} - -func NewCovenantEmulator( - config *covcfg.Config, - cc clientcontroller.ClientController, - passphrase string, - logger *zap.Logger, -) (*CovenantEmulator, error) { - input := strings.NewReader("") - kr, err := keyring.CreateKeyring( - config.BabylonConfig.KeyDirectory, - config.BabylonConfig.ChainID, - config.BabylonConfig.KeyringBackend, - input, - ) - if err != nil { - return nil, fmt.Errorf("failed to create keyring: %w", err) - } - - kc, err := keyring.NewChainKeyringControllerWithKeyring(kr, config.BabylonConfig.Key, input) - if err != nil { - return nil, err - } - - sk, err := kc.GetChainPrivKey(passphrase) - if err != nil { - return nil, fmt.Errorf("covenant key %s is not found: %w", config.BabylonConfig.Key, err) - } - - pk, err := btcec.ParsePubKey(sk.PubKey().Bytes()) - if err != nil { - return nil, err - } - - return &CovenantEmulator{ - cc: cc, - kc: kc, - config: config, - logger: logger, - input: input, - passphrase: passphrase, - pk: pk, - quit: make(chan struct{}), - }, nil -} - -func (ce *CovenantEmulator) UpdateParams() error { - params, err := ce.getParamsWithRetry() - if err != nil { - return err - } - ce.params = params - - return nil -} - -// AddCovenantSignature adds a Covenant signature on the given Bitcoin delegation and submits it to Babylon -// TODO: break this function into smaller components -func (ce *CovenantEmulator) AddCovenantSignature(btcDel *types.Delegation) (*AddCovenantSigResponse, error) { - // 0. nil checks - if btcDel == nil { - return nil, fmt.Errorf("empty delegation") - } - - if btcDel.BtcUndelegation == nil { - return nil, fmt.Errorf("empty undelegation") - } - - // 1. the quorum is already achieved, skip sending more sigs - if btcDel.HasCovenantQuorum(ce.params.CovenantQuorum) { - return nil, nil - } - - // 2. check unbonding time (staking time from unbonding tx) is larger than min unbonding time - // which is larger value from: - // - MinUnbondingTime - // - CheckpointFinalizationTimeout - unbondingTime := btcDel.BtcUndelegation.UnbondingTime - minUnbondingTime := ce.params.MinUnbondingTime - if unbondingTime <= minUnbondingTime { - return nil, fmt.Errorf("unbonding time %d must be larger than %d", - unbondingTime, minUnbondingTime) - } - - // 3. check staking tx and slashing tx are valid - stakingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.StakingTxHex) - if err != nil { - return nil, err - } - - slashingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.SlashingTxHex) - if err != nil { - return nil, err - } - - slashingMsgTx, err := slashingTx.ToMsgTx() - if err != nil { - return nil, err - } - - if err := btcstaking.CheckTransactions( - slashingMsgTx, - stakingMsgTx, - btcDel.StakingOutputIdx, - int64(ce.params.MinSlashingTxFeeSat), - ce.params.SlashingRate, - ce.params.SlashingAddress, - &ce.config.BTCNetParams, - ); err != nil { - return nil, fmt.Errorf("invalid txs in the delegation: %w", err) - } - - // 4. Check unbonding transaction - unbondingSlashingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) - if err != nil { - return nil, err - } - - unbondingMsgTx, _, err := bbntypes.NewBTCTxFromHex(btcDel.BtcUndelegation.UnbondingTxHex) - if err != nil { - return nil, err - } - - unbondingInfo, err := btcstaking.BuildUnbondingInfo( - btcDel.BtcPk, - btcDel.FpBtcPks, - ce.params.CovenantPks, - ce.params.CovenantQuorum, - uint16(btcDel.BtcUndelegation.UnbondingTime), - btcutil.Amount(unbondingMsgTx.TxOut[0].Value), - &ce.config.BTCNetParams, - ) - if err != nil { - return nil, err - } - - err = btcstaking.CheckTransactions( - unbondingSlashingMsgTx, - unbondingMsgTx, - 0, - int64(ce.params.MinSlashingTxFeeSat), - ce.params.SlashingRate, - ce.params.SlashingAddress, - &ce.config.BTCNetParams, - ) - if err != nil { - return nil, fmt.Errorf("invalid txs in the undelegation: %w", err) - } - - // 5. sign covenant staking sigs - covenantPrivKey, err := ce.getPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Covenant private key: %w", err) - } - - stakingInfo, err := btcstaking.BuildStakingInfo( - btcDel.BtcPk, - btcDel.FpBtcPks, - ce.params.CovenantPks, - ce.params.CovenantQuorum, - btcDel.GetStakingTime(), - btcutil.Amount(btcDel.TotalSat), - &ce.config.BTCNetParams, - ) - if err != nil { - return nil, err - } - - slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() - if err != nil { - return nil, err - } - - covSigs := make([][]byte, 0, len(btcDel.FpBtcPks)) - for _, valPk := range btcDel.FpBtcPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(valPk) - if err != nil { - return nil, err - } - covenantSig, err := slashingTx.EncSign( - stakingMsgTx, - btcDel.StakingOutputIdx, - slashingPathInfo.GetPkScriptPath(), - covenantPrivKey, - encKey, - ) - if err != nil { - return nil, err - } - covSigs = append(covSigs, covenantSig.MustMarshal()) - } - - // 6. sign covenant unbonding sig - stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() - if err != nil { - return nil, err - } - covenantUnbondingSignature, err := btcstaking.SignTxWithOneScriptSpendInputStrict( - unbondingMsgTx, - stakingMsgTx, - btcDel.StakingOutputIdx, - stakingTxUnbondingPathInfo.GetPkScriptPath(), - covenantPrivKey, - ) - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - // 7. sign covenant unbonding slashing sig - slashUnbondingTx, err := bstypes.NewBTCSlashingTxFromHex(btcDel.BtcUndelegation.SlashingTxHex) - if err != nil { - return nil, err - } - - unbondingTxSlashingPath, err := unbondingInfo.SlashingPathSpendInfo() - if err != nil { - return nil, err - } - - covSlashingSigs := make([][]byte, 0, len(btcDel.FpBtcPks)) - for _, fpPk := range btcDel.FpBtcPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) - if err != nil { - return nil, err - } - covenantSig, err := slashUnbondingTx.EncSign( - unbondingMsgTx, - 0, // 0th output is always the unbonding script output - unbondingTxSlashingPath.GetPkScriptPath(), - covenantPrivKey, - encKey, - ) - if err != nil { - return nil, err - } - covSlashingSigs = append(covSlashingSigs, covenantSig.MustMarshal()) - } - - // 8. submit covenant sigs - res, err := ce.cc.SubmitCovenantSigs(ce.pk, stakingMsgTx.TxHash().String(), covSigs, covenantUnbondingSignature, covSlashingSigs) - - if err != nil { - return nil, err - } - - return &AddCovenantSigResponse{TxHash: res.TxHash}, nil -} - -func (ce *CovenantEmulator) getPrivKey() (*btcec.PrivateKey, error) { - sdkPrivKey, err := ce.kc.GetChainPrivKey(ce.passphrase) - if err != nil { - return nil, err - } - - privKey, _ := btcec.PrivKeyFromBytes(sdkPrivKey.Key) - - return privKey, nil -} - -// covenantSigSubmissionLoop is the reactor to submit Covenant signature for BTC delegations -func (ce *CovenantEmulator) covenantSigSubmissionLoop() { - defer ce.wg.Done() - - interval := ce.config.QueryInterval - limit := ce.config.DelegationLimit - covenantSigTicker := time.NewTicker(interval) - - for { - select { - case <-covenantSigTicker.C: - // 0. Update slashing address in case it is changed upon governance proposal - if err := ce.UpdateParams(); err != nil { - ce.logger.Debug("failed to get staking params", zap.Error(err)) - continue - } - - // 1. Get all pending delegations - dels, err := ce.cc.QueryPendingDelegations(limit) - if err != nil { - ce.logger.Debug("failed to get pending delegations", zap.Error(err)) - continue - } - if len(dels) == 0 { - ce.logger.Debug("no pending delegations are found") - } - - for _, d := range dels { - _, err := ce.AddCovenantSignature(d) - if err != nil { - delPkHex := bbntypes.NewBIP340PubKeyFromBTCPK(d.BtcPk).MarshalHex() - ce.logger.Error( - "failed to submit covenant signatures to the BTC delegation", - zap.String("del_btc_pk", delPkHex), - zap.Error(err), - ) - } - } - - case <-ce.quit: - ce.logger.Debug("exiting covenant signature submission loop") - return - } - } - -} - -func CreateCovenantKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.ChainKeyInfo, error) { - sdkCtx, err := keyring.CreateClientCtx( - keyringDir, chainID, - ) - if err != nil { - return nil, err - } - - krController, err := keyring.NewChainKeyringController( - sdkCtx, - keyName, - backend, - ) - if err != nil { - return nil, err - } - - return krController.CreateChainKey(passphrase, hdPath) -} - -func (ce *CovenantEmulator) getParamsWithRetry() (*types.StakingParams, error) { - var ( - params *types.StakingParams - err error - ) - - if err := retry.Do(func() error { - params, err = ce.cc.QueryStakingParams() - if err != nil { - return err - } - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - ce.logger.Debug( - "failed to query the consumer chain for the staking params", - zap.Uint("attempt", n+1), - zap.Uint("max_attempts", RtyAttNum), - zap.Error(err), - ) - })); err != nil { - return nil, err - } - - return params, nil -} - -func (ce *CovenantEmulator) Start() error { - var startErr error - ce.startOnce.Do(func() { - ce.logger.Info("Starting Covenant Emulator") - - ce.wg.Add(1) - go ce.covenantSigSubmissionLoop() - }) - - return startErr -} - -func (ce *CovenantEmulator) Stop() error { - var stopErr error - ce.stopOnce.Do(func() { - ce.logger.Info("Stopping Covenant Emulator") - - // Always stop the submission loop first to not generate additional events and actions - ce.logger.Debug("Stopping submission loop") - close(ce.quit) - ce.wg.Wait() - - ce.logger.Debug("Covenant Emulator successfully stopped") - }) - return stopErr -} diff --git a/covenant/covenant_test.go b/covenant/covenant_test.go deleted file mode 100644 index 9a5f954a..00000000 --- a/covenant/covenant_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package covenant_test - -import ( - "encoding/hex" - "math/rand" - "testing" - - "github.com/babylonchain/babylon/btcstaking" - asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" - "github.com/babylonchain/babylon/testutil/datagen" - bbntypes "github.com/babylonchain/babylon/types" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/wire" - "github.com/stretchr/testify/require" - "go.uber.org/zap" - - "github.com/babylonchain/finality-provider/covenant" - covcfg "github.com/babylonchain/finality-provider/covenant/config" - "github.com/babylonchain/finality-provider/testutil" - "github.com/babylonchain/finality-provider/types" -) - -const ( - passphrase = "testpass" - hdPath = "" -) - -var net = &chaincfg.SimNetParams - -func FuzzAddCovenantSig(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - params := testutil.GenRandomParams(r, t) - randomStartingHeight := uint64(r.Int63n(100) + 1) - finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) - currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight, params) - - // create a Covenant key pair in the keyring - covenantConfig := covcfg.DefaultConfig() - covKeyPair, err := covenant.CreateCovenantKey( - covenantConfig.BabylonConfig.KeyDirectory, - covenantConfig.BabylonConfig.ChainID, - covenantConfig.BabylonConfig.Key, - covenantConfig.BabylonConfig.KeyringBackend, - passphrase, - hdPath, - ) - require.NoError(t, err) - - // create and start covenant emulator - ce, err := covenant.NewCovenantEmulator(&covenantConfig, mockClientController, passphrase, zap.NewNop()) - require.NoError(t, err) - - err = ce.UpdateParams() - require.NoError(t, err) - - // generate BTC delegation - changeAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - stakingTimeBlocks := uint16(5) - stakingValue := int64(2 * 10e8) - fpNum := datagen.RandomInt(r, 5) + 1 - fpPks := testutil.GenBtcPublicKeys(r, t, int(fpNum)) - testInfo := datagen.GenBTCStakingSlashingInfo( - r, - t, - net, - delSK, - fpPks, - params.CovenantPks, - params.CovenantQuorum, - stakingTimeBlocks, - stakingValue, - params.SlashingAddress.String(), - changeAddr.String(), - params.SlashingRate, - ) - stakingTxBytes, err := bbntypes.SerializeBTCTx(testInfo.StakingTx) - require.NoError(t, err) - startHeight := datagen.RandomInt(r, 1000) + 100 - btcDel := &types.Delegation{ - BtcPk: delPK, - FpBtcPks: fpPks, - StartHeight: startHeight, // not relevant here - EndHeight: startHeight + uint64(stakingTimeBlocks), - TotalSat: uint64(stakingValue), - StakingTxHex: hex.EncodeToString(stakingTxBytes), - StakingOutputIdx: 0, - SlashingTxHex: testInfo.SlashingTx.ToHexStr(), - } - // generate covenant staking sigs - slashingSpendInfo, err := testInfo.StakingInfo.SlashingPathSpendInfo() - require.NoError(t, err) - covSigs := make([][]byte, 0, len(fpPks)) - for _, fpPk := range fpPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) - require.NoError(t, err) - covenantSig, err := testInfo.SlashingTx.EncSign( - testInfo.StakingTx, - 0, - slashingSpendInfo.GetPkScriptPath(), - covKeyPair.PrivateKey, encKey, - ) - require.NoError(t, err) - covSigs = append(covSigs, covenantSig.MustMarshal()) - } - - // generate undelegation - unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 - unbondingValue := int64(btcDel.TotalSat) - 1000 - - stakingTxHash := testInfo.StakingTx.TxHash() - testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( - r, - t, - net, - delSK, - btcDel.FpBtcPks, - params.CovenantPks, - params.CovenantQuorum, - wire.NewOutPoint(&stakingTxHash, 0), - unbondingTime, - unbondingValue, - params.SlashingAddress.String(), changeAddr.String(), - params.SlashingRate, - ) - require.NoError(t, err) - // random signer - unbondingTxMsg := testUnbondingInfo.UnbondingTx - - unbondingSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() - require.NoError(t, err) - - serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) - require.NoError(t, err) - undel := &types.Undelegation{ - UnbondingTxHex: hex.EncodeToString(serializedUnbondingTx), - UnbondingTime: uint32(unbondingTime), - SlashingTxHex: testUnbondingInfo.SlashingTx.ToHexStr(), - } - btcDel.BtcUndelegation = undel - stakingTxUnbondingPathInfo, err := testInfo.StakingInfo.UnbondingPathSpendInfo() - require.NoError(t, err) - // generate covenant unbonding sigs - unbondingCovSig, err := btcstaking.SignTxWithOneScriptSpendInputStrict( - unbondingTxMsg, - testInfo.StakingTx, - btcDel.StakingOutputIdx, - stakingTxUnbondingPathInfo.GetPkScriptPath(), - covKeyPair.PrivateKey, - ) - require.NoError(t, err) - // generate covenant unbonding slashing sigs - unbondingCovSlashingSigs := make([][]byte, 0, len(fpPks)) - for _, fpPk := range fpPks { - encKey, err := asig.NewEncryptionKeyFromBTCPK(fpPk) - require.NoError(t, err) - covenantSig, err := testUnbondingInfo.SlashingTx.EncSign( - testUnbondingInfo.UnbondingTx, - 0, - unbondingSlashingPathInfo.GetPkScriptPath(), - covKeyPair.PrivateKey, - encKey, - ) - require.NoError(t, err) - unbondingCovSlashingSigs = append(unbondingCovSlashingSigs, covenantSig.MustMarshal()) - } - - // check the sigs are expected - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().SubmitCovenantSigs( - covKeyPair.PublicKey, - testInfo.StakingTx.TxHash().String(), - covSigs, - unbondingCovSig, - unbondingCovSlashingSigs, - ). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := ce.AddCovenantSignature(btcDel) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - }) -} diff --git a/covenant/service/server.go b/covenant/service/server.go deleted file mode 100644 index a0d283c6..00000000 --- a/covenant/service/server.go +++ /dev/null @@ -1,59 +0,0 @@ -package service - -import ( - "fmt" - "sync/atomic" - - "github.com/lightningnetwork/lnd/signal" - "go.uber.org/zap" - - "github.com/babylonchain/finality-provider/covenant" -) - -// CovenantServer is the main daemon construct for the covenant emulator. -type CovenantServer struct { - started int32 - - ce *covenant.CovenantEmulator - - logger *zap.Logger - - interceptor signal.Interceptor - - quit chan struct{} -} - -// NewCovenantServer creates a new server with the given config. -func NewCovenantServer(l *zap.Logger, ce *covenant.CovenantEmulator, sig signal.Interceptor) *CovenantServer { - return &CovenantServer{ - logger: l, - ce: ce, - interceptor: sig, - quit: make(chan struct{}, 1), - } -} - -// RunUntilShutdown runs the main EOTS manager server loop until a signal is -// received to shut down the process. -func (s *CovenantServer) RunUntilShutdown() error { - if atomic.AddInt32(&s.started, 1) != 1 { - return nil - } - - defer func() { - _ = s.ce.Stop() - s.logger.Info("Shutdown covenant emulator server complete") - }() - - if err := s.ce.Start(); err != nil { - return fmt.Errorf("failed to start covenant emulator: %w", err) - } - - s.logger.Info("Covenant Emulator Daemon is fully active!") - - // Wait for shutdown signal from either a graceful server stop or from - // the interrupt handler. - <-s.interceptor.ShutdownChannel() - - return nil -} diff --git a/covenant/types.go b/covenant/types.go deleted file mode 100644 index 16d99d0f..00000000 --- a/covenant/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package covenant - -type AddCovenantSigResponse struct { - TxHash string -} diff --git a/finality-provider/cmd/fpcli/main.go b/finality-provider/cmd/fpcli/main.go index b3a7acb2..a4d84e9c 100644 --- a/finality-provider/cmd/fpcli/main.go +++ b/finality-provider/cmd/fpcli/main.go @@ -6,9 +6,9 @@ import ( "os" "strconv" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" - "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" ) var ( diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go index 934df27b..48f082c8 100644 --- a/finality-provider/cmd/fpd/start.go +++ b/finality-provider/cmd/fpd/start.go @@ -9,11 +9,10 @@ import ( "github.com/lightningnetwork/lnd/signal" "github.com/urfave/cli" - "github.com/babylonchain/finality-provider/log" - "github.com/babylonchain/finality-provider/util" - fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" ) var startCommand = cli.Command{ diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index 8f4a26f2..9f688b0e 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -7,15 +7,13 @@ import ( "strconv" "time" - "github.com/babylonchain/finality-provider/util" - "github.com/btcsuite/btcd/btcutil" "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/util" ) const ( diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index e5edb7f9..807e0675 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -6,9 +6,6 @@ import ( "strings" "sync" - "github.com/babylonchain/finality-provider/types" - "github.com/babylonchain/finality-provider/util" - sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" @@ -17,15 +14,15 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "go.uber.org/zap" - fpkr "github.com/babylonchain/finality-provider/keyring" - "github.com/babylonchain/finality-provider/clientcontroller" "github.com/babylonchain/finality-provider/eotsmanager" "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" + fpkr "github.com/babylonchain/finality-provider/keyring" + "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/util" ) type FinalityProviderApp struct { diff --git a/finality-provider/service/app_test.go b/finality-provider/service/app_test.go index 1852fcd9..192c1737 100644 --- a/finality-provider/service/app_test.go +++ b/finality-provider/service/app_test.go @@ -43,8 +43,10 @@ func FuzzRegisterFinalityProvider(f *testing.F) { // Create mocked babylon client randomStartingHeight := uint64(r.Int63n(100) + 1) currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), + gomock.Any()).Return(uint64(0), nil).AnyTimes() // Create randomized config fpHomeDir := filepath.Join(t.TempDir(), "fp-home") diff --git a/finality-provider/service/fastsync_test.go b/finality-provider/service/fastsync_test.go index a0ca1583..8cc1b46a 100644 --- a/finality-provider/service/fastsync_test.go +++ b/finality-provider/service/fastsync_test.go @@ -20,7 +20,7 @@ func FuzzFastSync(f *testing.F) { finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight, &types.StakingParams{}) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) @@ -31,11 +31,11 @@ func FuzzFastSync(f *testing.F) { mockClientController.EXPECT(). CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). + Return(uint64(1), nil).AnyTimes() res, err := fpIns.CommitPubRand(startingBlock) require.NoError(t, err) require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). - Return(uint64(1), nil).AnyTimes() // fast sync catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) diff --git a/finality-provider/service/fp_instance_test.go b/finality-provider/service/fp_instance_test.go index dc180f8b..d5ca76c6 100644 --- a/finality-provider/service/fp_instance_test.go +++ b/finality-provider/service/fp_instance_test.go @@ -26,7 +26,7 @@ func FuzzCommitPubRandList(f *testing.F) { 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, &types.StakingParams{}) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()). Return(uint64(0), nil).AnyTimes() @@ -53,7 +53,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { 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, &types.StakingParams{}) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() diff --git a/finality-provider/service/fp_manager_test.go b/finality-provider/service/fp_manager_test.go index ce57cf8f..511068bb 100644 --- a/finality-provider/service/fp_manager_test.go +++ b/finality-provider/service/fp_manager_test.go @@ -63,6 +63,7 @@ func FuzzStatusUpdate(f *testing.F) { votingPower := uint64(r.Intn(2)) mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() + mockClientController.EXPECT().SubmitFinalitySig(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.TxResponse{TxHash: ""}, nil).AnyTimes() var slashedHeight uint64 if votingPower == 0 { mockClientController.EXPECT().QueryFinalityProviderSlashed(gomock.Any()).Return(true, nil).AnyTimes() diff --git a/go.mod b/go.mod index 9f01999e..a94d7d8a 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 github.com/babylonchain/babylon v0.7.2 + github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee github.com/babylonchain/rpc-client v0.7.0 github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 @@ -238,7 +239,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 3fa65613..63eec27a 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,10 @@ 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-private v0.0.0-20231224153404-79decc6a6866 h1:PhcQKkrFX2F+NJHgzQUquLAB3hjvZ5ojEnilf/lZycI= -github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= +github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 h1:ysEA08WGHlMm2pIoXgTt1O9YAW4QjBQXg3TM0CSn21g= +github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= +github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee h1:hTtjwiz6ooQUmjubCqsbGmekzsASfoxoKoxIzVA/YQA= +github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee/go.mod h1:6be7+qVoskKQM9by8KoCNDIFx3qfImoLdGeBj98zCw8= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a h1:IwntCUOlcsczQfl4P72ckqGf09coMdM42LvAG1aM+mg= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a/go.mod h1:dnUVCa5yHq2giiSpBpXx7W3CbJuuMabvQi3hG81AAtM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 222a3561..eedadba6 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -172,7 +172,7 @@ func TestFastSync(t *testing.T) { t.Logf("the latest finalized block is at %v", finalizedHeight) // check if the fast sync works by checking if the gap is not more than 1 - currentHeaderRes, err := tm.BabylonClient.QueryBestBlock() + currentHeaderRes, err := tm.FPBBNClient.QueryBestBlock() currentHeight := currentHeaderRes.Height t.Logf("the current block is at %v", currentHeight) require.NoError(t, err) diff --git a/itest/test_manager.go b/itest/test_manager.go index 9c983781..7e15b211 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -10,14 +10,17 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec/v2" - sdkmath "cosmossdk.io/math" "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" + covcc "github.com/babylonchain/covenant-emulator/clientcontroller" + covcfg "github.com/babylonchain/covenant-emulator/config" + "github.com/babylonchain/covenant-emulator/covenant" + covtypes "github.com/babylonchain/covenant-emulator/types" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -26,9 +29,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" - "github.com/babylonchain/finality-provider/clientcontroller" - "github.com/babylonchain/finality-provider/covenant" - covcfg "github.com/babylonchain/finality-provider/covenant/config" + fpcc "github.com/babylonchain/finality-provider/clientcontroller" "github.com/babylonchain/finality-provider/eotsmanager/client" eotsconfig "github.com/babylonchain/finality-provider/eotsmanager/config" fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" @@ -59,7 +60,9 @@ type TestManager struct { CovenanConfig *covcfg.Config Fpa *service.FinalityProviderApp EOTSClient *client.EOTSManagerGRpcClient - BabylonClient *clientcontroller.BabylonController + FPBBNClient *fpcc.BabylonController + CovBBNClient *covcc.BabylonController + StakingParams *covtypes.StakingParams baseDir string } @@ -99,7 +102,7 @@ func StartManager(t *testing.T) *TestManager { require.NoError(t, err) fpHomeDir := filepath.Join(testDir, "fp-home") cfg := defaultFpConfig(bh.GetNodeDataDir(), fpHomeDir) - bc, err := clientcontroller.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) + bc, err := fpcc.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) require.NoError(t, err) // 3. prepare EOTS manager @@ -117,7 +120,10 @@ func StartManager(t *testing.T) *TestManager { require.NoError(t, err) // 5. prepare covenant emulator - ce, err := covenant.NewCovenantEmulator(covenantConfig, bc, passphrase, logger) + bbnCfg := defaultBBNConfigWithKey(cfg.BabylonConfig.Key, cfg.BabylonConfig.KeyDirectory) + covbc, err := covcc.NewBabylonController(bbnCfg, &covenantConfig.BTCNetParams, logger) + require.NoError(t, err) + ce, err := covenant.NewCovenantEmulator(covenantConfig, covbc, passphrase, logger) require.NoError(t, err) err = ce.Start() require.NoError(t, err) @@ -131,7 +137,8 @@ func StartManager(t *testing.T) *TestManager { CovenantEmulator: ce, CovenanConfig: covenantConfig, EOTSClient: eotsCli, - BabylonClient: bc, + FPBBNClient: bc, + CovBBNClient: covbc, baseDir: testDir, } @@ -143,9 +150,12 @@ func StartManager(t *testing.T) *TestManager { func (tm *TestManager) WaitForServicesStart(t *testing.T) { // wait for Babylon node starts require.Eventually(t, func() bool { - _, err := tm.BabylonClient.QueryStakingParams() - - return err == nil + params, err := tm.CovBBNClient.QueryStakingParams() + if err != nil { + return false + } + tm.StakingParams = params + return true }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("Babylon node is started") @@ -179,7 +189,7 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser // check finality providers on Babylon side require.Eventually(t, func() bool { - fps, err := tm.BabylonClient.QueryFinalityProviders() + fps, err := tm.FPBBNClient.QueryFinalityProviders() if err != nil { t.Logf("failed to query finality providers from Babylon %s", err.Error()) return false @@ -224,7 +234,7 @@ func (tm *TestManager) Stop(t *testing.T) { func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { require.Eventually(t, func() bool { - queriedFps, err := tm.BabylonClient.QueryFinalityProviders() + queriedFps, err := tm.FPBBNClient.QueryFinalityProviders() if err != nil { return false } @@ -246,13 +256,13 @@ func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.Fi t.Logf("public randomness is successfully committed") } -func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegation { +func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*covtypes.Delegation { var ( - dels []*types.Delegation + dels []*covtypes.Delegation err error ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryPendingDelegations( + dels, err = tm.CovBBNClient.QueryPendingDelegations( tm.CovenanConfig.DelegationLimit, ) if err != nil { @@ -266,14 +276,14 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*types.Delegat return dels } -func (tm *TestManager) WaitForFpNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*types.Delegation { - var dels []*types.Delegation - currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() +func (tm *TestManager) WaitForFpNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*covtypes.Delegation { + var dels []*covtypes.Delegation + currentBtcTip, err := tm.FPBBNClient.QueryBtcLightClientTip() require.NoError(t, err) - params, err := tm.BabylonClient.QueryStakingParams() + params, err := tm.CovBBNClient.QueryStakingParams() require.NoError(t, err) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryFinalityProviderDelegations(btcPk, 1000) + dels, err = tm.CovBBNClient.QueryFinalityProviderDelegations(btcPk, 1000) if err != nil { return false } @@ -286,7 +296,7 @@ func (tm *TestManager) WaitForFpNActiveDels(t *testing.T, btcPk *bbntypes.BIP340 return dels } -func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32, status bstypes.BTCDelegationStatus) bool { +func CheckDelsStatus(dels []*covtypes.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32, status bstypes.BTCDelegationStatus) bool { allChecked := true for _, d := range dels { s := getDelStatus(d, btcHeight, w, covenantQuorum) @@ -298,7 +308,7 @@ func CheckDelsStatus(dels []*types.Delegation, btcHeight uint64, w uint64, coven return allChecked } -func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32) bstypes.BTCDelegationStatus { +func getDelStatus(del *covtypes.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32) bstypes.BTCDelegationStatus { if del.BtcUndelegation.DelegatorUnbondingSig != nil { // this means the delegator has signed unbonding signature, and Babylon will consider // this BTC delegation unbonded directly @@ -324,7 +334,7 @@ func getDelStatus(del *types.Delegation, btcHeight uint64, w uint64, covenantQuo func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { // we need to ensure votes are collected at the given height require.Eventually(t, func() bool { - votes, err := tm.BabylonClient.QueryVotesAtHeight(height) + votes, err := tm.FPBBNClient.QueryVotesAtHeight(height) if err != nil { t.Logf("failed to get the votes at height %v: %s", height, err.Error()) return false @@ -334,7 +344,7 @@ func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num i // as the votes have been collected, the block should be finalized require.Eventually(t, func() bool { - b, err := tm.BabylonClient.QueryBlock(height) + b, err := tm.FPBBNClient.QueryBlock(height) if err != nil { t.Logf("failed to query block at height %v: %s", height, err.Error()) return false @@ -363,7 +373,7 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo err error ) require.Eventually(t, func() bool { - blocks, err = tm.BabylonClient.QueryLatestFinalizedBlocks(uint64(n)) + blocks, err = tm.FPBBNClient.QueryLatestFinalizedBlocks(uint64(n)) if err != nil { t.Logf("failed to get the latest finalized block: %s", err.Error()) return false @@ -377,13 +387,13 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo } func (tm *TestManager) StopAndRestartFpAfterNBlocks(t *testing.T, n int, fpIns *service.FinalityProviderInstance) { - blockBeforeStop, err := tm.BabylonClient.QueryBestBlock() + blockBeforeStop, err := tm.FPBBNClient.QueryBestBlock() require.NoError(t, err) err = fpIns.Stop() require.NoError(t, err) require.Eventually(t, func() bool { - headerAfterStop, err := tm.BabylonClient.QueryBestBlock() + headerAfterStop, err := tm.FPBBNClient.QueryBestBlock() if err != nil { return false } @@ -404,16 +414,14 @@ func (tm *TestManager) GetFpPrivKey(t *testing.T, fpPk []byte) *btcec.PrivateKey return record.PrivKey } -func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *types.StakingParams) *TestDelegationData { +func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *covtypes.StakingParams) *TestDelegationData { r := rand.New(rand.NewSource(time.Now().UnixNano())) // delegator BTC key pairs, staking tx and slashing tx delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) - changeAddress, err := datagen.GenRandomBTCAddress(r, btcNetworkParams) - require.NoError(t, err) - + unbondingTime := uint16(tm.StakingParams.MinimumUnbondingTime()) + 1 testStakingInfo := datagen.GenBTCStakingSlashingInfo( r, t, @@ -424,8 +432,9 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe params.CovenantQuorum, stakingTime, stakingAmount, - params.SlashingAddress.String(), changeAddress.String(), + params.SlashingAddress.String(), params.SlashingRate, + unbondingTime, ) // delegator Babylon key pairs @@ -437,7 +446,7 @@ 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.BabylonClient.QueryBtcLightClientTip() + currentBtcTip, err := tm.FPBBNClient.QueryBtcLightClientTip() require.NoError(t, err) blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), testStakingInfo.StakingTx) accumulatedWork := btclctypes.CalcWork(&blockWithStakingTx.HeaderBytes) @@ -455,7 +464,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe headers = append(headers, *headerInfo.Header) parentBlockHeaderInfo = headerInfo } - _, err = tm.BabylonClient.InsertBtcBlockHeaders(headers) + _, err = tm.FPBBNClient.InsertBtcBlockHeaders(headers) require.NoError(t, err) btcHeader := blockWithStakingTx.HeaderBytes serializedStakingTx, err := bbntypes.SerializeBTCTx(testStakingInfo.StakingTx) @@ -474,7 +483,6 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe ) require.NoError(t, err) - unbondingTime := uint16(params.FinalizationTimeoutBlocks) + 1 unbondingValue := stakingAmount - 1000 stakingTxHash := testStakingInfo.StakingTx.TxHash() @@ -490,8 +498,8 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe unbondingTime, unbondingValue, params.SlashingAddress.String(), - changeAddress.String(), params.SlashingRate, + unbondingTime, ) unbondingTxMsg := testUnbondingInfo.UnbondingTx @@ -511,7 +519,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe require.NoError(t, err) // submit the BTC delegation to Babylon - _, err = tm.BabylonClient.CreateBTCDelegation( + _, err = tm.FPBBNClient.CreateBTCDelegation( delBabylonPubKey.(*secp256k1.PubKey), bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), fpPks, @@ -541,14 +549,13 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe StakingTxInfo: txInfo, DelegatorSig: delegatorSig, SlashingAddr: params.SlashingAddress.String(), - ChangeAddr: changeAddress.String(), StakingTime: stakingTime, StakingAmount: stakingAmount, } } -func (tm *TestManager) GetParams(t *testing.T) *types.StakingParams { - p, err := tm.BabylonClient.QueryStakingParams() +func (tm *TestManager) GetParams(t *testing.T) *covtypes.StakingParams { + p, err := tm.CovBBNClient.QueryStakingParams() require.NoError(t, err) return p } @@ -569,6 +576,15 @@ func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { return &cfg } +func defaultBBNConfigWithKey(key, keydir string) *covcfg.BBNConfig { + bbnCfg := covcfg.DefaultBBNConfig() + bbnCfg.Key = key + bbnCfg.KeyDirectory = keydir + bbnCfg.GasAdjustment = 20 + + return &bbnCfg +} + func defaultCovenantConfig(homeDir string) *covcfg.Config { cfg := covcfg.DefaultConfigWithHomePath(homeDir) cfg.BabylonConfig.KeyDirectory = homeDir diff --git a/testutil/datagen.go b/testutil/datagen.go index 91caa006..f556bd3f 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -16,7 +16,6 @@ import ( "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" "github.com/stretchr/testify/require" @@ -85,40 +84,6 @@ func GenValidSlashingRate(r *rand.Rand) sdkmath.LegacyDec { return sdkmath.LegacyNewDecWithPrec(int64(datagen.RandomInt(r, 41)+10), 2) } -func GenRandomParams(r *rand.Rand, t *testing.T) *types.StakingParams { - covThreshold := datagen.RandomInt(r, 5) + 1 - covNum := covThreshold * 2 - covenantPks := make([]*btcec.PublicKey, 0, covNum) - for i := 0; i < int(covNum); i++ { - _, covPk, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - covenantPks = append(covenantPks, covPk) - } - - slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - return &types.StakingParams{ - ComfirmationTimeBlocks: 10, - FinalizationTimeoutBlocks: 100, - MinSlashingTxFeeSat: 1, - CovenantPks: covenantPks, - SlashingAddress: slashingAddr, - CovenantQuorum: uint32(covThreshold), - SlashingRate: GenValidSlashingRate(r), - } -} - -func GenBtcPublicKeys(r *rand.Rand, t *testing.T, num int) []*btcec.PublicKey { - pks := make([]*btcec.PublicKey, 0, num) - for i := 0; i < num; i++ { - _, covPk, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - pks = append(pks, covPk) - } - - return pks -} - func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { blocks := make([]*types.BlockInfo, 0) for i := startHeight; i <= endHeight; i++ { diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index aa7c58aa..ed45056e 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -186,36 +186,6 @@ func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count int return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockClientController)(nil).QueryLatestFinalizedBlocks), count) } -// QueryPendingDelegations mocks base method. -func (m *MockClientController) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryPendingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryPendingDelegations indicates an expected call of QueryPendingDelegations. -func (mr *MockClientControllerMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryPendingDelegations), limit) -} - -// QueryStakingParams mocks base method. -func (m *MockClientController) QueryStakingParams() (*types.StakingParams, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryStakingParams") - ret0, _ := ret[0].(*types.StakingParams) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryStakingParams indicates an expected call of QueryStakingParams. -func (mr *MockClientControllerMockRecorder) QueryStakingParams() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryStakingParams", reflect.TypeOf((*MockClientController)(nil).QueryStakingParams)) -} - // RegisterFinalityProvider mocks base method. func (m *MockClientController) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() @@ -246,21 +216,6 @@ func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(fpPk, blocks return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), fpPk, blocks, sigs) } -// SubmitCovenantSigs mocks base method. -func (m *MockClientController) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockClientControllerMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockClientController)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) -} - // SubmitFinalitySig mocks base method. func (m *MockClientController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() @@ -275,259 +230,3 @@ func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(fpPk, blockHeight, mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), fpPk, blockHeight, blockHash, sig) } - -// MockFinalityProviderAPIs is a mock of FinalityProviderAPIs interface. -type MockFinalityProviderAPIs struct { - ctrl *gomock.Controller - recorder *MockFinalityProviderAPIsMockRecorder -} - -// MockFinalityProviderAPIsMockRecorder is the mock recorder for MockFinalityProviderAPIs. -type MockFinalityProviderAPIsMockRecorder struct { - mock *MockFinalityProviderAPIs -} - -// NewMockFinalityProviderAPIs creates a new mock instance. -func NewMockFinalityProviderAPIs(ctrl *gomock.Controller) *MockFinalityProviderAPIs { - mock := &MockFinalityProviderAPIs{ctrl: ctrl} - mock.recorder = &MockFinalityProviderAPIsMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockFinalityProviderAPIs) EXPECT() *MockFinalityProviderAPIsMockRecorder { - return m.recorder -} - -// CommitPubRandList mocks base method. -func (m *MockFinalityProviderAPIs) 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 *MockFinalityProviderAPIsMockRecorder) CommitPubRandList(fpPk, startHeight, pubRandList, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).CommitPubRandList), fpPk, startHeight, pubRandList, sig) -} - -// QueryActivatedHeight mocks base method. -func (m *MockFinalityProviderAPIs) QueryActivatedHeight() (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryActivatedHeight") - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryActivatedHeight indicates an expected call of QueryActivatedHeight. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryActivatedHeight() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryActivatedHeight)) -} - -// QueryBestBlock mocks base method. -func (m *MockFinalityProviderAPIs) QueryBestBlock() (*types.BlockInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBestBlock") - ret0, _ := ret[0].(*types.BlockInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryBestBlock indicates an expected call of QueryBestBlock. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryBestBlock() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBestBlock)) -} - -// QueryBlock mocks base method. -func (m *MockFinalityProviderAPIs) QueryBlock(height uint64) (*types.BlockInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBlock", height) - ret0, _ := ret[0].(*types.BlockInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryBlock indicates an expected call of QueryBlock. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryBlock(height interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBlock), height) -} - -// QueryBlocks mocks base method. -func (m *MockFinalityProviderAPIs) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) - ret0, _ := ret[0].([]*types.BlockInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryBlocks indicates an expected call of QueryBlocks. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryBlocks(startHeight, endHeight, limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryBlocks), startHeight, endHeight, limit) -} - -// QueryFinalityProviderSlashed mocks base method. -func (m *MockFinalityProviderAPIs) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryFinalityProviderSlashed", fpPk) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryFinalityProviderSlashed indicates an expected call of QueryFinalityProviderSlashed. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryFinalityProviderSlashed(fpPk interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderSlashed", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryFinalityProviderSlashed), fpPk) -} - -// QueryFinalityProviderVotingPower mocks base method. -func (m *MockFinalityProviderAPIs) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryFinalityProviderVotingPower", fpPk, blockHeight) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryFinalityProviderVotingPower indicates an expected call of QueryFinalityProviderVotingPower. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryFinalityProviderVotingPower(fpPk, blockHeight interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) -} - -// QueryLastCommittedPublicRand mocks base method. -func (m *MockFinalityProviderAPIs) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLastCommittedPublicRand", fpPk, count) - ret0, _ := ret[0].(map[uint64]*btcec.FieldVal) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryLastCommittedPublicRand indicates an expected call of QueryLastCommittedPublicRand. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryLastCommittedPublicRand(fpPk, count interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastCommittedPublicRand", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryLastCommittedPublicRand), fpPk, count) -} - -// QueryLatestFinalizedBlocks mocks base method. -func (m *MockFinalityProviderAPIs) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) - ret0, _ := ret[0].([]*types.BlockInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. -func (mr *MockFinalityProviderAPIsMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).QueryLatestFinalizedBlocks), count) -} - -// RegisterFinalityProvider mocks base method. -func (m *MockFinalityProviderAPIs) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RegisterFinalityProvider indicates an expected call of RegisterFinalityProvider. -func (mr *MockFinalityProviderAPIsMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description) -} - -// SubmitBatchFinalitySigs mocks base method. -func (m *MockFinalityProviderAPIs) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", fpPk, blocks, sigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. -func (mr *MockFinalityProviderAPIsMockRecorder) SubmitBatchFinalitySigs(fpPk, blocks, sigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).SubmitBatchFinalitySigs), fpPk, blocks, sigs) -} - -// SubmitFinalitySig mocks base method. -func (m *MockFinalityProviderAPIs) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", fpPk, blockHeight, blockHash, sig) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockFinalityProviderAPIsMockRecorder) SubmitFinalitySig(fpPk, blockHeight, blockHash, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockFinalityProviderAPIs)(nil).SubmitFinalitySig), fpPk, blockHeight, blockHash, sig) -} - -// MockCovenantAPIs is a mock of CovenantAPIs interface. -type MockCovenantAPIs struct { - ctrl *gomock.Controller - recorder *MockCovenantAPIsMockRecorder -} - -// MockCovenantAPIsMockRecorder is the mock recorder for MockCovenantAPIs. -type MockCovenantAPIsMockRecorder struct { - mock *MockCovenantAPIs -} - -// NewMockCovenantAPIs creates a new mock instance. -func NewMockCovenantAPIs(ctrl *gomock.Controller) *MockCovenantAPIs { - mock := &MockCovenantAPIs{ctrl: ctrl} - mock.recorder = &MockCovenantAPIsMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockCovenantAPIs) EXPECT() *MockCovenantAPIsMockRecorder { - return m.recorder -} - -// QueryPendingDelegations mocks base method. -func (m *MockCovenantAPIs) QueryPendingDelegations(limit uint64) ([]*types.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryPendingDelegations", limit) - ret0, _ := ret[0].([]*types.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryPendingDelegations indicates an expected call of QueryPendingDelegations. -func (mr *MockCovenantAPIsMockRecorder) QueryPendingDelegations(limit interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingDelegations", reflect.TypeOf((*MockCovenantAPIs)(nil).QueryPendingDelegations), limit) -} - -// SubmitCovenantSigs mocks base method. -func (m *MockCovenantAPIs) SubmitCovenantSigs(covPk *btcec.PublicKey, stakingTxHash string, sigs [][]byte, unbondingSig *schnorr.Signature, unbondingSlashingSigs [][]byte) (*types.TxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitCovenantSigs", covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) - ret0, _ := ret[0].(*types.TxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitCovenantSigs indicates an expected call of SubmitCovenantSigs. -func (mr *MockCovenantAPIsMockRecorder) SubmitCovenantSigs(covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitCovenantSigs", reflect.TypeOf((*MockCovenantAPIs)(nil).SubmitCovenantSigs), covPk, stakingTxHash, sigs, unbondingSig, unbondingSlashingSigs) -} diff --git a/testutil/utils.go b/testutil/utils.go index f464616f..45f73cc3 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -23,7 +23,7 @@ func ZeroCommissionRate() *sdkmath.LegacyDec { return &zeroCom } -func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64, params *types.StakingParams) *mocks.MockClientController { +func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64) *mocks.MockClientController { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) @@ -43,7 +43,6 @@ func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, curr mockClientController.EXPECT().Close().Return(nil).AnyTimes() mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() - mockClientController.EXPECT().QueryStakingParams().Return(params, nil).AnyTimes() o1 := mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() lastCommittedHeight := startHeight + TestPubRandNum lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) diff --git a/tools/go.mod b/tools/go.mod index c7260602..daedeaf1 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -212,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index 389fcbb9..c6135e47 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866 h1:PhcQKkrFX2F+NJHgzQUquLAB3hjvZ5ojEnilf/lZycI= -github.com/babylonchain/babylon-private v0.0.0-20231224153404-79decc6a6866/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= +github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 h1:ysEA08WGHlMm2pIoXgTt1O9YAW4QjBQXg3TM0CSn21g= +github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= 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= diff --git a/types/delegation.go b/types/delegation.go deleted file mode 100644 index c326c1d3..00000000 --- a/types/delegation.go +++ /dev/null @@ -1,102 +0,0 @@ -package types - -import ( - bbn "github.com/babylonchain/babylon/types" - "math" - - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" -) - -type Delegation struct { - // The Bitcoin secp256k1 PK of this BTC delegation - BtcPk *btcec.PublicKey - // The Bitcoin secp256k1 PKs of the finality providers that - // this BTC delegation delegates to - FpBtcPks []*btcec.PublicKey - // The start BTC height of the BTC delegation - // it is the start BTC height of the timelock - StartHeight uint64 - // The end height of the BTC delegation - // it is the end BTC height of the timelock - w - EndHeight uint64 - // The total amount of BTC stakes in this delegation - // quantified in satoshi - TotalSat uint64 - // The hex string of the staking tx - StakingTxHex string - // The index of the staking output in the staking tx - StakingOutputIdx uint32 - // The hex string of the slashing tx - SlashingTxHex string - // The signatures on the slashing tx - // by the covenants (i.e., SKs corresponding to covenant_pks in params) - // It will be a part of the witness for the staking tx output. - CovenantSigs []*CovenantAdaptorSigInfo - // if this object is present it means that staker requested undelegation, and whole - // delegation is being undelegated directly in delegation object - BtcUndelegation *Undelegation -} - -// HasCovenantQuorum returns whether a delegation has sufficient sigs -// from Covenant members to make a quorum -func (d *Delegation) HasCovenantQuorum(quorum uint32) bool { - return uint32(len(d.CovenantSigs)) >= quorum && d.BtcUndelegation.HasAllSignatures(quorum) -} - -func (d *Delegation) GetStakingTime() uint16 { - diff := d.EndHeight - d.StartHeight - - if diff > math.MaxUint16 { - // In a valid delegation, EndHeight is always greater than StartHeight and it is always uint16 value - panic("invalid delegation in database") - } - - return uint16(diff) -} - -// Undelegation signalizes that the delegation is being undelegated -type Undelegation struct { - // How long the funds will be locked in the unbonding output - UnbondingTime uint32 - // The hex string of the transaction which will transfer the funds from staking - // output to unbonding output. Unbonding output will usually have lower timelock - // than staking output. - UnbondingTxHex string - // The hex string of the slashing tx for unbonding transactions - // It is partially signed by SK corresponding to btc_pk, but not signed by - // finality provider or covenant yet. - SlashingTxHex string - // The signatures on the slashing tx by the covenant - // (i.e., SK corresponding to covenant_pk in params) - // It must be provided after processing undelagate message by the consumer chain - CovenantSlashingSigs []*CovenantAdaptorSigInfo - // The signatures on the unbonding tx by the covenant - // (i.e., SK corresponding to covenant_pk in params) - // It must be provided after processing undelagate message by the consumer chain - CovenantUnbondingSigs []*CovenantSchnorrSigInfo - // The delegator signature for the unbonding tx - DelegatorUnbondingSig *bbn.BIP340Signature -} - -func (ud *Undelegation) HasCovenantQuorumOnSlashing(quorum uint32) bool { - return len(ud.CovenantUnbondingSigs) >= int(quorum) -} - -func (ud *Undelegation) HasCovenantQuorumOnUnbonding(quorum uint32) bool { - return len(ud.CovenantUnbondingSigs) >= int(quorum) -} - -func (ud *Undelegation) HasAllSignatures(covenantQuorum uint32) bool { - return ud.HasCovenantQuorumOnUnbonding(covenantQuorum) && ud.HasCovenantQuorumOnSlashing(covenantQuorum) -} - -type CovenantAdaptorSigInfo struct { - Pk *btcec.PublicKey - Sigs [][]byte -} - -type CovenantSchnorrSigInfo struct { - Pk *btcec.PublicKey - Sig *schnorr.Signature -} diff --git a/types/params.go b/types/params.go deleted file mode 100644 index 4c71c227..00000000 --- a/types/params.go +++ /dev/null @@ -1,42 +0,0 @@ -package types - -import ( - sdkmath "cosmossdk.io/math" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcutil" -) - -type StakingParams struct { - // K-deep - ComfirmationTimeBlocks uint64 - // W-deep - FinalizationTimeoutBlocks uint64 - - // Minimum amount of tx fee (quantified in Satoshi) needed for the pre-signed slashing tx - MinSlashingTxFeeSat btcutil.Amount - - // Bitcoin public keys of the covenant committee - CovenantPks []*btcec.PublicKey - - // Address to which slashing transactions are sent - SlashingAddress btcutil.Address - - // Minimum number of signatures needed for the covenant multisignature - CovenantQuorum uint32 - - // The staked amount to be slashed, expressed as a decimal (e.g., 0.5 for 50%). - SlashingRate sdkmath.LegacyDec - - // The minimum time for unbonding transaction timelock in BTC blocks - MinUnbondingTime uint32 -} - -// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from: -// - MinUnbondingTime -// - CheckpointFinalizationTimeout -func (p *StakingParams) MinimumUnbondingTime() uint64 { - return sdkmath.Max[uint64]( - uint64(p.MinUnbondingTime), - p.FinalizationTimeoutBlocks, - ) -} From b2576f666acf6effb2065dc0b263964d844ebc15 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 17 Jan 2024 18:44:01 +0800 Subject: [PATCH 46/66] fix: Slashing finality-provider caused program panicking (#201) --- finality-provider/service/fp_manager.go | 6 ++- go.mod | 30 +++++------ go.sum | 60 +++++++++++----------- itest/e2e_test.go | 8 +++ itest/test_manager.go | 9 ++++ tools/go.mod | 34 ++++++------- tools/go.sum | 68 ++++++++++++------------- 7 files changed, 117 insertions(+), 98 deletions(-) diff --git a/finality-provider/service/fp_manager.go b/finality-provider/service/fp_manager.go index a045592e..921747e4 100644 --- a/finality-provider/service/fp_manager.go +++ b/finality-provider/service/fp_manager.go @@ -84,7 +84,9 @@ func (fpm *FinalityProviderManager) monitorCriticalErr() { case criticalErr = <-fpm.criticalErrChan: fpi, err := fpm.GetFinalityProviderInstance(criticalErr.fpBtcPk) if err != nil { - panic(fmt.Errorf("failed to get the finality-provider instance: %w", err)) + fpm.logger.Debug("the finality-provider instance is already shutdown", + zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) + continue } if errors.Is(criticalErr.err, btcstakingtypes.ErrFpAlreadySlashed) { fpm.setFinalityProviderSlashed(fpi) @@ -92,7 +94,7 @@ func (fpm *FinalityProviderManager) monitorCriticalErr() { zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) continue } - fpi.logger.Fatal(instanceTerminatingMsg, + fpm.logger.Fatal(instanceTerminatingMsg, zap.String("pk", criticalErr.fpBtcPk.MarshalHex()), zap.Error(criticalErr.err)) case <-fpm.quit: return diff --git a/go.mod b/go.mod index a94d7d8a..dff0aa91 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/lightningnetwork/lnd v0.16.4-beta.rc1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.14 - go.etcd.io/bbolt v1.3.7 + 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.59.0 @@ -46,7 +46,7 @@ require ( cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/log v1.2.1 // indirect - cosmossdk.io/store v1.0.0 // indirect + cosmossdk.io/store v1.0.1 // 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 @@ -56,8 +56,8 @@ require ( filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/CosmWasm/wasmd v0.50.0-rc.2 // indirect - github.com/CosmWasm/wasmvm v1.5.0 // indirect + github.com/CosmWasm/wasmd v0.50.0 // indirect + github.com/CosmWasm/wasmvm v1.5.1 // 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.312 // indirect @@ -79,7 +79,7 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v0.38.2 // indirect - github.com/cometbft/cometbft-db v0.8.0 // 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-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect @@ -101,9 +101,9 @@ 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.1+incompatible // indirect + github.com/docker/docker v23.0.8+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/ethereum/go-ethereum v1.13.5 // indirect @@ -117,7 +117,7 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/golang/glog v1.1.2 // 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/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -158,12 +158,12 @@ require ( github.com/jmhodges/levigo v1.0.0 // indirect github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.4 // 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.4 // indirect + github.com/linxGnu/grocksdb v1.8.6 // 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 @@ -213,14 +213,14 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.15.0 // indirect + golang.org/x/crypto v0.17.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.18.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.143.0 // indirect @@ -239,7 +239,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 63eec27a..3c9ce8d1 100644 --- a/go.sum +++ b/go.sum @@ -203,8 +203,8 @@ cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= -cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= -cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/store v1.0.1 h1:XBDhCqlL+2MUgE8CHWwndKVJ4beX+TyaPIjB5SV62dM= +cosmossdk.io/store v1.0.1/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= @@ -231,10 +231,10 @@ github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi 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-rc.2 h1:CK7bRrAxYo8xooGhAwCRWyJqog+/M/7G1/p1BQVDNNU= -github.com/CosmWasm/wasmd v0.50.0-rc.2/go.mod h1:KtrZmXmh/V1ZmQ2/3dU6VRuZ09moRDpRqTL3L/mnPIE= -github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= -github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= +github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -279,8 +279,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-private v0.0.0-20240105083612-dd4e4b1c0598 h1:ysEA08WGHlMm2pIoXgTt1O9YAW4QjBQXg3TM0CSn21g= -github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= +github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 h1:ZNvQ1PB7jqAqmcGyOPk/R0NxUHgj6htJNCmizWt84Pw= +github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987/go.mod h1:/qhtE2riCrEN35zF2Svdxs+nbLOd7DRQnMKBXDIgTCs= github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee h1:hTtjwiz6ooQUmjubCqsbGmekzsASfoxoKoxIzVA/YQA= github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee/go.mod h1:6be7+qVoskKQM9by8KoCNDIFx3qfImoLdGeBj98zCw8= github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a h1:IwntCUOlcsczQfl4P72ckqGf09coMdM42LvAG1aM+mg= @@ -381,8 +381,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= -github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= -github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= +github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= +github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= @@ -462,8 +462,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.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= -github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +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/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= @@ -472,8 +472,8 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 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= @@ -573,8 +573,8 @@ github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2 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/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -829,8 +829,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.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -857,8 +857,8 @@ github.com/lightningnetwork/lnd v0.16.4-beta.rc1 h1:L8ktsv1lM5esVtiOlEtOBqU1dCoD github.com/lightningnetwork/lnd v0.16.4-beta.rc1/go.mod h1:sK9F98TpFuO/fjLCX4jEjc65qr2GZGs8IquVde1N46I= 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.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= -github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= +github.com/linxGnu/grocksdb v1.8.6/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= @@ -1164,8 +1164,8 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp 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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +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.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1213,8 +1213,8 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 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= @@ -1318,8 +1318,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.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 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= @@ -1463,13 +1463,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.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.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.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 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= diff --git a/itest/e2e_test.go b/itest/e2e_test.go index eedadba6..b10b1f9f 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -95,6 +95,14 @@ func TestDoubleSigning(t *testing.T) { require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) t.Logf("the equivocation attack is successful") + + tm.WaitForFpShutDown(t, fpIns.GetBtcPkBIP340()) + + // 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)) } // TestMultipleFinalityProviders tests starting with multiple finality providers diff --git a/itest/test_manager.go b/itest/test_manager.go index 7e15b211..b8129f1a 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -386,6 +386,15 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo return blocks } +func (tm *TestManager) WaitForFpShutDown(t *testing.T, pk *bbntypes.BIP340PubKey) { + require.Eventually(t, func() bool { + _, err := tm.Fpa.GetFinalityProviderInstance(pk) + return err != nil + }, eventuallyWaitTimeOut, eventuallyPollTime) + + t.Logf("the finality-provider instance %s is shutdown", pk.MarshalHex()) +} + func (tm *TestManager) StopAndRestartFpAfterNBlocks(t *testing.T, n int, fpIns *service.FinalityProviderInstance) { blockBeforeStop, err := tm.FPBBNClient.QueryBestBlock() require.NoError(t, err) diff --git a/tools/go.mod b/tools/go.mod index daedeaf1..cfcdf966 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -20,7 +20,7 @@ require ( cosmossdk.io/errors v1.0.0 // indirect cosmossdk.io/log v1.2.1 // indirect cosmossdk.io/math v1.2.0 // indirect - cosmossdk.io/store v1.0.0 // indirect + cosmossdk.io/store v1.0.1 // indirect cosmossdk.io/tools/confix v0.1.0 // indirect cosmossdk.io/x/circuit v0.1.0 // indirect cosmossdk.io/x/evidence v0.1.0 // indirect @@ -31,8 +31,8 @@ require ( filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/CosmWasm/wasmd v0.50.0-rc.2 // indirect - github.com/CosmWasm/wasmvm v1.5.0 // indirect + github.com/CosmWasm/wasmd v0.50.0 // indirect + github.com/CosmWasm/wasmvm v1.5.1 // 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 @@ -57,7 +57,7 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft v0.38.2 // indirect - github.com/cometbft/cometbft-db v0.8.0 // 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 @@ -81,9 +81,9 @@ 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.1+incompatible // indirect + github.com/docker/docker v23.0.8+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -95,7 +95,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.2 // indirect + github.com/golang/glog v1.2.0 // indirect 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 @@ -134,12 +134,12 @@ 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.2 // indirect + github.com/klauspost/compress v1.17.4 // 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.4 // indirect + github.com/linxGnu/grocksdb v1.8.6 // 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 @@ -176,24 +176,24 @@ require ( github.com/spf13/viper v1.17.0 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/supranational/blst v0.3.8 // 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/ulikunitz/xz v0.5.11 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect - go.etcd.io/bbolt v1.3.7 // indirect + 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.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.143.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -212,7 +212,7 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 + github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index c6135e47..fac14dd4 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -203,8 +203,8 @@ cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= -cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= -cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/store v1.0.1 h1:XBDhCqlL+2MUgE8CHWwndKVJ4beX+TyaPIjB5SV62dM= +cosmossdk.io/store v1.0.1/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= @@ -230,10 +230,10 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 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/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CosmWasm/wasmd v0.50.0-rc.2 h1:CK7bRrAxYo8xooGhAwCRWyJqog+/M/7G1/p1BQVDNNU= -github.com/CosmWasm/wasmd v0.50.0-rc.2/go.mod h1:KtrZmXmh/V1ZmQ2/3dU6VRuZ09moRDpRqTL3L/mnPIE= -github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= -github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= +github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -272,8 +272,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598 h1:ysEA08WGHlMm2pIoXgTt1O9YAW4QjBQXg3TM0CSn21g= -github.com/babylonchain/babylon-private v0.0.0-20240105083612-dd4e4b1c0598/go.mod h1:qiavPBxKkbMeTXg0vaLpMw97Xw8Nb3kpzZJ0ptiYcss= +github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 h1:ZNvQ1PB7jqAqmcGyOPk/R0NxUHgj6htJNCmizWt84Pw= +github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987/go.mod h1:/qhtE2riCrEN35zF2Svdxs+nbLOd7DRQnMKBXDIgTCs= 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= @@ -370,8 +370,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= -github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= -github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= +github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= +github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -441,8 +441,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.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= -github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +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/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= @@ -451,8 +451,8 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 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= @@ -548,8 +548,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -789,8 +789,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.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -811,8 +811,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.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= -github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= +github.com/linxGnu/grocksdb v1.8.6/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= @@ -1055,8 +1055,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= -github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= @@ -1091,8 +1091,8 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp 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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +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.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1134,8 +1134,8 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 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= @@ -1239,8 +1239,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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 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= @@ -1384,13 +1384,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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.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.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 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= @@ -1401,8 +1401,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 83766b42d998f8dcbfa5f382918b91095f18a648 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 19 Jan 2024 16:11:57 +0800 Subject: [PATCH 47/66] chore: Ensure all the Babylon queries are using rpc-client (#203) --- clientcontroller/babylon.go | 91 ++++++------------------------------- go.mod | 41 +++++++++-------- go.sum | 81 +++++++++++++++++---------------- tools/go.mod | 37 +++++++-------- tools/go.sum | 73 +++++++++++++++-------------- 5 files changed, 133 insertions(+), 190 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 5c8aad08..4222b041 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -16,7 +16,6 @@ import ( bbnclient "github.com/babylonchain/rpc-client/client" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg" - sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" sdkquery "github.com/cosmos/cosmos-sdk/types/query" @@ -218,16 +217,8 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, bloc } func (bc *BabylonController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk) - - queryRequest := &btcstakingtypes.QueryFinalityProviderRequest{FpBtcPkHex: fpPubKey.MarshalHex()} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - res, err := queryClient.FinalityProvider(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.FinalityProvider(fpPubKey.MarshalHex()) if err != nil { return false, fmt.Errorf("failed to query the finality provider %s: %v", fpPubKey.MarshalHex(), err) } @@ -257,31 +248,24 @@ func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types. // 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, } - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - queryRequest := &finalitytypes.QueryListPublicRandomnessRequest{ - Pagination: pagination, - FpBtcPkHex: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk).MarshalHex(), - } - - res, err := queryClient.ListPublicRandomness(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.ListPublicRandomness(fpBtcPk.MarshalHex(), pagination) if err != nil { - return nil, fmt.Errorf("failed to query committed public randomness: %v", err) + 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() } @@ -329,18 +313,7 @@ func getContextWithCancel(timeout time.Duration) (context.Context, context.Cance } func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) { - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query the indexed block at the given height - queryRequest := &finalitytypes.QueryBlockRequest{ - Height: height, - } - res, err := queryClient.Block(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.Block(height) if err != nil { return nil, fmt.Errorf("failed to query indexed block at height %v: %w", height, err) } @@ -353,16 +326,7 @@ func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) } func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query the indexed block at the given height - queryRequest := &btcstakingtypes.QueryActivatedHeightRequest{} - res, err := queryClient.ActivatedHeight(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.ActivatedHeight() if err != nil { return 0, fmt.Errorf("failed to query activated height: %w", err) } @@ -467,18 +431,8 @@ func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.Finali Limit: 100, } - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - for { - queryRequest := &btcstakingtypes.QueryFinalityProvidersRequest{ - Pagination: pagination, - } - res, err := queryClient.FinalityProviders(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.FinalityProviders(pagination) if err != nil { return nil, fmt.Errorf("failed to query finality providers: %v", err) } @@ -495,15 +449,7 @@ func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.Finali // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := btclctypes.NewQueryClient(clientCtx) - - queryRequest := &btclctypes.QueryTipRequest{} - res, err := queryClient.Tip(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip() if err != nil { return nil, fmt.Errorf("failed to query BTC tip: %v", err) } @@ -513,18 +459,7 @@ func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo // Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { - ctx, cancel := getContextWithCancel(bc.cfg.Timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.bbnClient.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &finalitytypes.QueryVotesAtHeightRequest{ - Height: height, - } - res, err := queryClient.VotesAtHeight(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.VotesAtHeight(height) if err != nil { return nil, fmt.Errorf("failed to query BTC delegations: %w", err) } diff --git a/go.mod b/go.mod index dff0aa91..e7c53ce5 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 toolchain go1.21.4 require ( - cosmossdk.io/errors v1.0.0 + cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 github.com/babylonchain/babylon v0.7.2 @@ -15,10 +15,10 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cosmos/cosmos-proto v1.0.0-beta.3 - github.com/cosmos/cosmos-sdk v0.50.1 + github.com/cosmos/cosmos-sdk v0.50.3 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.11 - github.com/cosmos/relayer/v2 v2.4.3-0.20231121194223-be8ebe0a83db + github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 @@ -30,34 +30,35 @@ require ( 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.59.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 ) require ( - cloud.google.com/go v0.110.8 // indirect - cloud.google.com/go/compute v1.23.1 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.3 // indirect + cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/storage v1.31.0 // indirect cosmossdk.io/api v0.7.2 // 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.2.1 // indirect - cosmossdk.io/store v1.0.1 // indirect + cosmossdk.io/log v1.3.0 // 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.12.0 // indirect + cosmossdk.io/x/tx v0.13.0 // 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 github.com/99designs/keyring v1.2.1 // indirect github.com/CosmWasm/wasmd v0.50.0 // indirect github.com/CosmWasm/wasmvm v1.5.1 // indirect + 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.312 // indirect @@ -126,8 +127,8 @@ require ( 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.3.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/google/uuid v1.4.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 @@ -217,17 +218,17 @@ require ( golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.143.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/api v0.149.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 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -240,7 +241,7 @@ require ( replace ( github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 - github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a + github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 3c9ce8d1..9905ce0b 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,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.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +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/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= @@ -70,8 +70,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.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= -cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +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/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= @@ -111,8 +111,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.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc= -cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +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/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= @@ -197,14 +197,14 @@ cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= -cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +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/store v1.0.1 h1:XBDhCqlL+2MUgE8CHWwndKVJ4beX+TyaPIjB5SV62dM= -cosmossdk.io/store v1.0.1/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +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= cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= @@ -213,8 +213,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.12.0 h1:Ry2btjQdrfrje9qZ3iZeZSmDArjgxUJMMcLMrX4wj5U= -cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +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/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= @@ -235,6 +235,7 @@ 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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -283,8 +284,8 @@ github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 h1:ZN github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987/go.mod h1:/qhtE2riCrEN35zF2Svdxs+nbLOd7DRQnMKBXDIgTCs= github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee h1:hTtjwiz6ooQUmjubCqsbGmekzsASfoxoKoxIzVA/YQA= github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee/go.mod h1:6be7+qVoskKQM9by8KoCNDIFx3qfImoLdGeBj98zCw8= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a h1:IwntCUOlcsczQfl4P72ckqGf09coMdM42LvAG1aM+mg= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20231214053715-9de58555773a/go.mod h1:dnUVCa5yHq2giiSpBpXx7W3CbJuuMabvQi3hG81AAtM= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169 h1:wb/7f20NCiWT8IDJWhHKIxex30FvAvBJS6SGcv108kA= +github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169/go.mod h1:bdEfcPa2N3cBtfzgsLGRhpiaET9loB/wHlUPmLRqohA= 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= @@ -403,8 +404,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 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.1 h1:2SYwAYqd7ZwtrWxu/J8PwbQV/cDcu90bCr/a78g3lVw= -github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= +github.com/cosmos/cosmos-sdk v0.50.3 h1:zP0AXm54ws2t2qVWvcQhEYVafhOAREU2QL0gnbwjvXw= +github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= 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= @@ -422,8 +423,8 @@ github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZD github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= 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.20231121194223-be8ebe0a83db h1:F5dlvwH3zQpTDnZySmH9OoMKKdx2OUKrP8CEQTWsAuY= -github.com/cosmos/relayer/v2 v2.4.3-0.20231121194223-be8ebe0a83db/go.mod h1:z5EtRGgbdFhqiemIu09cwwNbNu+UNH/qkhk696JFv48= +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/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= @@ -672,13 +673,13 @@ 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.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/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/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= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -1345,8 +1346,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.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= 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= @@ -1479,6 +1480,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -1607,8 +1609,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.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA= -google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= +google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= 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= @@ -1616,8 +1618,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1727,12 +1730,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-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= -google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +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/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= @@ -1774,8 +1777,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.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +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/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= @@ -1792,8 +1795,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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/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= 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= diff --git a/tools/go.mod b/tools/go.mod index cfcdf966..5effc66a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -7,32 +7,33 @@ toolchain go1.21.4 require github.com/babylonchain/babylon v0.7.1 require ( - cloud.google.com/go v0.110.8 // indirect - cloud.google.com/go/compute v1.23.1 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.3 // indirect + cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/storage v1.30.1 // indirect cosmossdk.io/api v0.7.2 // 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.0 // indirect - cosmossdk.io/log v1.2.1 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.3.0 // indirect cosmossdk.io/math v1.2.0 // indirect - cosmossdk.io/store v1.0.1 // indirect + cosmossdk.io/store v1.0.2 // indirect cosmossdk.io/tools/confix v0.1.0 // 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.12.0 // indirect + cosmossdk.io/x/tx v0.13.0 // 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 github.com/99designs/keyring v1.2.1 // indirect github.com/CosmWasm/wasmd v0.50.0 // indirect github.com/CosmWasm/wasmvm v1.5.1 // indirect + 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 @@ -61,7 +62,7 @@ require ( 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-sdk v0.50.1 // indirect + github.com/cosmos/cosmos-sdk v0.50.3 // 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 @@ -105,8 +106,8 @@ require ( 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.3.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/google/uuid v1.4.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 @@ -189,19 +190,19 @@ require ( golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.143.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/api v0.149.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/grpc v1.60.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tools/go.sum b/tools/go.sum index fac14dd4..6f2036c5 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -32,8 +32,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.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +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/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= @@ -70,8 +70,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.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= -cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +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/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= @@ -111,8 +111,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.3 h1:18tKG7DzydKWUnLjonWcJO6wjSCAtzh4GcRKlH/Hrzc= -cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +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/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= @@ -197,14 +197,14 @@ cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= -cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04= -cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= -cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk= -cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +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/store v1.0.1 h1:XBDhCqlL+2MUgE8CHWwndKVJ4beX+TyaPIjB5SV62dM= -cosmossdk.io/store v1.0.1/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= @@ -215,8 +215,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.12.0 h1:Ry2btjQdrfrje9qZ3iZeZSmDArjgxUJMMcLMrX4wj5U= -cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +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/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= @@ -234,6 +234,7 @@ 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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -386,8 +387,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 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.1 h1:2SYwAYqd7ZwtrWxu/J8PwbQV/cDcu90bCr/a78g3lVw= -github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= +github.com/cosmos/cosmos-sdk v0.50.3 h1:zP0AXm54ws2t2qVWvcQhEYVafhOAREU2QL0gnbwjvXw= +github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= 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= @@ -645,13 +646,13 @@ github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8 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.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/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/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= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -1266,8 +1267,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.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= 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= @@ -1400,6 +1401,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -1530,8 +1532,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.143.0 h1:o8cekTkqhywkbZT6p1UHJPZ9+9uuCAJs/KYomxZB8fA= -google.golang.org/api v0.143.0/go.mod h1:FoX9DO9hT7DLNn97OuoZAGSDuNAXdJRuGK98rSUgurk= +google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= 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= @@ -1539,8 +1541,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1649,12 +1652,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-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= -google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +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/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= @@ -1696,8 +1699,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.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +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/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= @@ -1714,8 +1717,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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/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= 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= From c5dd6e8dbbc17061054c508fd2ac8ea0d5f23243 Mon Sep 17 00:00:00 2001 From: Gurjot Singh <111540954+gusin13@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:11:52 -0500 Subject: [PATCH 48/66] fix: Add BLS flags in make (#202) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23d9690a..855a7e7e 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ all: build install build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) $(BUILD_TARGETS): go.sum $(BUILDDIR)/ - go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... + CGO_CFLAGS="-O -D__BLST_PORTABLE__" go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ From de79ebce2c271559579da75035419912278d10e0 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 22 Jan 2024 13:49:42 +0800 Subject: [PATCH 49/66] chore: Add account address in the output of `keys add` (#205) --- LICENSE | 300 ++++++++++-------------------- docs/eots.md | 2 +- eotsmanager/config/config.go | 2 +- finality-provider/cmd/fpd/keys.go | 6 +- keyring/keyringcontroller.go | 5 + types/chainkey.go | 12 +- 6 files changed, 108 insertions(+), 219 deletions(-) diff --git a/LICENSE b/LICENSE index 261eeb9e..4bda301c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,99 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + + +----------------------------------------------------------------------------- + +Parameters + +Licensor: Babylonchain, Inc. + +Licensed Work: finality-provider + The Licensed Work is (c) 2023 Babylonchain, Inc. + +Additional Use Grant: None. + +Change Date: 2027-01-20 (January 20th, 2027] + +Change License: Apache 2.0 + +----------------------------------------------------------------------------- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. + +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. + +MariaDB hereby grants you permission to use this License’s text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. + +----------------------------------------------------------------------------- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. + +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. + +----------------------------------------------------------------------------- + +Notice + +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. diff --git a/docs/eots.md b/docs/eots.md index 005964ae..83109dc4 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -68,7 +68,7 @@ RpcListener = 127.0.0.1:15813 # Type of keyring to use, # supported backends - (os|file|kwallet|pass|test|memory) # ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring -KeyringBackend = file +KeyringBackend = test # Possible database to choose as backend Backend = bbolt diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index a6ed128d..77e8277a 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -22,7 +22,7 @@ const ( defaultDBPath = "bbolt-eots.db" defaultConfigFileName = "eotsd.conf" DefaultRPCPort = 15813 - defaultKeyringBackend = keyring.BackendFile + defaultKeyringBackend = keyring.BackendTest ) var ( diff --git a/finality-provider/cmd/fpd/keys.go b/finality-provider/cmd/fpd/keys.go index 989a9729..c39dacd3 100644 --- a/finality-provider/cmd/fpd/keys.go +++ b/finality-provider/cmd/fpd/keys.go @@ -92,14 +92,10 @@ func addKey(ctx *cli.Context) error { return fmt.Errorf("failed to create the chain key: %w", err) } - addr, err := keyInfo.GetValAddress() - if err != nil { - return err - } printRespJSON( KeyOutput{ Name: keyName, - Address: addr.String(), + Address: keyInfo.AccAddress.String(), Mnemonic: keyInfo.Mnemonic, }, ) diff --git a/keyring/keyringcontroller.go b/keyring/keyringcontroller.go index c5167324..14e2cca7 100644 --- a/keyring/keyringcontroller.go +++ b/keyring/keyringcontroller.go @@ -96,12 +96,17 @@ func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*ty } privKey := record.GetLocal().PrivKey.GetCachedValue() + accAddress, err := record.GetAddress() + if err != nil { + return nil, err + } switch v := privKey.(type) { case *sdksecp256k1.PrivKey: sk, pk := btcec.PrivKeyFromBytes(v.Key) return &types.ChainKeyInfo{ Name: kc.fpName, + AccAddress: accAddress, PublicKey: pk, PrivateKey: sk, Mnemonic: mnemonic, diff --git a/types/chainkey.go b/types/chainkey.go index b5af543b..6d5df870 100644 --- a/types/chainkey.go +++ b/types/chainkey.go @@ -1,24 +1,14 @@ package types import ( - "fmt" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" ) type ChainKeyInfo struct { Name string Mnemonic string + AccAddress sdk.AccAddress PublicKey *btcec.PublicKey PrivateKey *btcec.PrivateKey } - -func (ki *ChainKeyInfo) GetValAddress() (sdk.ValAddress, error) { - if ki.PublicKey == nil { - return nil, fmt.Errorf("empty public key") - } - pk := secp256k1.PubKey{Key: ki.PublicKey.SerializeCompressed()} - return pk.Address().Bytes(), nil -} From fb5f6426612ecfcf2ca7ebb163d3d74e24daa984 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 22 Jan 2024 15:10:33 +0800 Subject: [PATCH 50/66] chore: Bump public dependency (#204) --- go.mod | 10 +++++----- go.sum | 16 ++++++++-------- tools/go.mod | 10 +++------- tools/go.sum | 4 ++-- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index e7c53ce5..f297d7d8 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,9 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonchain/babylon v0.7.2 - github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee - github.com/babylonchain/rpc-client v0.7.0 + github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb + github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 + github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.3 @@ -240,8 +240,8 @@ require ( ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 - github.com/babylonchain/rpc-client => github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169 + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 9905ce0b..8c460d21 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,6 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= -github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= 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= @@ -280,12 +278,12 @@ 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-private v0.0.0-20240117063238-ec7d62eb0987 h1:ZNvQ1PB7jqAqmcGyOPk/R0NxUHgj6htJNCmizWt84Pw= -github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987/go.mod h1:/qhtE2riCrEN35zF2Svdxs+nbLOd7DRQnMKBXDIgTCs= -github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee h1:hTtjwiz6ooQUmjubCqsbGmekzsASfoxoKoxIzVA/YQA= -github.com/babylonchain/covenant-emulator v0.0.0-20240109011217-2586ba2d2aee/go.mod h1:6be7+qVoskKQM9by8KoCNDIFx3qfImoLdGeBj98zCw8= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169 h1:wb/7f20NCiWT8IDJWhHKIxex30FvAvBJS6SGcv108kA= -github.com/babylonchain/rpc-client-private v0.7.0-rc0.0.20240119033927-3f5ec9a92169/go.mod h1:bdEfcPa2N3cBtfzgsLGRhpiaET9loB/wHlUPmLRqohA= +github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb h1:WRRhO4JT97Kq/4NrUmE5UzLEPth6ZKkI64hnje9nqvw= +github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= +github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 h1:NMgDiBBuA0xfcS8LTaP2Lpca9j6qWJnMfbQ2u1HYj2k= +github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6/go.mod h1:Rz51BAn7ym3Nf53FZ0R+pJXMj5GPwD0alVqDR+f+Rjw= +github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 h1:FWsneAs2tSact+VKJuwVtX6xjj10OtthA1np4AG2CQ4= +github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2/go.mod h1:3WkXcOZX2m0VvM4K6KshfiSQeTz3sSCjVw+NQ6Ayx2U= 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= @@ -421,6 +419,8 @@ github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOh github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +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= diff --git a/tools/go.mod b/tools/go.mod index 5effc66a..3c00b9bb 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.7.1 +require github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb require ( cloud.google.com/go v0.110.10 // indirect @@ -212,9 +212,5 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) -replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 - - // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 - github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 -) +// Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 +replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/tools/go.sum b/tools/go.sum index 6f2036c5..e0805f27 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -273,8 +273,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987 h1:ZNvQ1PB7jqAqmcGyOPk/R0NxUHgj6htJNCmizWt84Pw= -github.com/babylonchain/babylon-private v0.0.0-20240117063238-ec7d62eb0987/go.mod h1:/qhtE2riCrEN35zF2Svdxs+nbLOd7DRQnMKBXDIgTCs= +github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb h1:WRRhO4JT97Kq/4NrUmE5UzLEPth6ZKkI64hnje9nqvw= +github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= 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= From d5f06f55e4bd5a9c71a41c5a57e30c202eb9f53e Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Mon, 22 Jan 2024 12:01:26 +0200 Subject: [PATCH 51/66] chore: Upgrade bbn to 0.8.0-rc.0 (#211) --- go.mod | 2 +- go.sum | 4 ++-- tools/go.mod | 2 +- tools/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f297d7d8..73752b62 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb + github.com/babylonchain/babylon v0.8.0-rc.0 github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 diff --git a/go.sum b/go.sum index 8c460d21..a4e3d6f6 100644 --- a/go.sum +++ b/go.sum @@ -278,8 +278,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.7.2-0.20240121090242-60e5612f9acb h1:WRRhO4JT97Kq/4NrUmE5UzLEPth6ZKkI64hnje9nqvw= -github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= +github.com/babylonchain/babylon v0.8.0-rc.0 h1:zl2pyCpdvj+9tVuQ23qg/JqoywIbThwaxkdJcL5dGcM= +github.com/babylonchain/babylon v0.8.0-rc.0/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 h1:NMgDiBBuA0xfcS8LTaP2Lpca9j6qWJnMfbQ2u1HYj2k= github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6/go.mod h1:Rz51BAn7ym3Nf53FZ0R+pJXMj5GPwD0alVqDR+f+Rjw= github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 h1:FWsneAs2tSact+VKJuwVtX6xjj10OtthA1np4AG2CQ4= diff --git a/tools/go.mod b/tools/go.mod index 3c00b9bb..359d3d08 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.7.2-0.20240121090242-60e5612f9acb +require github.com/babylonchain/babylon v0.8.0-rc.0 require ( cloud.google.com/go v0.110.10 // indirect diff --git a/tools/go.sum b/tools/go.sum index e0805f27..144bed7e 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -273,8 +273,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb h1:WRRhO4JT97Kq/4NrUmE5UzLEPth6ZKkI64hnje9nqvw= -github.com/babylonchain/babylon v0.7.2-0.20240121090242-60e5612f9acb/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= +github.com/babylonchain/babylon v0.8.0-rc.0 h1:zl2pyCpdvj+9tVuQ23qg/JqoywIbThwaxkdJcL5dGcM= +github.com/babylonchain/babylon v0.8.0-rc.0/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= 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= From 20979c2b00c75c7f040aab0d04a79bb7b72a4978 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 22 Jan 2024 18:37:13 +0800 Subject: [PATCH 52/66] chore: Remove private repo thingy (#210) --- Dockerfile | 6 +----- README.md | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index db458b66..dd5a7b21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,15 +12,11 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d libzmq-static libsodium-static gcc -RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts -RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/* - # Build WORKDIR /go/src/github.com/babylonchain/finality-provider # Cache dependencies COPY go.mod go.sum /go/src/github.com/babylonchain/finality-provider/ -RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download +RUN go mod download # Copy the rest of the files COPY ./ /go/src/github.com/babylonchain/finality-provider/ diff --git a/README.md b/README.md index dac7c0d5..21d00c6a 100644 --- a/README.md +++ b/README.md @@ -95,10 +95,6 @@ $ ls build └── fpd ``` -If Go complains that it cannot retrieve some of the dependencies, one reason -could be that these repositories are private. Try following the instructions -[here](https://go.dev/doc/faq#git_https). - 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 From d9a390f51fea3325e20365d83e1a30d51a986602 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Mon, 22 Jan 2024 19:01:00 +0800 Subject: [PATCH 53/66] chore: Remove dependency on covenant-emulator (#212) --- clientcontroller/babylon.go | 100 +++++++++++- go.mod | 1 - go.sum | 2 - itest/babylon_node_handler.go | 36 ++--- itest/e2e_test.go | 59 +++---- itest/test_manager.go | 294 +++++++++++++++++++++------------- tools/go.mod | 6 +- tools/go.sum | 4 +- types/stakingparams.go | 42 +++++ 9 files changed, 369 insertions(+), 175 deletions(-) create mode 100644 types/stakingparams.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 4222b041..d394e714 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -6,6 +6,7 @@ import ( "time" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" @@ -360,7 +361,10 @@ func (bc *BabylonController) Close() error { return bc.bbnClient.Stop() } -// Currently this is only used for e2e tests, probably does not need to add it into the interface +/* + Implementations for e2e tests only +*/ + func (bc *BabylonController) CreateBTCDelegation( delBabylonPk *secp256k1.PubKey, delBtcPk *bbntypes.BIP340PubKey, @@ -407,8 +411,6 @@ func (bc *BabylonController) CreateBTCDelegation( return &types.TxResponse{TxHash: res.TxHash}, nil } -// Insert BTC block header using rpc client -// Currently this is only used for e2e tests, probably does not need to add it into the interface func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { msg := &btclctypes.MsgInsertHeaders{ Signer: bc.mustGetTxSigner(), @@ -423,8 +425,6 @@ func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderB return res, nil } -// QueryFinalityProvider queries finality providers -// Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.FinalityProvider, error) { var fps []*btcstakingtypes.FinalityProvider pagination := &sdkquery.PageRequest{ @@ -447,7 +447,6 @@ func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.Finali return fps, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip() if err != nil { @@ -457,7 +456,6 @@ func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo return res.Header, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { res, err := bc.bbnClient.QueryClient.VotesAtHeight(height) if err != nil { @@ -466,3 +464,91 @@ func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP34 return res.BtcPks, nil } + +func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { + return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) +} + +func (bc *BabylonController) QueryActiveDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, 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) { + pagination := &sdkquery.PageRequest{ + Limit: limit, + } + + res, err := bc.bbnClient.QueryClient.BTCDelegations(status, pagination) + if err != nil { + return nil, fmt.Errorf("failed to query BTC delegations: %v", err) + } + + return res.BtcDelegations, nil +} + +func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) { + // query btc checkpoint params + ckptParamRes, err := bc.bbnClient.QueryClient.BTCCheckpointParams() + if err != nil { + return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err) + } + + // query btc staking params + stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParams() + if err != nil { + return nil, fmt.Errorf("failed to query staking params: %v", err) + } + + covenantPks := make([]*btcec.PublicKey, 0, len(stakingParamRes.Params.CovenantPks)) + for _, pk := range stakingParamRes.Params.CovenantPks { + covPk, err := pk.ToBTCPK() + if err != nil { + return nil, fmt.Errorf("invalid covenant public key") + } + covenantPks = append(covenantPks, covPk) + } + slashingAddress, err := btcutil.DecodeAddress(stakingParamRes.Params.SlashingAddress, bc.btcParams) + if err != nil { + return nil, err + } + + return &types.StakingParams{ + ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, + FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, + MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), + CovenantPks: covenantPks, + SlashingAddress: slashingAddress, + CovenantQuorum: stakingParamRes.Params.CovenantQuorum, + SlashingRate: stakingParamRes.Params.SlashingRate, + MinUnbondingTime: stakingParamRes.Params.MinUnbondingTime, + }, nil +} + +func (bc *BabylonController) SubmitCovenantSigs( + covPk *btcec.PublicKey, + stakingTxHash string, + slashingSigs [][]byte, + unbondingSig *schnorr.Signature, + unbondingSlashingSigs [][]byte, +) (*types.TxResponse, error) { + bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) + + msg := &btcstakingtypes.MsgAddCovenantSigs{ + Signer: bc.mustGetTxSigner(), + Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), + StakingTxHash: stakingTxHash, + SlashingTxSigs: slashingSigs, + UnbondingTxSig: bip340UnbondingSig, + SlashingUnbondingTxSigs: unbondingSlashingSigs, + } + + res, err := bc.reliablySendMsg(msg) + if err != nil { + return nil, err + } + + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil +} diff --git a/go.mod b/go.mod index 73752b62..7b2fc68e 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 github.com/babylonchain/babylon v0.8.0-rc.0 - github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 github.com/btcsuite/btcd/btcec/v2 v2.3.2 diff --git a/go.sum b/go.sum index a4e3d6f6..1dc52ad4 100644 --- a/go.sum +++ b/go.sum @@ -280,8 +280,6 @@ github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8 github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/babylonchain/babylon v0.8.0-rc.0 h1:zl2pyCpdvj+9tVuQ23qg/JqoywIbThwaxkdJcL5dGcM= github.com/babylonchain/babylon v0.8.0-rc.0/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= -github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6 h1:NMgDiBBuA0xfcS8LTaP2Lpca9j6qWJnMfbQ2u1HYj2k= -github.com/babylonchain/covenant-emulator v0.0.0-20240122065420-24422ab54cb6/go.mod h1:Rz51BAn7ym3Nf53FZ0R+pJXMj5GPwD0alVqDR+f+Rjw= github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 h1:FWsneAs2tSact+VKJuwVtX6xjj10OtthA1np4AG2CQ4= github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2/go.mod h1:3WkXcOZX2m0VvM4K6KshfiSQeTz3sSCjVw+NQ6Ayx2U= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index 9b1362d4..f5e63e20 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "testing" "github.com/babylonchain/babylon/types" @@ -15,21 +16,15 @@ import ( ) type babylonNode struct { - cmd *exec.Cmd - pidFile string - dataDir string - chainID string - slashingAddr string - covenantPk *types.BIP340PubKey + cmd *exec.Cmd + pidFile string + dataDir string } -func newBabylonNode(dataDir string, cmd *exec.Cmd, chainID string, slashingAddr string, covenantPk *types.BIP340PubKey) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd) *babylonNode { return &babylonNode{ - dataDir: dataDir, - cmd: cmd, - chainID: chainID, - slashingAddr: slashingAddr, - covenantPk: covenantPk, + dataDir: dataDir, + cmd: cmd, } } @@ -107,7 +102,7 @@ type BabylonNodeHandler struct { babylonNode *babylonNode } -func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *BabylonNodeHandler { +func NewBabylonNodeHandler(t *testing.T, covenantQuorum int, covenantPks []*types.BIP340PubKey) *BabylonNodeHandler { testDir, err := baseDir("zBabylonTest") require.NoError(t, err) defer func() { @@ -121,6 +116,11 @@ func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *Babylo slashingAddr := "SZtRT4BySL3o4efdGLh3k7Kny8GAnsBrSW" + var covenantPksStr []string + for _, pk := range covenantPks { + covenantPksStr = append(covenantPksStr, pk.MarshalHex()) + } + initTestnetCmd := exec.Command( "babylond", "testnet", @@ -131,8 +131,8 @@ func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *Babylo "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--covenant-pks=%s", covenantPk.MarshalHex()), - "--covenant-quorum=1", + fmt.Sprintf("--covenant-quorum=%d", covenantQuorum), + fmt.Sprintf("--covenant-pks=%s", strings.Join(covenantPksStr, ",")), ) var stderr bytes.Buffer @@ -157,7 +157,7 @@ func NewBabylonNodeHandler(t *testing.T, covenantPk *types.BIP340PubKey) *Babylo startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, chainID, slashingAddr, covenantPk), + babylonNode: newBabylonNode(testDir, startCmd), } } @@ -182,7 +182,3 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { dir := filepath.Join(w.babylonNode.dataDir, "node0", "babylond") return dir } - -func (w *BabylonNodeHandler) GetCovenantPk() *types.BIP340PubKey { - return w.babylonNode.covenantPk -} diff --git a/itest/e2e_test.go b/itest/e2e_test.go index b10b1f9f..3ebe7f57 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -31,19 +31,20 @@ func TestFinalityProviderLifeCycle(t *testing.T) { fpIns := fpInsList[0] - params := tm.GetParams(t) - // check the public randomness is committed tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - _ = tm.WaitForNPendingDels(t, 1) + dels := tm.WaitForNPendingDels(t, 1) + + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) // check the BTC delegation is active - _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForNActiveDels(t, 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) @@ -60,19 +61,20 @@ func TestDoubleSigning(t *testing.T) { fpIns := fpInsList[0] - params := tm.GetParams(t) - // check the public randomness is committed tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - _ = tm.WaitForNPendingDels(t, 1) + dels := tm.WaitForNPendingDels(t, 1) + + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) // check the BTC delegation is active - _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) + _ = tm.WaitForNActiveDels(t, 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) @@ -111,8 +113,6 @@ func TestMultipleFinalityProviders(t *testing.T) { tm, fpInstances := StartManagerWithFinalityProvider(t, n) defer tm.Stop(t) - params := tm.GetParams(t) - // submit BTC delegations for each finality-provider for _, fpIns := range fpInstances { tm.Wg.Add(1) @@ -120,21 +120,24 @@ func TestMultipleFinalityProviders(t *testing.T) { 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, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpi.MustGetBtcPk()}, stakingTime, stakingAmount) }(fpIns) } tm.Wg.Wait() - for _, fpIns := range fpInstances { - tm.Wg.Add(1) - go func(fpi *service.FinalityProviderInstance) { - defer tm.Wg.Done() - _ = tm.WaitForFpNActiveDels(t, fpi.GetBtcPkBIP340(), 1) - }(fpIns) + // check the BTC delegations are pending + dels := tm.WaitForNPendingDels(t, n) + require.Equal(t, n, len(dels)) + + // send covenant sigs to each of the delegations + for _, d := range dels { + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, d) } - tm.Wg.Wait() + + // check the BTC delegations are active + _ = tm.WaitForNActiveDels(t, n) // check there's a block finalized _ = tm.WaitForNFinalizedBlocks(t, 1) @@ -147,18 +150,20 @@ func TestFastSync(t *testing.T) { fpIns := fpInsList[0] - params := tm.GetParams(t) - // check the public randomness is committed tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount, params) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending - _ = tm.WaitForNPendingDels(t, 1) + dels := tm.WaitForNPendingDels(t, 1) - _ = tm.WaitForFpNActiveDels(t, fpIns.GetBtcPkBIP340(), 1) + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) + + // check the BTC delegation is active + _ = tm.WaitForNActiveDels(t, 1) // check the last voted block is finalized lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) @@ -180,7 +185,7 @@ func TestFastSync(t *testing.T) { t.Logf("the latest finalized block is at %v", finalizedHeight) // check if the fast sync works by checking if the gap is not more than 1 - currentHeaderRes, err := tm.FPBBNClient.QueryBestBlock() + currentHeaderRes, err := tm.BBNClient.QueryBestBlock() currentHeight := currentHeaderRes.Height t.Logf("the current block is at %v", currentHeight) require.NoError(t, err) diff --git a/itest/test_manager.go b/itest/test_manager.go index b8129f1a..867a6fa5 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -11,16 +11,15 @@ import ( "time" sdkmath "cosmossdk.io/math" + "github.com/babylonchain/babylon/btcstaking" + 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" - covcc "github.com/babylonchain/covenant-emulator/clientcontroller" - covcfg "github.com/babylonchain/covenant-emulator/config" - "github.com/babylonchain/covenant-emulator/covenant" - covtypes "github.com/babylonchain/covenant-emulator/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" @@ -42,27 +41,25 @@ var ( eventuallyPollTime = 500 * time.Millisecond btcNetworkParams = &chaincfg.SimNetParams - fpNamePrefix = "test-fp-" - monikerPrefix = "moniker-" - covenantKeyName = "covenant-key" - chainID = "chain-test" - passphrase = "testpass" - hdPath = "" + fpNamePrefix = "test-fp-" + monikerPrefix = "moniker-" + chainID = "chain-test" + passphrase = "testpass" + hdPath = "" + simnetParams = &chaincfg.SimNetParams ) type TestManager struct { Wg sync.WaitGroup BabylonHandler *BabylonNodeHandler EOTSServerHandler *EOTSServerHandler - CovenantEmulator *covenant.CovenantEmulator FpConfig *fpcfg.Config EOTSConfig *eotsconfig.Config - CovenanConfig *covcfg.Config Fpa *service.FinalityProviderApp EOTSClient *client.EOTSManagerGRpcClient - FPBBNClient *fpcc.BabylonController - CovBBNClient *covcc.BabylonController - StakingParams *covtypes.StakingParams + BBNClient *fpcc.BabylonController + StakingParams *types.StakingParams + CovenantPrivKeys []*btcec.PrivateKey baseDir string } @@ -89,15 +86,13 @@ func StartManager(t *testing.T) *TestManager { logger := zap.NewNop() - // 1. prepare covenant key, which will be used as input of Babylon node - covenantConfig := defaultCovenantConfig(testDir) - err = covenantConfig.Validate() - require.NoError(t, err) - covKeyPair, err := covenant.CreateCovenantKey(testDir, chainID, covenantKeyName, keyring.BackendTest, passphrase, hdPath) - require.NoError(t, err) + // 1. generate covenant committee + covenantQuorum := 2 + numCovenants := 3 + covenantPrivKeys, covenantPubKeys := generateCovenantCommittee(numCovenants, t) // 2. prepare Babylon node - bh := NewBabylonNodeHandler(t, bbntypes.NewBIP340PubKeyFromBTCPK(covKeyPair.PublicKey)) + bh := NewBabylonNodeHandler(t, covenantQuorum, covenantPubKeys) err = bh.Start() require.NoError(t, err) fpHomeDir := filepath.Join(testDir, "fp-home") @@ -119,26 +114,15 @@ func StartManager(t *testing.T) *TestManager { err = fpApp.Start() require.NoError(t, err) - // 5. prepare covenant emulator - bbnCfg := defaultBBNConfigWithKey(cfg.BabylonConfig.Key, cfg.BabylonConfig.KeyDirectory) - covbc, err := covcc.NewBabylonController(bbnCfg, &covenantConfig.BTCNetParams, logger) - require.NoError(t, err) - ce, err := covenant.NewCovenantEmulator(covenantConfig, covbc, passphrase, logger) - require.NoError(t, err) - err = ce.Start() - require.NoError(t, err) - tm := &TestManager{ BabylonHandler: bh, EOTSServerHandler: eh, FpConfig: cfg, EOTSConfig: eotsCfg, Fpa: fpApp, - CovenantEmulator: ce, - CovenanConfig: covenantConfig, EOTSClient: eotsCli, - FPBBNClient: bc, - CovBBNClient: covbc, + BBNClient: bc, + CovenantPrivKeys: covenantPrivKeys, baseDir: testDir, } @@ -150,7 +134,7 @@ func StartManager(t *testing.T) *TestManager { func (tm *TestManager) WaitForServicesStart(t *testing.T) { // wait for Babylon node starts require.Eventually(t, func() bool { - params, err := tm.CovBBNClient.QueryStakingParams() + params, err := tm.BBNClient.QueryStakingParams() if err != nil { return false } @@ -189,7 +173,7 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser // check finality providers on Babylon side require.Eventually(t, func() bool { - fps, err := tm.FPBBNClient.QueryFinalityProviders() + fps, err := tm.BBNClient.QueryFinalityProviders() if err != nil { t.Logf("failed to query finality providers from Babylon %s", err.Error()) return false @@ -223,8 +207,6 @@ func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*ser func (tm *TestManager) Stop(t *testing.T) { err := tm.Fpa.Stop() require.NoError(t, err) - err = tm.CovenantEmulator.Stop() - require.NoError(t, err) err = tm.BabylonHandler.Stop() require.NoError(t, err) err = os.RemoveAll(tm.baseDir) @@ -234,7 +216,7 @@ func (tm *TestManager) Stop(t *testing.T) { func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { require.Eventually(t, func() bool { - queriedFps, err := tm.FPBBNClient.QueryFinalityProviders() + queriedFps, err := tm.BBNClient.QueryFinalityProviders() if err != nil { return false } @@ -256,14 +238,14 @@ func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.Fi t.Logf("public randomness is successfully committed") } -func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*covtypes.Delegation { +func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDelegation { var ( - dels []*covtypes.Delegation + dels []*bstypes.BTCDelegation err error ) require.Eventually(t, func() bool { - dels, err = tm.CovBBNClient.QueryPendingDelegations( - tm.CovenanConfig.DelegationLimit, + dels, err = tm.BBNClient.QueryPendingDelegations( + 100, ) if err != nil { return false @@ -276,65 +258,47 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*covtypes.Dele return dels } -func (tm *TestManager) WaitForFpNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*covtypes.Delegation { - var dels []*covtypes.Delegation - currentBtcTip, err := tm.FPBBNClient.QueryBtcLightClientTip() - require.NoError(t, err) - params, err := tm.CovBBNClient.QueryStakingParams() - require.NoError(t, err) +func (tm *TestManager) WaitForNActiveDels(t *testing.T, n int) []*bstypes.BTCDelegation { + var ( + dels []*bstypes.BTCDelegation + err error + ) require.Eventually(t, func() bool { - dels, err = tm.CovBBNClient.QueryFinalityProviderDelegations(btcPk, 1000) + dels, err = tm.BBNClient.QueryActiveDelegations( + 100, + ) if err != nil { return false } - return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, - params.CovenantQuorum, bstypes.BTCDelegationStatus_ACTIVE) + return len(dels) == n }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Logf("the delegation is active, finality providers should start voting") + t.Logf("delegations are active") return dels } -func CheckDelsStatus(dels []*covtypes.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32, status bstypes.BTCDelegationStatus) bool { - allChecked := true - for _, d := range dels { - s := getDelStatus(d, btcHeight, w, covenantQuorum) - if s != status { - allChecked = false - } - } - - return allChecked -} - -func getDelStatus(del *covtypes.Delegation, btcHeight uint64, w uint64, covenantQuorum uint32) bstypes.BTCDelegationStatus { - if del.BtcUndelegation.DelegatorUnbondingSig != nil { - // this means the delegator has signed unbonding signature, and Babylon will consider - // this BTC delegation unbonded directly - return bstypes.BTCDelegationStatus_UNBONDED - } - - if btcHeight < del.StartHeight || btcHeight+w > del.EndHeight { - // staking tx's timelock has not begun, or is less than w BTC - // blocks left, or is expired - return bstypes.BTCDelegationStatus_UNBONDED - } +func generateCovenantCommittee(numCovenants int, t *testing.T) ([]*btcec.PrivateKey, []*bbntypes.BIP340PubKey) { + var ( + covenantPrivKeys []*btcec.PrivateKey + covenantPubKeys []*bbntypes.BIP340PubKey + ) - // at this point, BTC delegation has an active timelock, and Babylon is not - // aware of unbonding tx with delegator's signature - if del.HasCovenantQuorum(covenantQuorum) { - return bstypes.BTCDelegationStatus_ACTIVE + for i := 0; i < numCovenants; i++ { + privKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + covenantPrivKeys = append(covenantPrivKeys, privKey) + pubKey := bbntypes.NewBIP340PubKeyFromBTCPK(privKey.PubKey()) + covenantPubKeys = append(covenantPubKeys, pubKey) } - // no covenant quorum yet, pending - return bstypes.BTCDelegationStatus_PENDING + return covenantPrivKeys, covenantPubKeys } func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { // we need to ensure votes are collected at the given height require.Eventually(t, func() bool { - votes, err := tm.FPBBNClient.QueryVotesAtHeight(height) + votes, err := tm.BBNClient.QueryVotesAtHeight(height) if err != nil { t.Logf("failed to get the votes at height %v: %s", height, err.Error()) return false @@ -344,7 +308,7 @@ func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num i // as the votes have been collected, the block should be finalized require.Eventually(t, func() bool { - b, err := tm.FPBBNClient.QueryBlock(height) + b, err := tm.BBNClient.QueryBlock(height) if err != nil { t.Logf("failed to query block at height %v: %s", height, err.Error()) return false @@ -373,7 +337,7 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo err error ) require.Eventually(t, func() bool { - blocks, err = tm.FPBBNClient.QueryLatestFinalizedBlocks(uint64(n)) + blocks, err = tm.BBNClient.QueryLatestFinalizedBlocks(uint64(n)) if err != nil { t.Logf("failed to get the latest finalized block: %s", err.Error()) return false @@ -396,13 +360,13 @@ func (tm *TestManager) WaitForFpShutDown(t *testing.T, pk *bbntypes.BIP340PubKey } func (tm *TestManager) StopAndRestartFpAfterNBlocks(t *testing.T, n int, fpIns *service.FinalityProviderInstance) { - blockBeforeStop, err := tm.FPBBNClient.QueryBestBlock() + blockBeforeStop, err := tm.BBNClient.QueryBestBlock() require.NoError(t, err) err = fpIns.Stop() require.NoError(t, err) require.Eventually(t, func() bool { - headerAfterStop, err := tm.FPBBNClient.QueryBestBlock() + headerAfterStop, err := tm.BBNClient.QueryBestBlock() if err != nil { return false } @@ -423,7 +387,129 @@ func (tm *TestManager) GetFpPrivKey(t *testing.T, fpPk []byte) *btcec.PrivateKey return record.PrivKey } -func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64, params *covtypes.StakingParams) *TestDelegationData { +func (tm *TestManager) InsertCovenantSigForDelegation(t *testing.T, btcDel *bstypes.BTCDelegation) { + slashingTx := btcDel.SlashingTx + stakingTx := btcDel.StakingTx + stakingMsgTx, err := bbntypes.NewBTCTxFromBytes(stakingTx) + require.NoError(t, err) + + params := tm.StakingParams + + stakingInfo, err := btcstaking.BuildStakingInfo( + btcDel.BtcPk.MustToBTCPK(), + // TODO: Handle multiple providers + []*btcec.PublicKey{btcDel.FpBtcPkList[0].MustToBTCPK()}, + params.CovenantPks, + params.CovenantQuorum, + btcDel.GetStakingTime(), + btcutil.Amount(btcDel.TotalSat), + simnetParams, + ) + require.NoError(t, err) + stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() + require.NoError(t, err) + + idx, err := bbntypes.GetOutputIdxInBTCTx(stakingMsgTx, stakingInfo.StakingOutput) + require.NoError(t, err) + + require.NoError(t, err) + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() + require.NoError(t, err) + // get covenant private key from the keyring + valEncKey, err := asig.NewEncryptionKeyFromBTCPK(btcDel.FpBtcPkList[0].MustToBTCPK()) + require.NoError(t, err) + + unbondingMsgTx, err := bbntypes.NewBTCTxFromBytes(btcDel.BtcUndelegation.UnbondingTx) + require.NoError(t, err) + unbondingInfo, err := btcstaking.BuildUnbondingInfo( + btcDel.BtcPk.MustToBTCPK(), + []*btcec.PublicKey{btcDel.FpBtcPkList[0].MustToBTCPK()}, + params.CovenantPks, + params.CovenantQuorum, + uint16(btcDel.UnbondingTime), + btcutil.Amount(unbondingMsgTx.TxOut[0].Value), + simnetParams, + ) + require.NoError(t, err) + + // Covenant 0 signatures + covenantAdaptorStakingSlashing1, err := slashingTx.EncSign( + stakingMsgTx, + idx, + slashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[0], + valEncKey, + ) + require.NoError(t, err) + covenantUnbondingSig1, err := btcstaking.SignTxWithOneScriptSpendInputFromTapLeaf( + unbondingMsgTx, + stakingInfo.StakingOutput, + tm.CovenantPrivKeys[0], + stakingTxUnbondingPathInfo.RevealedLeaf, + ) + require.NoError(t, err) + + // slashing unbonding tx sig + unbondingTxSlashingPathInfo, err := unbondingInfo.SlashingPathSpendInfo() + require.NoError(t, err) + covenantAdaptorUnbondingSlashing1, err := btcDel.BtcUndelegation.SlashingTx.EncSign( + unbondingMsgTx, + 0, + unbondingTxSlashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[0], + valEncKey, + ) + require.NoError(t, err) + + _, err = tm.BBNClient.SubmitCovenantSigs( + tm.CovenantPrivKeys[0].PubKey(), + stakingMsgTx.TxHash().String(), + [][]byte{covenantAdaptorStakingSlashing1.MustMarshal()}, + covenantUnbondingSig1, + [][]byte{covenantAdaptorUnbondingSlashing1.MustMarshal()}, + ) + require.NoError(t, err) + + // Covenant 1 signatures + covenantAdaptorStakingSlashing2, err := slashingTx.EncSign( + stakingMsgTx, + idx, + slashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[1], + valEncKey, + ) + require.NoError(t, err) + covenantUnbondingSig2, err := btcstaking.SignTxWithOneScriptSpendInputFromTapLeaf( + unbondingMsgTx, + stakingInfo.StakingOutput, + tm.CovenantPrivKeys[1], + stakingTxUnbondingPathInfo.RevealedLeaf, + ) + require.NoError(t, err) + + // slashing unbonding tx sig + + covenantAdaptorUnbondingSlashing2, err := btcDel.BtcUndelegation.SlashingTx.EncSign( + unbondingMsgTx, + 0, + unbondingTxSlashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[1], + valEncKey, + ) + + require.NoError(t, err) + _, err = tm.BBNClient.SubmitCovenantSigs( + tm.CovenantPrivKeys[1].PubKey(), + stakingMsgTx.TxHash().String(), + [][]byte{covenantAdaptorStakingSlashing2.MustMarshal()}, + covenantUnbondingSig2, + [][]byte{covenantAdaptorUnbondingSlashing2.MustMarshal()}, + ) + require.NoError(t, err) +} + +func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData { + params := tm.StakingParams r := rand.New(rand.NewSource(time.Now().UnixNano())) // delegator BTC key pairs, staking tx and slashing tx @@ -455,7 +541,7 @@ 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.FPBBNClient.QueryBtcLightClientTip() + currentBtcTip, err := tm.BBNClient.QueryBtcLightClientTip() require.NoError(t, err) blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), testStakingInfo.StakingTx) accumulatedWork := btclctypes.CalcWork(&blockWithStakingTx.HeaderBytes) @@ -473,7 +559,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe headers = append(headers, *headerInfo.Header) parentBlockHeaderInfo = headerInfo } - _, err = tm.FPBBNClient.InsertBtcBlockHeaders(headers) + _, err = tm.BBNClient.InsertBtcBlockHeaders(headers) require.NoError(t, err) btcHeader := blockWithStakingTx.HeaderBytes serializedStakingTx, err := bbntypes.SerializeBTCTx(testStakingInfo.StakingTx) @@ -528,7 +614,7 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe require.NoError(t, err) // submit the BTC delegation to Babylon - _, err = tm.FPBBNClient.CreateBTCDelegation( + _, err = tm.BBNClient.CreateBTCDelegation( delBabylonPubKey.(*secp256k1.PubKey), bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), fpPks, @@ -563,12 +649,6 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe } } -func (tm *TestManager) GetParams(t *testing.T) *covtypes.StakingParams { - p, err := tm.CovBBNClient.QueryStakingParams() - require.NoError(t, err) - return p -} - func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { cfg := fpcfg.DefaultConfigWithHome(homeDir) @@ -585,22 +665,6 @@ func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { return &cfg } -func defaultBBNConfigWithKey(key, keydir string) *covcfg.BBNConfig { - bbnCfg := covcfg.DefaultBBNConfig() - bbnCfg.Key = key - bbnCfg.KeyDirectory = keydir - bbnCfg.GasAdjustment = 20 - - return &bbnCfg -} - -func defaultCovenantConfig(homeDir string) *covcfg.Config { - cfg := covcfg.DefaultConfigWithHomePath(homeDir) - cfg.BabylonConfig.KeyDirectory = homeDir - - return &cfg -} - func defaultEOTSConfig() *eotsconfig.Config { cfg := eotsconfig.DefaultConfig() diff --git a/tools/go.mod b/tools/go.mod index 359d3d08..093e2d9a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -213,4 +213,8 @@ require ( ) // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 -replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 +replace ( + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 +) diff --git a/tools/go.sum b/tools/go.sum index 144bed7e..1f9ff48c 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -224,8 +224,6 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= -github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= 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= @@ -404,6 +402,8 @@ github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOh github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= +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/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= diff --git a/types/stakingparams.go b/types/stakingparams.go new file mode 100644 index 00000000..4c71c227 --- /dev/null +++ b/types/stakingparams.go @@ -0,0 +1,42 @@ +package types + +import ( + sdkmath "cosmossdk.io/math" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" +) + +type StakingParams struct { + // K-deep + ComfirmationTimeBlocks uint64 + // W-deep + FinalizationTimeoutBlocks uint64 + + // Minimum amount of tx fee (quantified in Satoshi) needed for the pre-signed slashing tx + MinSlashingTxFeeSat btcutil.Amount + + // Bitcoin public keys of the covenant committee + CovenantPks []*btcec.PublicKey + + // Address to which slashing transactions are sent + SlashingAddress btcutil.Address + + // Minimum number of signatures needed for the covenant multisignature + CovenantQuorum uint32 + + // The staked amount to be slashed, expressed as a decimal (e.g., 0.5 for 50%). + SlashingRate sdkmath.LegacyDec + + // The minimum time for unbonding transaction timelock in BTC blocks + MinUnbondingTime uint32 +} + +// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from: +// - MinUnbondingTime +// - CheckpointFinalizationTimeout +func (p *StakingParams) MinimumUnbondingTime() uint64 { + return sdkmath.Max[uint64]( + uint64(p.MinUnbondingTime), + p.FinalizationTimeoutBlocks, + ) +} From cb798465670a644a98cad30eca80e88c432d4b8a Mon Sep 17 00:00:00 2001 From: Filippos Malandrakis <35352222+filippos47@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:49:49 +0200 Subject: [PATCH 54/66] docs: Add note regarding randomness commitments (#213) --- README.md | 12 ++++++------ docs/eots.md | 14 ++++++-------- docs/finality-provider.md | 40 ++++++++++++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 21d00c6a..7fbdd11b 100644 --- a/README.md +++ b/README.md @@ -46,15 +46,15 @@ the [official Go installation guide](https://golang.org/doc/install). To get started, clone the repository to your local machine from Github: ```bash -$ git clone git@github.com:babylonchain/finality-provider.git +git clone git@github.com:babylonchain/finality-provider.git ``` You can choose a specific version from the [official releases page](https://github.com/babylonchain/finality-provider/releases) ```bash -$ cd finality-provider # cd into the project directory -$ git checkout +cd finality-provider # cd into the project directory +git checkout ``` #### Building and installing the binary @@ -62,7 +62,7 @@ $ git checkout At the top-level directory of the project ```bash -$ make install +make install ``` The above command will build and install the following binaries to @@ -83,13 +83,13 @@ echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.profile To build without installing, ```bash -$ make build +make build ``` The above command will put the built binaries in a build directory with the following structure: ```bash -$ ls build +ls build ├── eotsd ├── fpcli └── fpd diff --git a/docs/eots.md b/docs/eots.md index 83109dc4..b27b53cb 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -41,13 +41,13 @@ 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/ +eotsd init --home /path/to/eotsd/home/ ``` After initialization, the home directory will have the following structure ```bash -$ ls /path/to/eotsd/home/ +ls /path/to/eotsd/home/ ├── eotsd.conf # Eotsd-specific configuration file. ├── logs # Eotsd logs ``` @@ -59,7 +59,7 @@ be used. For different operating systems, those are: - **Linux** `~/.Eotsd` - **Windows** `C:\Users\\AppData\Local\Eotsd` -Below are some of the important parameters in the `eotsd.conf` file. +Below are the `eotsd.conf` file contents: ```bash # Default address to listen for RPC connections @@ -68,7 +68,7 @@ RpcListener = 127.0.0.1:15813 # Type of keyring to use, # supported backends - (os|file|kwallet|pass|test|memory) # ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring -KeyringBackend = test +KeyringBackend = file # Possible database to choose as backend Backend = bbolt @@ -80,14 +80,12 @@ Path = bbolt-eots.db Name = default ``` -To see the complete list of configuration options, check the `eotsd.conf` file. - ## 3. Starting the EOTS Daemon You can start the EOTS daemon using the following command: ```bash -$ eotsd start --home /path/to/eotsd/home +eotsd start --home /path/to/eotsd/home ``` This will start the rpc server at the address specified in the configuration under @@ -95,7 +93,7 @@ the `RpcListener` field, which has a default value of `127.0.0.1:15813`. You can also specify a custom address using the `--rpc-listener` flag. ```bash -$ eotsd start +eotsd start time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:15813"}" time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager Daemon is fully active!" diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 9cab3649..732b797c 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -33,13 +33,13 @@ 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/ +fpd init --home /path/to/fpd/home/ ``` After initialization, the home directory will have the following structure ```bash -$ ls /path/to/fpd/home/ +ls /path/to/fpd/home/ ├── fpd.conf # Fpd-specific configuration file. ├── logs # Fpd logs ``` @@ -88,6 +88,28 @@ KeyDirectory = /path/to/fpd/home 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 + + ; 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 + ``` + ## 3. Add key for the consumer chain The finality provider daemon requires the existence of a keyring that contains @@ -97,7 +119,7 @@ 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 chain-test ``` After executing the above command, the key name will be saved in the config file @@ -108,7 +130,7 @@ created in [step](#2-configuration). You can start the finality provider daemon using the following command: ```bash -$ fpd start --home /path/to/fpd/home +fpd start --home /path/to/fpd/home ``` This will start the RPC server at the address specified in the configuration under @@ -116,7 +138,7 @@ the `RpcListener` field, which has a default value of `127.0.0.1:15812`. You can also specify a custom address using the `--rpc-listener` flag. ```bash -$ fpd start --rpc-listener '127.0.0.1:8088' +fpd start --rpc-listener '127.0.0.1:8088' time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager {"address": "127.0.0.1:15813"}" time="2023-11-26T16:37:00-05:00" level=info msg="Starting FinalityProviderApp" @@ -139,7 +161,7 @@ a Babylon account to which staking rewards will be directed. The key name must be the same as the key added in [step](#3-add-key-for-the-consumer-chain). ```bash -$ fpcli create-finality-provider --key-name my-finality-provider \ +fpcli create-finality-provider --key-name my-finality-provider \ --chain-id chain-test --moniker my-name { "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", @@ -159,7 +181,7 @@ Note that if the `key-name` is not specified, the `Key` field of config specifie will be used. ```bash -$ fpcli register-finality-provider \ +fpcli register-finality-provider \ --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 { "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" @@ -175,10 +197,10 @@ The `status` field can receive the following values: - `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 +- `SLASHED`: The finality provider is slashed due to malicious behavior ```bash -$ fpcli list-finality-providers +fpcli list-finality-providers { "finality-providers": [ ... From b8053664b74fc2cb105b0860e660ed4b77d6285c Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Tue, 23 Jan 2024 20:44:23 +0800 Subject: [PATCH 55/66] fix(doc): Inconsistency of keyringbackend in doc (#214) --- docs/eots.md | 6 ++---- docs/finality-provider.md | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/eots.md b/docs/eots.md index b27b53cb..6e0dba03 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -65,10 +65,8 @@ Below are the `eotsd.conf` file contents: # Default address to listen for RPC connections RpcListener = 127.0.0.1:15813 -# Type of keyring to use, -# supported backends - (os|file|kwallet|pass|test|memory) -# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring -KeyringBackend = file +# Type of keyring to use +KeyringBackend = test # Possible database to choose as backend Backend = bbolt diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 732b797c..6fbdb8c7 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -77,9 +77,7 @@ 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, -# supported backends - (os|file|kwallet|pass|test|memory) -# ref https://docs.cosmos.network/v0.46/run-node/keyring.html#available-backends-for-the-keyring +# Type of keyring to use KeyringBackend = test # Directory where keys will be retrieved from and stored From a2f63dc3cad81bba8e58f21521feb5dd2b1f7e60 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 24 Jan 2024 15:26:08 +0800 Subject: [PATCH 56/66] chore: Remove `--all` flag when starting `fpd` daemon (#216) --- docs/finality-provider.md | 60 +++++++++++++++++------------- finality-provider/cmd/fpd/flags.go | 3 +- finality-provider/cmd/fpd/start.go | 9 +---- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 6fbdb8c7..30d8879a 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -54,9 +54,10 @@ will be used. For different operating systems, those are: 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). +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. ```bash @@ -131,10 +132,16 @@ 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:15812`. +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:15812`. You can also 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). + ```bash fpd start --rpc-listener '127.0.0.1:8088' @@ -145,18 +152,18 @@ time="2023-11-26T16:37:00-05:00" level=info msg="RPC server listening {"address" time="2023-11-26T16:37:00-05:00" level=info msg="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 -A finality provider named `my-finality-provider` can be created in the internal -storage ([bolt db](https://github.com/etcd-io/bbolt)) -through the `fpcli create-finality-provider` command. -This finality provider is associated with a BTC public key which +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. -The key name must be the same as the key added in [step](#3-add-key-for-the-consumer-chain). +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 \ @@ -171,30 +178,33 @@ fpcli create-finality-provider --key-name my-finality-provider \ } ``` -The finality provider can be registered with Babylon through -the `register-finality-provider` command. -The output contains the hash of the Babylon -finality provider registration transaction. -Note that if the `key-name` is not specified, the `Key` field of config specified in [step](#3-add-key-for-the-consumer-chain) -will be used. +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. ```bash fpcli register-finality-provider \ - --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 + --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 { "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" } ``` -To verify that your finality provider has been created, -we can check the finality providers that are managed by the daemon and their status. -These can be listed through the `fpcli list-finality-providers` command. +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: - `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 diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/flags.go index 0a942a35..9d79f802 100644 --- a/finality-provider/cmd/fpd/flags.go +++ b/finality-provider/cmd/fpd/flags.go @@ -5,9 +5,8 @@ import "github.com/cosmos/cosmos-sdk/crypto/keyring" const ( homeFlag = "home" forceFlag = "force" - allFlag = "all" passphraseFlag = "passphrase" - fpPkFlag = "finality-provider-pk" + fpPkFlag = "btc-pk" keyNameFlag = "key-name" hdPathFlag = "hd-path" chainIdFlag = "chain-id" diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go index 48f082c8..86868164 100644 --- a/finality-provider/cmd/fpd/start.go +++ b/finality-provider/cmd/fpd/start.go @@ -25,10 +25,6 @@ var startCommand = cli.Command{ Usage: "The pass phrase used to decrypt the private key", Value: defaultPassphrase, }, - cli.BoolFlag{ - Name: allFlag, - Usage: "Start all the managed finality providers", - }, cli.StringFlag{ Name: homeFlag, Usage: "The path to the finality-provider home directory", @@ -56,7 +52,6 @@ func start(ctx *cli.Context) error { passphrase := ctx.String(passphraseFlag) fpPkStr := ctx.String(fpPkFlag) rpcListener := ctx.String(rpcListenerFlag) - all := ctx.Bool(allFlag) cfg, err := fpcfg.LoadConfig(homePath) if err != nil { @@ -87,7 +82,7 @@ func start(ctx *cli.Context) error { return fmt.Errorf("failed to start the finality-provider app: %w", err) } - if !all && fpPkStr != "" { + if fpPkStr != "" { // start the finality-provider instance with the given public key fpPk, err := types.NewBIP340PubKeyFromHex(fpPkStr) if err != nil { @@ -96,7 +91,7 @@ func start(ctx *cli.Context) error { if err := fpApp.StartHandlingFinalityProvider(fpPk, passphrase); err != nil { return fmt.Errorf("failed to start the finality-provider instance %s: %w", fpPkStr, err) } - } else if all { + } else { if err := fpApp.StartHandlingAll(); err != nil { return err } From 8473c52206998efe5f542ca772d8694d625b6764 Mon Sep 17 00:00:00 2001 From: Filippos Malandrakis <35352222+filippos47@users.noreply.github.com> Date: Fri, 26 Jan 2024 14:09:36 +0200 Subject: [PATCH 57/66] CI: Remove redundant SSH key logic (#218) We don't have private dependencies anymore. --- .circleci/config.yml | 3 --- Makefile | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f3bb04ab..97666303 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,7 +18,6 @@ jobs: command: "go env" - go/load-cache: key: go-mod-v6-{{ checksum "go.sum" }} - - add_ssh_keys - go/mod-download - go/save-cache: key: go-mod-v6-{{ checksum "go.sum" }} @@ -46,7 +45,6 @@ jobs: resource_class: large steps: - checkout - - add_ssh_keys - aws-ecr/build-image: push-image: false dockerfile: Dockerfile @@ -54,7 +52,6 @@ jobs: build-path: ./ tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "$CIRCLE_PROJECT_REPONAME" - extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - run: name: Save Docker image to export it to workspace command: | diff --git a/Makefile b/Makefile index 855a7e7e..857a26a5 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/finality-provider -f Dockerfile \ + $(DOCKER) build --tag babylonchain/finality-provider -f Dockerfile \ $(shell git rev-parse --show-toplevel) .PHONY: build build-docker From 37750dfb89496d213e3e491526f1bef240dfe2cb Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Thu, 1 Feb 2024 08:00:05 +0200 Subject: [PATCH 58/66] fix: Only clean up blocks buffer up to the fast-synced height (#225) --- finality-provider/service/chain_poller.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/finality-provider/service/chain_poller.go b/finality-provider/service/chain_poller.go index 856a6d45..8e674587 100644 --- a/finality-provider/service/chain_poller.go +++ b/finality-provider/service/chain_poller.go @@ -270,11 +270,14 @@ func (cp *ChainPoller) SetNextHeight(height uint64) { func (cp *ChainPoller) SetNextHeightAndClearBuffer(height uint64) { cp.SetNextHeight(height) - cp.clearChanBuffer() + cp.clearChanBufferUpToHeight(height) } -func (cp *ChainPoller) clearChanBuffer() { +func (cp *ChainPoller) clearChanBufferUpToHeight(upToHeight uint64) { for len(cp.blockInfoChan) > 0 { - <-cp.blockInfoChan + block := <-cp.blockInfoChan + if block.Height+1 >= upToHeight { + break + } } } From 331e7963afd8879ee1ced3115190c6c0ced09f2f Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 1 Feb 2024 19:58:19 +0800 Subject: [PATCH 59/66] fix: `LastProcessedHeight` is falsely set causing skipping of blocks (#228) --- finality-provider/service/app_test.go | 1 + finality-provider/service/fastsync.go | 29 ++-- finality-provider/service/fastsync_test.go | 74 ++++++-- finality-provider/service/fp_instance.go | 158 +++++++++++++----- finality-provider/service/fp_instance_test.go | 39 ++--- testutil/utils.go | 7 - 6 files changed, 208 insertions(+), 100 deletions(-) diff --git a/finality-provider/service/app_test.go b/finality-provider/service/app_test.go index 192c1737..74d2ca01 100644 --- a/finality-provider/service/app_test.go +++ b/finality-provider/service/app_test.go @@ -94,6 +94,7 @@ func FuzzRegisterFinalityProvider(f *testing.F) { 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) require.NoError(t, err) diff --git a/finality-provider/service/fastsync.go b/finality-provider/service/fastsync.go index d070109a..b0d16b9a 100644 --- a/finality-provider/service/fastsync.go +++ b/finality-provider/service/fastsync.go @@ -49,19 +49,27 @@ func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*Fa // have gaps during sync catchUpBlocks := make([]*types.BlockInfo, 0, len(blocks)) for _, b := range blocks { - should, err := fp.shouldSubmitFinalitySignature(b) + // check whether the block has been processed before + if fp.hasProcessed(b) { + continue + } + // check whether the finality provider has voting power + hasVp, err := fp.hasVotingPower(b) if err != nil { - // stop catch-up when critical errors occur return nil, err } - if !should { - // two cases could lead to here: - // 1. insufficient committed randomness - // 2. no voting power - // thus we should continue here in case the two conditions - // will not happen in the rest of the blocks + if !hasVp { 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) } @@ -86,11 +94,12 @@ func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*Fa ) } - fp.MustSetLastProcessedHeight(endHeight) + // update the processed height + fp.MustSetLastProcessedHeight(syncedHeight) return &FastSyncResult{ Responses: responses, SyncedHeight: syncedHeight, - LastProcessedHeight: endHeight, + LastProcessedHeight: fp.GetLastProcessedHeight(), }, nil } diff --git a/finality-provider/service/fastsync_test.go b/finality-provider/service/fastsync_test.go index 8cc1b46a..bd4940ee 100644 --- a/finality-provider/service/fastsync_test.go +++ b/finality-provider/service/fastsync_test.go @@ -4,6 +4,7 @@ import ( "math/rand" "testing" + "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -11,7 +12,11 @@ import ( "github.com/babylonchain/finality-provider/types" ) -func FuzzFastSync(f *testing.F) { +// 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 +// height through fast-sync +func FuzzFastSync_SufficientRandomness(f *testing.F) { testutil.AddRandomSeedsToFuzzer(f, 10) f.Fuzz(func(t *testing.T, seed int64) { r := rand.New(rand.NewSource(seed)) @@ -19,27 +24,22 @@ func FuzzFastSync(f *testing.F) { randomStartingHeight := uint64(r.Int63n(100) + 1) finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return(nil, nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) - require.NoError(t, err) - // commit public randomness - 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().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). Return(uint64(1), nil).AnyTimes() - res, err := fpIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) + // 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() - // fast sync catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) - expectedTxHash = testutil.GenRandomHexStr(r, 32) + 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)). @@ -54,3 +54,45 @@ func FuzzFastSync(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 1a852321..a2301f7a 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -184,36 +184,42 @@ func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", b.Height), ) - if b.Height <= fp.GetLastProcessedHeight() { - fp.logger.Debug( - "the block has been processed before, skip processing", - zap.Uint64("height", b.Height), - zap.Uint64("last_processed_height", fp.GetLastProcessedHeight()), - zap.Uint64("last_voted_height", fp.GetLastVotedHeight()), - ) + + // check whether the block has been processed before + if fp.hasProcessed(b) { continue } - // use the copy of the block to avoid the impact to other receivers - nextBlock := *b - should, err := fp.shouldSubmitFinalitySignature(&nextBlock) - + // check whether the finality provider has voting power + hasVp, err := fp.hasVotingPower(b) if err != nil { fp.reportCriticalErr(err) continue } - - if !should { - fp.MustSetLastProcessedHeight(nextBlock.Height) + if !hasVp { + // the finality provider does not have voting power + // and it will never will at this block + fp.MustSetLastProcessedHeight(b.Height) 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.reportCriticalErr(err) continue } if res == nil { - fp.reportCriticalErr(fmt.Errorf("received an empty response when submitting finality sig")) + // this can happen when a finality signature is not needed + // either if the block is already submitted or the signature + // is already submitted continue } fp.logger.Info( @@ -337,22 +343,6 @@ func (fp *FinalityProviderInstance) tryFastSync(targetBlock *types.BlockInfo) (* return nil, fmt.Errorf("the finality-provider %s is already in sync", fp.GetBtcPkHex()) } - lastCommittedHeight, err := fp.GetLastCommittedHeight() - if err != nil { - return nil, err - } - if lastCommittedHeight <= fp.GetLastVotedHeight() { - if err := fp.SetLastProcessedHeight(targetBlock.Height); err != nil { - return nil, err - } - fp.logger.Debug( - "insufficient public randomness, jumping to the latest block", - zap.String("pk", fp.GetBtcPkHex()), - zap.Uint64("target_height", targetBlock.Height), - ) - return nil, nil - } - // get the last finalized height lastFinalizedBlocks, err := fp.cc.QueryLatestFinalizedBlocks(1) if err != nil { @@ -388,35 +378,50 @@ func (fp *FinalityProviderInstance) tryFastSync(targetBlock *types.BlockInfo) (* return fp.FastSync(startHeight, targetBlock.Height) } -// shouldSubmitFinalitySignature checks all the conditions that a finality should not be sent: -// 1. the finality-provider does not have voting power on the given block -// 2. the last committed height is lower than the block height as this indicates the finality-provider -// does not have the corresponding public randomness -// 3. the block height is lower than the last voted height as this indicates that the finality-provider -// does not need to send finality signature over this block -func (fp *FinalityProviderInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (bool, error) { - // check last voted height - if fp.GetLastVotedHeight() >= b.Height { +func (fp *FinalityProviderInstance) hasProcessed(b *types.BlockInfo) bool { + if b.Height <= fp.GetLastProcessedHeight() { fp.logger.Debug( - "the block has been voted before, skip voting", + "the block has been processed before, skip processing", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), - zap.Uint64("last_voted_height", fp.GetLastVotedHeight()), + zap.Uint64("last_processed_height", fp.GetLastProcessedHeight()), ) - return false, nil + return true } + return false +} + +func (fp *FinalityProviderInstance) hasVotingPower(b *types.BlockInfo) (bool, error) { power, err := fp.GetVotingPowerWithRetry(b.Height) if err != nil { return false, err } - if power == 0 { fp.logger.Debug( - "the finality-provider does not have voting power, skip voting", + "the finality-provider does not have voting power", zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("block_height", b.Height), ) + + return false, nil + } + + 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 } @@ -435,6 +440,65 @@ 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) { @@ -478,6 +542,8 @@ func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinali 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 } @@ -540,6 +606,8 @@ func (fp *FinalityProviderInstance) retryCommitPubRandUntilBlockFinalized(target 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 } diff --git a/finality-provider/service/fp_instance_test.go b/finality-provider/service/fp_instance_test.go index d5ca76c6..c58ad91d 100644 --- a/finality-provider/service/fp_instance_test.go +++ b/finality-provider/service/fp_instance_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -27,18 +28,16 @@ func FuzzCommitPubRandList(f *testing.F) { 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().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()). Return(uint64(0), nil).AnyTimes() - app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) - require.NoError(t, err) 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) @@ -55,22 +54,16 @@ func FuzzSubmitFinalitySig(f *testing.F) { 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() - app, storeFp, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) defer cleanUp() - mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). - Return(uint64(0), nil).AnyTimes() - fpIns, err := app.GetFinalityProviderInstance(storeFp.MustGetBIP340BTCPK()) - require.NoError(t, err) - // commit public randomness - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := fpIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryFinalityProviderVotingPower(storeFp.MustGetBTCPK(), gomock.Any()). + 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()). Return(uint64(1), nil).AnyTimes() // submit finality sig @@ -78,7 +71,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { Height: startingBlock.Height + 1, Hash: testutil.GenRandomByteArray(r, 32), } - expectedTxHash = testutil.GenRandomHexStr(r, 32) + expectedTxHash := testutil.GenRandomHexStr(r, 32) mockClientController.EXPECT(). SubmitFinalitySig(fpIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() @@ -92,7 +85,7 @@ func FuzzSubmitFinalitySig(f *testing.F) { }) } -func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.FinalityProviderApp, *proto.StoreFinalityProvider, func()) { +func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.FinalityProviderApp, *service.FinalityProviderInstance, func()) { logger := zap.NewNop() // create an EOTS manager eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") @@ -110,12 +103,14 @@ func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc cli require.NoError(t, err) err = app.Start() require.NoError(t, err) + err = app.StartHandlingAll() + require.NoError(t, err) // create registered finality-provider fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) err = app.GetFinalityProviderStore().SetFinalityProviderStatus(fp, proto.FinalityProviderStatus_REGISTERED) require.NoError(t, err) - err = app.StartHandlingFinalityProvider(fp.MustGetBIP340BTCPK(), passphrase) + fpIns, err := service.NewFinalityProviderInstance(fp.MustGetBIP340BTCPK(), fpCfg, app.GetFinalityProviderStore(), cc, em, passphrase, make(chan *service.CriticalError), logger) require.NoError(t, err) cleanUp := func() { @@ -127,5 +122,5 @@ func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc cli require.NoError(t, err) } - return app, fp, cleanUp + return app, fpIns, cleanUp } diff --git a/testutil/utils.go b/testutil/utils.go index 45f73cc3..2fb29c8c 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -5,7 +5,6 @@ import ( "testing" sdkmath "cosmossdk.io/math" - "github.com/btcsuite/btcd/btcec/v2" "github.com/golang/mock/gomock" "github.com/babylonchain/finality-provider/testutil/mocks" @@ -43,12 +42,6 @@ func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, curr mockClientController.EXPECT().Close().Return(nil).AnyTimes() mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() - o1 := mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() - lastCommittedHeight := startHeight + TestPubRandNum - lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) - lastCommittedPubRandMap[lastCommittedHeight] = GenPublicRand(r, t).ToFieldVal() - o2 := mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() - gomock.InOrder(o1, o2) return mockClientController } From 6fe4917d55835769dc5fa0706549d2d1b24a351c Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 1 Feb 2024 22:44:15 +0800 Subject: [PATCH 60/66] fix query best block (#231) --- clientcontroller/babylon.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index d394e714..25d90039 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -336,6 +336,16 @@ func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { } func (bc *BabylonController) QueryBestBlock() (*types.BlockInfo, error) { + blocks, err := bc.queryLatestBlocks(nil, 1, finalitytypes.QueriedBlockStatus_ANY, true) + if err != nil || len(blocks) != 1 { + // try query comet block if the index block query is not available + return bc.queryCometBestBlock() + } + + return blocks[0], nil +} + +func (bc *BabylonController) queryCometBestBlock() (*types.BlockInfo, error) { ctx, cancel := getContextWithCancel(bc.cfg.Timeout) // this will return 20 items at max in the descending order (highest first) chainInfo, err := bc.bbnClient.RPCClient.BlockchainInfo(ctx, 0, 0) From e1846354d5ed0564c2aa3ee18ea2bb40ac93543f Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Fri, 2 Feb 2024 10:58:35 +0800 Subject: [PATCH 61/66] chore: Fix panicking upon expected error during retrying (#221) --- clientcontroller/babylon.go | 64 +++++++++++++++++++----- clientcontroller/retry_utils.go | 38 +++++++++----- clientcontroller/retry_utils_test.go | 16 ++++++ finality-provider/service/fp_instance.go | 14 ++++-- itest/e2e_test.go | 62 +++++++++++++++++++++++ 5 files changed, 165 insertions(+), 29 deletions(-) create mode 100644 clientcontroller/retry_utils_test.go diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 25d90039..08938b2d 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + sdkErr "cosmossdk.io/errors" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" @@ -30,6 +31,8 @@ import ( var _ ClientController = &BabylonController{} +var emptyErrs = []*sdkErr.Error{} + type BabylonController struct { bbnClient *bbnclient.Client cfg *config.BBNConfig @@ -92,16 +95,16 @@ func (bc *BabylonController) GetKeyAddress() sdk.AccAddress { return addr } -func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxResponse, error) { - return bc.reliablySendMsgs([]sdk.Msg{msg}) +func (bc *BabylonController) reliablySendMsg(msg sdk.Msg, expectedErrs []*sdkErr.Error, unrecoverableErrs []*sdkErr.Error) (*provider.RelayerTxResponse, error) { + return bc.reliablySendMsgs([]sdk.Msg{msg}, expectedErrs, unrecoverableErrs) } -func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg, expectedErrs []*sdkErr.Error, unrecoverableErrs []*sdkErr.Error) (*provider.RelayerTxResponse, error) { return bc.bbnClient.ReliablySendMsgs( context.Background(), msgs, - expectedErrors, - unrecoverableErrors, + expectedErrs, + unrecoverableErrs, ) } @@ -133,7 +136,7 @@ func (bc *BabylonController) RegisterFinalityProvider( Description: &sdkDescription, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } @@ -165,7 +168,14 @@ func (bc *BabylonController) CommitPubRandList( Sig: bip340Sig, } - res, err := bc.reliablySendMsg(msg) + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidPubRand, + finalitytypes.ErrTooFewPubRand, + finalitytypes.ErrNoPubRandYet, + btcstakingtypes.ErrFpNotFound, + } + + res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } @@ -183,10 +193,25 @@ func (bc *BabylonController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeigh FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), } - res, err := bc.reliablySendMsg(msg) + expectedErrs := []*sdkErr.Error{ + finalitytypes.ErrDuplicatedFinalitySig, + } + + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrPubRandNotFound, + btcstakingtypes.ErrFpAlreadySlashed, + } + + res, err := bc.reliablySendMsg(msg, expectedErrs, unrecoverableErrs) if err != nil { return nil, err } + if res == nil { + // NOTE: this can happen when encountering expected errors + // during retrying + return nil, Expected(fmt.Errorf("expected error: %w", finalitytypes.ErrDuplicatedFinalitySig)) + } return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } @@ -209,10 +234,25 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, bloc msgs = append(msgs, msg) } - res, err := bc.reliablySendMsgs(msgs) + expectedErrs := []*sdkErr.Error{ + finalitytypes.ErrDuplicatedFinalitySig, + } + + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrPubRandNotFound, + btcstakingtypes.ErrFpAlreadySlashed, + } + + res, err := bc.reliablySendMsgs(msgs, expectedErrs, unrecoverableErrs) if err != nil { return nil, err } + if res == nil { + // NOTE: this can happen when encountering expected errors + // during retrying + return nil, Expected(fmt.Errorf("expected error: %w", finalitytypes.ErrDuplicatedFinalitySig)) + } return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } @@ -413,7 +453,7 @@ func (bc *BabylonController) CreateBTCDelegation( DelegatorUnbondingSlashingSig: delUnbondingSlashingSig, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } @@ -427,7 +467,7 @@ func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderB Headers: headers, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } @@ -555,7 +595,7 @@ func (bc *BabylonController) SubmitCovenantSigs( SlashingUnbondingTxSigs: unbondingSlashingSigs, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } diff --git a/clientcontroller/retry_utils.go b/clientcontroller/retry_utils.go index 486bf5e6..d216dabb 100644 --- a/clientcontroller/retry_utils.go +++ b/clientcontroller/retry_utils.go @@ -13,8 +13,6 @@ import ( var unrecoverableErrors = []*sdkErr.Error{ finalitytypes.ErrBlockNotFound, finalitytypes.ErrInvalidFinalitySig, - finalitytypes.ErrHeightTooHigh, - finalitytypes.ErrInvalidPubRand, finalitytypes.ErrNoPubRandYet, finalitytypes.ErrPubRandNotFound, finalitytypes.ErrTooFewPubRand, @@ -32,19 +30,33 @@ func IsUnrecoverable(err error) bool { return false } -var expectedErrors = []*sdkErr.Error{ - // if due to some low-level reason (e.g., network), we submit duplicated finality sig, - // we should just ignore the error - finalitytypes.ErrDuplicatedFinalitySig, +type ExpectedError struct { + error } -// IsExpected returns true when the error is in the expectedErrors list -func IsExpected(err error) bool { - for _, e := range expectedErrors { - if errors.Is(err, e) { - return true - } +func (e ExpectedError) Error() string { + if e.error == nil { + return "expected error" } + return e.error.Error() +} - return false +func (e ExpectedError) Unwrap() error { + return e.error +} + +// Is adds support for errors.Is usage on isExpected +func (ExpectedError) Is(err error) bool { + _, isExpected := err.(ExpectedError) + return isExpected +} + +// Expected wraps an error in ExpectedError struct +func Expected(err error) error { + return ExpectedError{err} +} + +// IsExpected checks if error is an instance of ExpectedError +func IsExpected(err error) bool { + return errors.Is(err, ExpectedError{}) } diff --git a/clientcontroller/retry_utils_test.go b/clientcontroller/retry_utils_test.go new file mode 100644 index 00000000..f607d044 --- /dev/null +++ b/clientcontroller/retry_utils_test.go @@ -0,0 +1,16 @@ +package clientcontroller + +import ( + "fmt" + "testing" + + "github.com/babylonchain/babylon/x/finality/types" + "github.com/stretchr/testify/require" +) + +func TestExpectedErr(t *testing.T) { + expectedErr := Expected(types.ErrDuplicatedFinalitySig) + require.True(t, IsExpected(expectedErr)) + wrappedErr := fmt.Errorf("expected: %w", expectedErr) + require.True(t, IsExpected(wrappedErr)) +} diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go index a2301f7a..7b6a3c21 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -137,7 +137,7 @@ func (fp *FinalityProviderInstance) bootstrap() (uint64, error) { if fp.checkLagging(latestBlock) { _, err := fp.tryFastSync(latestBlock) - if err != nil { + if err != nil && !clientcontroller.IsExpected(err) { return 0, err } } @@ -510,9 +510,7 @@ func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinali // error will be returned if max retries have been reached res, err := fp.SubmitFinalitySignature(targetBlock) if err != nil { - if clientcontroller.IsUnrecoverable(err) { - return nil, err - } + fp.logger.Debug( "failed to submit finality signature to the consumer chain", zap.String("pk", fp.GetBtcPkHex()), @@ -521,6 +519,14 @@ func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinali zap.Error(err), ) + if clientcontroller.IsUnrecoverable(err) { + return nil, err + } + + if clientcontroller.IsExpected(err) { + return nil, nil + } + failedCycles += 1 if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { return nil, fmt.Errorf("reached max failed cycles with err: %w", err) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 3ebe7f57..23a0f775 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -191,3 +191,65 @@ 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) + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) + require.GreaterOrEqual(t, finalizedBlocks[0].Height, lastVotedHeight) +} From d7ddb4c14ed8801a5780796cd6c5824cc5366eb9 Mon Sep 17 00:00:00 2001 From: Vitalis Salis Date: Fri, 2 Feb 2024 10:39:48 +0200 Subject: [PATCH 62/66] Change default ports to 12581 and 12582 (#232) --- docs/eots.md | 6 +++--- docs/finality-provider.md | 8 ++++---- eotsmanager/config/config.go | 2 +- finality-provider/config/config.go | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/eots.md b/docs/eots.md index 6e0dba03..b7f14dd3 100644 --- a/docs/eots.md +++ b/docs/eots.md @@ -63,7 +63,7 @@ Below are the `eotsd.conf` file contents: ```bash # Default address to listen for RPC connections -RpcListener = 127.0.0.1:15813 +RpcListener = 127.0.0.1:12582 # Type of keyring to use KeyringBackend = test @@ -87,13 +87,13 @@ 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:15813`. +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. ```bash eotsd start -time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:15813"}" +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!" ``` diff --git a/docs/finality-provider.md b/docs/finality-provider.md index 30d8879a..ecd4949c 100644 --- a/docs/finality-provider.md +++ b/docs/finality-provider.md @@ -62,7 +62,7 @@ So we can ignore the setting of the two fields in this step. ```bash # RPC Address of the EOTS Daemon -EOTSManagerAddress = 127.0.0.1:15813 +EOTSManagerAddress = 127.0.0.1:12582 # Babylon specific parameters @@ -133,7 +133,7 @@ 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:15812`. +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. This will also start all the registered finality provider instances except for @@ -145,10 +145,10 @@ finality provider (`btc_pk_hex`) obtained in [step](#5-create-and-register-a-fin ```bash fpd start --rpc-listener '127.0.0.1:8088' -time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager {"address": "127.0.0.1:15813"}" +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:15812"}" +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!" ``` diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go index 77e8277a..ca7161b8 100644 --- a/eotsmanager/config/config.go +++ b/eotsmanager/config/config.go @@ -21,7 +21,7 @@ const ( defaultLogFilename = "eotsd.log" defaultDBPath = "bbolt-eots.db" defaultConfigFileName = "eotsd.conf" - DefaultRPCPort = 15813 + DefaultRPCPort = 12582 defaultKeyringBackend = keyring.BackendTest ) diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index 9f688b0e..5ff55e17 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -22,7 +22,7 @@ const ( defaultLogDirname = "logs" defaultLogFilename = "fpd.log" defaultFinalityProviderKeyName = "finality-provider" - DefaultRPCPort = 15812 + DefaultRPCPort = 12581 defaultConfigFileName = "fpd.conf" defaultNumPubRand = 100 defaultNumPubRandMax = 100 From c50387205d959334f3ca4e7d85cebc37d0ee06d4 Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Tue, 6 Feb 2024 08:50:31 +0100 Subject: [PATCH 63/66] Bumps babylon to latest version (#236) --- clientcontroller/babylon.go | 22 +----- clientcontroller/retry_utils_test.go | 3 +- go.mod | 39 +++++----- go.sum | 101 +++++++++++--------------- tools/go.mod | 39 +++++----- tools/go.sum | 105 ++++++++++++--------------- 6 files changed, 131 insertions(+), 178 deletions(-) diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 08938b2d..77cf2e16 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -193,25 +193,16 @@ func (bc *BabylonController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeigh FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), } - expectedErrs := []*sdkErr.Error{ - finalitytypes.ErrDuplicatedFinalitySig, - } - unrecoverableErrs := []*sdkErr.Error{ finalitytypes.ErrInvalidFinalitySig, finalitytypes.ErrPubRandNotFound, btcstakingtypes.ErrFpAlreadySlashed, } - res, err := bc.reliablySendMsg(msg, expectedErrs, unrecoverableErrs) + res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } - if res == nil { - // NOTE: this can happen when encountering expected errors - // during retrying - return nil, Expected(fmt.Errorf("expected error: %w", finalitytypes.ErrDuplicatedFinalitySig)) - } return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } @@ -234,25 +225,16 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, bloc msgs = append(msgs, msg) } - expectedErrs := []*sdkErr.Error{ - finalitytypes.ErrDuplicatedFinalitySig, - } - unrecoverableErrs := []*sdkErr.Error{ finalitytypes.ErrInvalidFinalitySig, finalitytypes.ErrPubRandNotFound, btcstakingtypes.ErrFpAlreadySlashed, } - res, err := bc.reliablySendMsgs(msgs, expectedErrs, unrecoverableErrs) + res, err := bc.reliablySendMsgs(msgs, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } - if res == nil { - // NOTE: this can happen when encountering expected errors - // during retrying - return nil, Expected(fmt.Errorf("expected error: %w", finalitytypes.ErrDuplicatedFinalitySig)) - } return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } diff --git a/clientcontroller/retry_utils_test.go b/clientcontroller/retry_utils_test.go index f607d044..d1f178a6 100644 --- a/clientcontroller/retry_utils_test.go +++ b/clientcontroller/retry_utils_test.go @@ -4,12 +4,11 @@ import ( "fmt" "testing" - "github.com/babylonchain/babylon/x/finality/types" "github.com/stretchr/testify/require" ) func TestExpectedErr(t *testing.T) { - expectedErr := Expected(types.ErrDuplicatedFinalitySig) + expectedErr := Expected(fmt.Errorf("some error")) require.True(t, IsExpected(expectedErr)) wrappedErr := fmt.Errorf("expected: %w", expectedErr) require.True(t, IsExpected(wrappedErr)) diff --git a/go.mod b/go.mod index 7b2fc68e..208fc4c1 100644 --- a/go.mod +++ b/go.mod @@ -8,13 +8,13 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonchain/babylon v0.8.0-rc.0 + github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 - github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 + github.com/btcsuite/btcd v0.24.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/btcsuite/btcd/btcutil v1.1.3 + 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.3 + github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 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 @@ -38,7 +38,7 @@ require ( cloud.google.com/go/compute v1.23.3 // 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.31.0 // indirect + cloud.google.com/go/storage v1.35.1 // indirect cosmossdk.io/api v0.7.2 // indirect cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -56,7 +56,7 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/CosmWasm/wasmd v0.50.0 // indirect - github.com/CosmWasm/wasmvm v1.5.1 // indirect + github.com/CosmWasm/wasmvm v1.5.2 // indirect 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 @@ -66,7 +66,7 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -78,7 +78,7 @@ require ( github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // 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.2 // 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 @@ -109,7 +109,7 @@ require ( github.com/ethereum/go-ethereum v1.13.5 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -192,15 +192,15 @@ require ( github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.31.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.3.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/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.10.0 // indirect - github.com/spf13/cast v1.5.1 // 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.17.0 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect @@ -213,17 +213,18 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.17.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.19.0 // indirect - golang.org/x/oauth2 v0.13.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.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.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.149.0 // indirect + google.golang.org/api v0.153.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 diff --git a/go.sum b/go.sum index 1dc52ad4..f3df0b7d 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -170,12 +168,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= 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.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI= -cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0= +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/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= @@ -231,8 +228,8 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr 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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= -github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= +github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= @@ -278,8 +275,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-rc.0 h1:zl2pyCpdvj+9tVuQ23qg/JqoywIbThwaxkdJcL5dGcM= -github.com/babylonchain/babylon v0.8.0-rc.0/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= +github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b h1:J951fCTXQGa40HnmDpWtGeHoQQFc5a9L2k90nLwKINM= +github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 h1:FWsneAs2tSact+VKJuwVtX6xjj10OtthA1np4AG2CQ4= github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2/go.mod h1:3WkXcOZX2m0VvM4K6KshfiSQeTz3sSCjVw+NQ6Ayx2U= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -298,21 +295,21 @@ github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvP 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.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 h1:FZR6mILlSI/GDx8ydNVBZAlXlRXsoRBWX2Un64mpfsI= -github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +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= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= 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= @@ -376,8 +373,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= -github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= +github.com/cometbft/cometbft v0.38.5 h1:4lOcK5VTPrfbLOhNHmPYe6c7eDXHtBdMCQuKbAfFJdU= +github.com/cometbft/cometbft v0.38.5/go.mod h1:0tqKin+KQs8zDwzYD8rPHzSBIDNPuB4NrwwGDNb/hUg= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= @@ -400,8 +397,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 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.3 h1:zP0AXm54ws2t2qVWvcQhEYVafhOAREU2QL0gnbwjvXw= -github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= +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= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -504,12 +501,12 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8 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= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -658,7 +655,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -690,7 +686,6 @@ github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMd github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= @@ -832,7 +827,6 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW github.com/klauspost/compress v1.17.4/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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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= @@ -990,7 +984,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1051,8 +1044,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= -github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= @@ -1078,11 +1071,11 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= @@ -1093,8 +1086,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +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/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1209,11 +1202,9 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U 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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +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/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= @@ -1297,14 +1288,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/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= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 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-20211112202133-69e39bad7dc2/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= @@ -1317,8 +1306,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.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +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/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= @@ -1344,8 +1333,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.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= 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= @@ -1418,13 +1407,11 @@ 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-20210225134936-a50acf3fe073/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= @@ -1457,18 +1444,17 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc 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= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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/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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +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/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= @@ -1486,6 +1472,8 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1539,7 +1527,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1607,8 +1594,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.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= -google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +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/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= @@ -1658,10 +1645,8 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= diff --git a/tools/go.mod b/tools/go.mod index 093e2d9a..715560e6 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -4,14 +4,14 @@ go 1.21 toolchain go1.21.4 -require github.com/babylonchain/babylon v0.8.0-rc.0 +require github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b require ( cloud.google.com/go v0.110.10 // indirect cloud.google.com/go/compute v1.23.3 // 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.30.1 // indirect + cloud.google.com/go/storage v1.35.1 // indirect cosmossdk.io/api v0.7.2 // indirect cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -32,7 +32,7 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/CosmWasm/wasmd v0.50.0 // indirect - github.com/CosmWasm/wasmvm v1.5.1 // indirect + github.com/CosmWasm/wasmvm v1.5.2 // indirect 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 @@ -42,10 +42,10 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 // indirect + github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect @@ -57,12 +57,12 @@ require ( github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // 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.2 // 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-sdk v0.50.3 // 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 @@ -88,7 +88,7 @@ require ( github.com/emicklei/dot v1.6.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -166,15 +166,15 @@ require ( github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.31.0 // indirect - github.com/sagikazarmark/locafero v0.3.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/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.10.0 // indirect - github.com/spf13/cast v1.5.1 // 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.17.0 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect @@ -187,16 +187,17 @@ 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.17.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.19.0 // indirect - golang.org/x/oauth2 v0.13.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.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.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.149.0 // indirect + google.golang.org/api v0.153.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 diff --git a/tools/go.sum b/tools/go.sum index 1f9ff48c..18211c36 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -170,12 +168,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= 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.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +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/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= @@ -230,15 +227,15 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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.1 h1:2MHN9uFyHP6pxfvpBJ0JW6ujvAIBk9kQk283zyri0Ro= -github.com/CosmWasm/wasmvm v1.5.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= +github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= 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/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +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= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -271,8 +268,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon v0.8.0-rc.0 h1:zl2pyCpdvj+9tVuQ23qg/JqoywIbThwaxkdJcL5dGcM= -github.com/babylonchain/babylon v0.8.0-rc.0/go.mod h1:UJMehldQROFooqS5rXMd6avJSjwIsc0jpL+uKoOsTls= +github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b h1:J951fCTXQGa40HnmDpWtGeHoQQFc5a9L2k90nLwKINM= +github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= 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,21 +286,21 @@ github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvP 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.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231 h1:FZR6mILlSI/GDx8ydNVBZAlXlRXsoRBWX2Un64mpfsI= -github.com/btcsuite/btcd v0.23.5-0.20230711222809-7faa9b266231/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +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= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= 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= @@ -367,8 +364,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.2 h1:io0JCh5EPxINKN5ZMI5hCdpW3QVZRy+o8qWe3mlJa/8= -github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= +github.com/cometbft/cometbft v0.38.5 h1:4lOcK5VTPrfbLOhNHmPYe6c7eDXHtBdMCQuKbAfFJdU= +github.com/cometbft/cometbft v0.38.5/go.mod h1:0tqKin+KQs8zDwzYD8rPHzSBIDNPuB4NrwwGDNb/hUg= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -385,8 +382,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 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.3 h1:zP0AXm54ws2t2qVWvcQhEYVafhOAREU2QL0gnbwjvXw= -github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= +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= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -481,12 +478,12 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8 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= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -634,7 +631,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -665,7 +661,6 @@ github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMd github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= @@ -794,7 +789,6 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW github.com/klauspost/compress v1.17.4/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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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= @@ -936,7 +930,6 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -992,8 +985,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR 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= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ= -github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= @@ -1017,11 +1010,11 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= @@ -1032,8 +1025,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 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= @@ -1132,11 +1125,9 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U 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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +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/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= @@ -1220,14 +1211,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/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= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 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-20211112202133-69e39bad7dc2/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= @@ -1240,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.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +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/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= @@ -1267,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.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= 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= @@ -1341,13 +1330,11 @@ 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-20210225134936-a50acf3fe073/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= @@ -1380,18 +1367,17 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc 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= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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/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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +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/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= @@ -1409,6 +1395,8 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1464,7 +1452,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1532,8 +1519,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.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= -google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +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/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= @@ -1582,10 +1569,8 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= From 135b161f1781981f9049878ce15bb10ef90e65a1 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Wed, 7 Feb 2024 17:23:36 +0800 Subject: [PATCH 64/66] fix(poller): Next height should not be set with a lower value (#235) --- finality-provider/service/chain_poller.go | 168 +++++++++++------- .../service/chain_poller_test.go | 148 +++++++++++++++ finality-provider/service/fp_instance.go | 11 +- 3 files changed, 265 insertions(+), 62 deletions(-) create mode 100644 finality-provider/service/chain_poller_test.go diff --git a/finality-provider/service/chain_poller.go b/finality-provider/service/chain_poller.go index 8e674587..9dcba37b 100644 --- a/finality-provider/service/chain_poller.go +++ b/finality-provider/service/chain_poller.go @@ -6,6 +6,7 @@ import ( "time" "github.com/avast/retry-go/v4" + "go.uber.org/atomic" "go.uber.org/zap" "github.com/babylonchain/finality-provider/clientcontroller" @@ -26,18 +27,26 @@ const ( maxFailedCycles = 20 ) +type skipHeightRequest struct { + height uint64 + resp chan *skipHeightResponse +} + +type skipHeightResponse struct { + err error +} + type ChainPoller struct { - startOnce sync.Once - stopOnce sync.Once + isStarted *atomic.Bool wg sync.WaitGroup - mu sync.Mutex quit chan struct{} - cc clientcontroller.ClientController - cfg *cfg.ChainPollerConfig - blockInfoChan chan *types.BlockInfo - nextHeight uint64 - logger *zap.Logger + cc clientcontroller.ClientController + cfg *cfg.ChainPollerConfig + blockInfoChan chan *types.BlockInfo + skipHeightChan chan *skipHeightRequest + nextHeight uint64 + logger *zap.Logger } func NewChainPoller( @@ -46,48 +55,59 @@ func NewChainPoller( cc clientcontroller.ClientController, ) *ChainPoller { return &ChainPoller{ - logger: logger, - cfg: cfg, - cc: cc, - blockInfoChan: make(chan *types.BlockInfo, cfg.BufferSize), - quit: make(chan struct{}), + isStarted: atomic.NewBool(false), + logger: logger, + cfg: cfg, + cc: cc, + blockInfoChan: make(chan *types.BlockInfo, cfg.BufferSize), + skipHeightChan: make(chan *skipHeightRequest), + quit: make(chan struct{}), } } func (cp *ChainPoller) Start(startHeight uint64) error { - var startErr error - cp.startOnce.Do(func() { - cp.logger.Info("Starting the chain poller") + if cp.isStarted.Swap(true) { + return fmt.Errorf("the poller is already started") + } - err := cp.validateStartHeight(startHeight) - if err != nil { - startErr = err - return - } + cp.logger.Info("starting the chain poller") + + err := cp.validateStartHeight(startHeight) + if err != nil { + return fmt.Errorf("invalid starting height %d: %w", startHeight, err) + } - cp.nextHeight = startHeight + cp.nextHeight = startHeight - cp.wg.Add(1) + cp.wg.Add(1) - go cp.pollChain() - }) - return startErr + go cp.pollChain() + + cp.logger.Info("the chain poller is successfully started") + + return nil } func (cp *ChainPoller) Stop() error { - var stopError error - cp.stopOnce.Do(func() { - cp.logger.Info("Stopping the chain poller") - err := cp.cc.Close() - if err != nil { - stopError = err - return - } - close(cp.quit) - cp.wg.Wait() - }) + if !cp.isStarted.Swap(false) { + return fmt.Errorf("the chain poller has already stopped") + } + + cp.logger.Info("stopping the chain poller") + err := cp.cc.Close() + if err != nil { + return err + } + close(cp.quit) + cp.wg.Wait() - return stopError + cp.logger.Info("the chain poller is successfully stopped") + + return nil +} + +func (cp *ChainPoller) IsRunning() bool { + return cp.isStarted.Load() } // Return read only channel for incoming blocks @@ -184,8 +204,8 @@ func (cp *ChainPoller) waitForActivation() { if err != nil { cp.logger.Debug("failed to query the consumer chain for the activated height", zap.Error(err)) } else { - if cp.GetNextHeight() < activatedHeight { - cp.SetNextHeight(activatedHeight) + if cp.nextHeight < activatedHeight { + cp.nextHeight = activatedHeight } return } @@ -210,7 +230,7 @@ func (cp *ChainPoller) pollChain() { for { // TODO: Handlig of request cancellation, as otherwise shutdown will be blocked // until request is finished - blockToRetrieve := cp.GetNextHeight() + blockToRetrieve := cp.nextHeight block, err := cp.blockWithRetry(blockToRetrieve) if err != nil { failedCycles++ @@ -223,7 +243,7 @@ func (cp *ChainPoller) pollChain() { } else { // no error and we got the header we wanted to get, bump the state and push // notification about data - cp.SetNextHeight(blockToRetrieve + 1) + cp.nextHeight = blockToRetrieve + 1 failedCycles = 0 cp.logger.Info("the poller retrieved the block from the consumer chain", @@ -242,35 +262,63 @@ func (cp *ChainPoller) pollChain() { select { case <-time.After(cp.cfg.PollInterval): + case req := <-cp.skipHeightChan: + // no need to skip heights if the target height is not higher + // than the next height to retrieve + targetHeight := req.height + if targetHeight <= cp.nextHeight { + resp := &skipHeightResponse{ + err: fmt.Errorf( + "the target height %d is not higher than the next height %d to retrieve", + targetHeight, cp.nextHeight)} + req.resp <- resp + continue + } + + // drain blocks that can be skipped from blockInfoChan + cp.clearChanBufferUpToHeight(targetHeight) + + // set the next height to the skip height + cp.nextHeight = targetHeight + + cp.logger.Debug("the poller has skipped height(s)", + zap.Uint64("next_height", req.height)) + + req.resp <- &skipHeightResponse{} + case <-cp.quit: return } } } -func (cp *ChainPoller) GetNextHeight() uint64 { - return cp.getNextHeight() -} +func (cp *ChainPoller) SkipToHeight(height uint64) error { + if !cp.IsRunning() { + return fmt.Errorf("the chain poller is stopped") + } -func (cp *ChainPoller) getNextHeight() uint64 { - cp.mu.Lock() - defer cp.mu.Unlock() - return cp.nextHeight -} + respChan := make(chan *skipHeightResponse, 1) -func (cp *ChainPoller) setNextHeight(height uint64) { - cp.mu.Lock() - defer cp.mu.Unlock() - cp.nextHeight = height -} + // this handles the case when the poller is stopped before the + // skip height request is sent + select { + case <-cp.quit: + return fmt.Errorf("the chain poller is stopped") + case cp.skipHeightChan <- &skipHeightRequest{height: height, resp: respChan}: + } -func (cp *ChainPoller) SetNextHeight(height uint64) { - cp.setNextHeight(height) + // this handles the case when the poller is stopped before + // the skip height request is returned + select { + case <-cp.quit: + return fmt.Errorf("the chain poller is stopped") + case resp := <-respChan: + return resp.err + } } -func (cp *ChainPoller) SetNextHeightAndClearBuffer(height uint64) { - cp.SetNextHeight(height) - cp.clearChanBufferUpToHeight(height) +func (cp *ChainPoller) NextHeight() uint64 { + return cp.nextHeight } func (cp *ChainPoller) clearChanBufferUpToHeight(upToHeight uint64) { diff --git a/finality-provider/service/chain_poller_test.go b/finality-provider/service/chain_poller_test.go new file mode 100644 index 00000000..8c5fdc90 --- /dev/null +++ b/finality-provider/service/chain_poller_test.go @@ -0,0 +1,148 @@ +package service_test + +import ( + "math/rand" + "sync" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" +) + +// FuzzChainPoller_Start tests the poller polling blocks +// in sequence +func FuzzChainPoller_Start(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + currentHeight := uint64(r.Int63n(100) + 1) + startHeight := currentHeight + 1 + endHeight := startHeight + uint64(r.Int63n(10)+1) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + } + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + + for i := startHeight; i <= endHeight; i++ { + resBlock := &types.BlockInfo{ + Height: i, + } + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() + } + + pollerCfg := fpcfg.DefaultChainPollerConfig() + pollerCfg.PollInterval = 10 * time.Millisecond + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + err := poller.Start(startHeight) + require.NoError(t, err) + defer func() { + err := poller.Stop() + require.NoError(t, err) + }() + + for i := startHeight; i <= endHeight; i++ { + select { + case info := <-poller.GetBlockInfoChan(): + require.Equal(t, i, info.Height) + case <-time.After(10 * time.Second): + t.Fatalf("Failed to get block info") + } + } + }) +} + +// FuzzChainPoller_SkipHeight tests the functionality of SkipHeight +func FuzzChainPoller_SkipHeight(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + currentHeight := uint64(r.Int63n(100) + 1) + startHeight := currentHeight + 1 + endHeight := startHeight + uint64(r.Int63n(10)+2) + skipHeight := endHeight + uint64(r.Int63n(10)+1) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + } + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + + for i := startHeight; i <= skipHeight; i++ { + resBlock := &types.BlockInfo{ + Height: i, + } + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() + } + + pollerCfg := fpcfg.DefaultChainPollerConfig() + pollerCfg.PollInterval = 1 * time.Second + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + // should expect error if the poller is not started + err := poller.SkipToHeight(skipHeight) + require.Error(t, err) + err = poller.Start(startHeight) + require.NoError(t, err) + defer func() { + err := poller.Stop() + require.NoError(t, err) + // should expect error if the poller is stopped + err = poller.SkipToHeight(skipHeight) + require.Error(t, err) + }() + + var wg sync.WaitGroup + wg.Add(1) + go func() { + wg.Done() + // insert a skipToHeight request with height lower than the next + // height to retrieve, expecting an error + err = poller.SkipToHeight(poller.NextHeight() - 1) + require.Error(t, err) + // insert a skipToHeight request with a height higher than the + // next height to retrieve + err = poller.SkipToHeight(skipHeight) + require.NoError(t, err) + }() + + skipped := false + for i := startHeight; i <= endHeight; i++ { + if skipped { + break + } + select { + case info := <-poller.GetBlockInfoChan(): + if info.Height == skipHeight { + skipped = true + } else { + require.Equal(t, i, info.Height) + } + case <-time.After(10 * time.Second): + t.Fatalf("Failed to get block info") + } + } + + wg.Wait() + + require.Equal(t, skipHeight+1, poller.NextHeight()) + }) +} diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go index 7b6a3c21..4864c08a 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -253,8 +253,15 @@ func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { zap.Uint64("last_processed_height", res.LastProcessedHeight), ) - // set the poller to fetch blocks that have not been processed - fp.poller.SetNextHeightAndClearBuffer(fp.GetLastProcessedHeight() + 1) + // inform the poller to skip to the next block of the last + // processed one + err := fp.poller.SkipToHeight(fp.GetLastProcessedHeight() + 1) + if err != nil { + fp.logger.Debug( + "failed to skip heights from the poller", + zap.Error(err), + ) + } } case <-fp.quit: fp.logger.Info("the finality signature submission loop is closing") From 53d457133e2a532b568a117f48d313aca5f83c95 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 8 Feb 2024 18:00:24 +0800 Subject: [PATCH 65/66] chore: Change default config value (#238) --- config/babylon.go | 4 +- finality-provider/config/config.go | 113 ++++++++++++++--------------- finality-provider/config/poller.go | 2 +- itest/e2e_test.go | 6 +- itest/test_manager.go | 4 +- testutil/datagen.go | 2 +- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/config/babylon.go b/config/babylon.go index 7567c28a..ee97f80b 100644 --- a/config/babylon.go +++ b/config/babylon.go @@ -33,8 +33,8 @@ func DefaultBBNConfig() BBNConfig { GRPCAddr: dc.GRPCAddr, AccountPrefix: dc.AccountPrefix, KeyringBackend: dc.KeyringBackend, - GasAdjustment: dc.GasAdjustment, - GasPrices: dc.GasPrices, + GasAdjustment: 1.5, + GasPrices: "0.002ubbn", Debug: dc.Debug, Timeout: dc.Timeout, // Setting this to relatively low value, out currnet babylon client (lens) will diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go index 5ff55e17..24bec710 100644 --- a/finality-provider/config/config.go +++ b/finality-provider/config/config.go @@ -17,28 +17,27 @@ import ( ) const ( - defaultChainName = "babylon" - defaultLogLevel = "info" - defaultLogDirname = "logs" - defaultLogFilename = "fpd.log" - defaultFinalityProviderKeyName = "finality-provider" - DefaultRPCPort = 12581 - defaultConfigFileName = "fpd.conf" - defaultNumPubRand = 100 - defaultNumPubRandMax = 100 - defaultMinRandHeightGap = 10 - defaultStatusUpdateInterval = 5 * time.Second - defaultRandomInterval = 5 * time.Second - defautlUnbondingSigSubmissionInterval = 20 * time.Second - defaultSubmitRetryInterval = 1 * time.Second - defaultFastSyncInterval = 20 * time.Second - defaultFastSyncLimit = 10 - defaultFastSyncGap = 6 - defaultMaxSubmissionRetries = 20 - defaultBitcoinNetwork = "simnet" - defaultDataDirname = "data" - defaultDBPath = "bbolt-fpd.db" - defaultMaxNumFinalityProviders = 3 + defaultChainName = "babylon" + defaultLogLevel = "info" + defaultLogDirname = "logs" + defaultLogFilename = "fpd.log" + defaultFinalityProviderKeyName = "finality-provider" + DefaultRPCPort = 12581 + defaultConfigFileName = "fpd.conf" + defaultNumPubRand = 100 + defaultNumPubRandMax = 200 + defaultMinRandHeightGap = 20 + defaultStatusUpdateInterval = 20 * time.Second + defaultRandomInterval = 30 * time.Second + defaultSubmitRetryInterval = 1 * time.Second + defaultFastSyncInterval = 10 * time.Second + defaultFastSyncLimit = 10 + defaultFastSyncGap = 3 + defaultMaxSubmissionRetries = 20 + defaultBitcoinNetwork = "signet" + defaultDataDirname = "data" + defaultDBPath = "bbolt-fpd.db" + defaultMaxNumFinalityProviders = 3 ) var ( @@ -47,7 +46,7 @@ var ( // ~/Users//Library/Application Support/Fpd on MacOS DefaultFpdDir = btcutil.AppDataDir("fpd", false) - defaultBTCNetParams = chaincfg.SimNetParams + defaultBTCNetParams = chaincfg.SigNetParams defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) DefaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) ) @@ -56,20 +55,19 @@ 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"` // ChainName and ChainID (if any) of the chain config identify a consumer chain - ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` - NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` - NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` - MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` - StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"` - RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` - SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` - UnbondingSigSubmissionInterval time.Duration `long:"unbondingsigsubmissioninterval" description:"The interval between each attempt to check and submit unbonding signature"` - MaxSubmissionRetries uint64 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"` - FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"` - FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` - FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` - EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` - MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"` + ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` + NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` + NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` + MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` + StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"` + RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` + SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` + MaxSubmissionRetries uint64 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"` + FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"` + FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` + FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` + EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` + MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"` BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` @@ -91,27 +89,26 @@ func DefaultConfigWithHome(homePath string) Config { dbCfg := config.DefaultDatabaseConfig() pollerCfg := DefaultChainPollerConfig() cfg := Config{ - ChainName: defaultChainName, - LogLevel: defaultLogLevel, - DatabaseConfig: &dbCfg, - BabylonConfig: &bbnCfg, - PollerConfig: &pollerCfg, - NumPubRand: defaultNumPubRand, - NumPubRandMax: defaultNumPubRandMax, - MinRandHeightGap: defaultMinRandHeightGap, - StatusUpdateInterval: defaultStatusUpdateInterval, - RandomnessCommitInterval: defaultRandomInterval, - SubmissionRetryInterval: defaultSubmitRetryInterval, - UnbondingSigSubmissionInterval: defautlUnbondingSigSubmissionInterval, - FastSyncInterval: defaultFastSyncInterval, - FastSyncLimit: defaultFastSyncLimit, - FastSyncGap: defaultFastSyncGap, - MaxSubmissionRetries: defaultMaxSubmissionRetries, - BitcoinNetwork: defaultBitcoinNetwork, - BTCNetParams: defaultBTCNetParams, - EOTSManagerAddress: defaultEOTSManagerAddress, - RpcListener: DefaultRpcListener, - MaxNumFinalityProviders: defaultMaxNumFinalityProviders, + ChainName: defaultChainName, + LogLevel: defaultLogLevel, + DatabaseConfig: &dbCfg, + BabylonConfig: &bbnCfg, + PollerConfig: &pollerCfg, + NumPubRand: defaultNumPubRand, + NumPubRandMax: defaultNumPubRandMax, + MinRandHeightGap: defaultMinRandHeightGap, + StatusUpdateInterval: defaultStatusUpdateInterval, + RandomnessCommitInterval: defaultRandomInterval, + SubmissionRetryInterval: defaultSubmitRetryInterval, + FastSyncInterval: defaultFastSyncInterval, + FastSyncLimit: defaultFastSyncLimit, + FastSyncGap: defaultFastSyncGap, + MaxSubmissionRetries: defaultMaxSubmissionRetries, + BitcoinNetwork: defaultBitcoinNetwork, + BTCNetParams: defaultBTCNetParams, + EOTSManagerAddress: defaultEOTSManagerAddress, + RpcListener: DefaultRpcListener, + MaxNumFinalityProviders: defaultMaxNumFinalityProviders, } if err := cfg.Validate(); err != nil { diff --git a/finality-provider/config/poller.go b/finality-provider/config/poller.go index 1ee1fee1..6184ccfc 100644 --- a/finality-provider/config/poller.go +++ b/finality-provider/config/poller.go @@ -4,7 +4,7 @@ import "time" var ( defaultBufferSize = uint32(1000) - defaultPollingInterval = 5 * time.Second + defaultPollingInterval = 20 * time.Second defaultStaticStartHeight = uint64(1) ) diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 23a0f775..4139b3fe 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -250,6 +250,8 @@ func TestFastSync_DuplicateVotes(t *testing.T) { require.NoError(t, err) err = fpIns3.Start() require.NoError(t, err) - finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) - require.GreaterOrEqual(t, finalizedBlocks[0].Height, lastVotedHeight) + require.Eventually(t, func() bool { + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) + return finalizedBlocks[0].Height > lastVotedHeight + }, eventuallyWaitTimeOut, eventuallyPollTime) } diff --git a/itest/test_manager.go b/itest/test_manager.go index 867a6fa5..e89ec430 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -652,6 +652,9 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKe func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { cfg := fpcfg.DefaultConfigWithHome(homeDir) + cfg.BitcoinNetwork = "simnet" + cfg.BTCNetParams = chaincfg.SimNetParams + cfg.PollerConfig.AutoChainScanningMode = false // babylon configs for sending transactions cfg.BabylonConfig.KeyDirectory = keyringDir @@ -660,7 +663,6 @@ func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { cfg.BabylonConfig.Key = "test-spending-key" // Big adjustment to make sure we have enough gas in our transactions cfg.BabylonConfig.GasAdjustment = 20 - cfg.UnbondingSigSubmissionInterval = 3 * time.Second return &cfg } diff --git a/testutil/datagen.go b/testutil/datagen.go index f556bd3f..64c0ec1b 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -66,7 +66,7 @@ func GenRandomFinalityProvider(r *rand.Rand, t *testing.T) *proto.StoreFinalityP // generate and verify PoP, correct case pop, err := bstypes.NewPoP(babylonSK, btcSK) require.NoError(t, err) - err = pop.Verify(babylonPK, bip340PK, &chaincfg.SigNetParams) + err = pop.Verify(babylonPK, bip340PK, &chaincfg.SimNetParams) require.NoError(t, err) return &proto.StoreFinalityProvider{ From dbfe3632bb213560af71e0323a45bbccc1d66000 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 8 Feb 2024 18:19:56 +0800 Subject: [PATCH 66/66] chore: Bump Babylon to v0.8.0 (#239) --- go.mod | 4 ++-- go.sum | 8 ++++---- tools/go.mod | 2 +- tools/go.sum | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 208fc4c1..ff2e9477 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.2.0 github.com/avast/retry-go/v4 v4.5.1 - github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b - github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 + github.com/babylonchain/babylon v0.8.0 + github.com/babylonchain/rpc-client v0.8.0 github.com/btcsuite/btcd v0.24.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.5 diff --git a/go.sum b/go.sum index f3df0b7d..ffc99b3b 100644 --- a/go.sum +++ b/go.sum @@ -275,10 +275,10 @@ 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-rc.0.0.20240205142652-d166d40b188b h1:J951fCTXQGa40HnmDpWtGeHoQQFc5a9L2k90nLwKINM= -github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= -github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2 h1:FWsneAs2tSact+VKJuwVtX6xjj10OtthA1np4AG2CQ4= -github.com/babylonchain/rpc-client v0.7.0-rc0.0.20240121104942-d8a42431b1c2/go.mod h1:3WkXcOZX2m0VvM4K6KshfiSQeTz3sSCjVw+NQ6Ayx2U= +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/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= diff --git a/tools/go.mod b/tools/go.mod index 715560e6..c5e1d2f4 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-rc.0.0.20240205142652-d166d40b188b +require github.com/babylonchain/babylon v0.8.0 require ( cloud.google.com/go v0.110.10 // indirect diff --git a/tools/go.sum b/tools/go.sum index 18211c36..0a2974f1 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -268,8 +268,8 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX 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-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b h1:J951fCTXQGa40HnmDpWtGeHoQQFc5a9L2k90nLwKINM= -github.com/babylonchain/babylon v0.8.0-rc.0.0.20240205142652-d166d40b188b/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= +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/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=