|
| 1 | +package reshare |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "os/signal" |
| 7 | + "syscall" |
| 8 | + |
| 9 | + "github.com/hyle-team/tss-svc/cmd/utils" |
| 10 | + "github.com/hyle-team/tss-svc/internal/bridge/chains" |
| 11 | + "github.com/hyle-team/tss-svc/internal/bridge/clients/bitcoin" |
| 12 | + "github.com/hyle-team/tss-svc/internal/p2p" |
| 13 | + "github.com/hyle-team/tss-svc/internal/secrets/vault" |
| 14 | + "github.com/hyle-team/tss-svc/internal/tss" |
| 15 | + "github.com/hyle-team/tss-svc/internal/tss/session/resharing" |
| 16 | + "github.com/pkg/errors" |
| 17 | + "github.com/spf13/cobra" |
| 18 | + "golang.org/x/sync/errgroup" |
| 19 | +) |
| 20 | + |
| 21 | +var consolidateParams = bitcoin.DefaultConsolidateOutputsParams |
| 22 | + |
| 23 | +func init() { |
| 24 | + registerReshareBtcOptions(reshareBtcCmd) |
| 25 | +} |
| 26 | + |
| 27 | +func registerReshareBtcOptions(cmd *cobra.Command) { |
| 28 | + cmd.Flags().Uint64Var(&consolidateParams.FeeRate, "fee-rate", consolidateParams.FeeRate, "Fee rate for the transaction (sats/vbyte)") |
| 29 | + cmd.Flags().IntVar(&consolidateParams.OutputsCount, "outputs-count", consolidateParams.OutputsCount, "Number of outputs to split the funds into") |
| 30 | + cmd.Flags().IntVar(&consolidateParams.MaxInputsCount, "max-inputs-count", consolidateParams.MaxInputsCount, "Maximum number of inputs to use in the transaction") |
| 31 | +} |
| 32 | + |
| 33 | +var reshareBtcCmd = &cobra.Command{ |
| 34 | + Use: "bitcoin [target-addr]", |
| 35 | + Short: "Command for service migration during key resharing for Bitcoin", |
| 36 | + Args: cobra.ExactArgs(1), |
| 37 | + RunE: func(cmd *cobra.Command, args []string) error { |
| 38 | + cfg, err := utils.ConfigFromFlags(cmd) |
| 39 | + if err != nil { |
| 40 | + return errors.Wrap(err, "failed to get config from flags") |
| 41 | + } |
| 42 | + |
| 43 | + storage := vault.NewStorage(cfg.VaultClient()) |
| 44 | + share, err := storage.GetTssShare() |
| 45 | + if err != nil { |
| 46 | + return errors.Wrap(err, "failed to get tss share") |
| 47 | + } |
| 48 | + account, err := storage.GetCoreAccount() |
| 49 | + if err != nil { |
| 50 | + return errors.Wrap(err, "failed to get core account") |
| 51 | + } |
| 52 | + |
| 53 | + var client *bitcoin.Client |
| 54 | + for _, chain := range cfg.Chains() { |
| 55 | + if chain.Type == chains.TypeBitcoin { |
| 56 | + client = bitcoin.NewBridgeClient(chain.Bitcoin()) |
| 57 | + break |
| 58 | + } |
| 59 | + } |
| 60 | + if client == nil { |
| 61 | + return errors.New("bitcoin client configuration not found") |
| 62 | + } |
| 63 | + |
| 64 | + connectionManager := p2p.NewConnectionManager( |
| 65 | + cfg.Parties(), |
| 66 | + p2p.PartyStatus_PS_RESHARE, |
| 67 | + cfg.Log().WithField("component", "connection_manager"), |
| 68 | + ) |
| 69 | + |
| 70 | + session := resharing.NewBitcoinResharingSession( |
| 71 | + tss.LocalSignParty{ |
| 72 | + Address: account.CosmosAddress(), |
| 73 | + Share: share, |
| 74 | + Threshold: cfg.TssSessionParams().Threshold, |
| 75 | + }, |
| 76 | + client, |
| 77 | + resharing.BitcoinResharingSessionParams{ |
| 78 | + ConsolidateParams: consolidateParams, |
| 79 | + SessionParams: cfg.TssSessionParams(), |
| 80 | + }, |
| 81 | + cfg.Parties(), |
| 82 | + connectionManager.GetReadyCount, |
| 83 | + cfg.Log().WithField("component", "btc_reshare_session"), |
| 84 | + ) |
| 85 | + |
| 86 | + sessionManager := p2p.NewSessionManager(session) |
| 87 | + |
| 88 | + errGroup := new(errgroup.Group) |
| 89 | + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT) |
| 90 | + defer cancel() |
| 91 | + |
| 92 | + errGroup.Go(func() error { |
| 93 | + server := p2p.NewServer(cfg.P2pGrpcListener(), sessionManager) |
| 94 | + server.SetStatus(p2p.PartyStatus_PS_RESHARE) |
| 95 | + return server.Run(ctx) |
| 96 | + }) |
| 97 | + |
| 98 | + errGroup.Go(func() error { |
| 99 | + defer cancel() |
| 100 | + |
| 101 | + if err := session.Run(ctx); err != nil { |
| 102 | + return errors.Wrap(err, "failed to run bitcoin resharing session") |
| 103 | + } |
| 104 | + txHash, err := session.WaitFor() |
| 105 | + if err != nil { |
| 106 | + return errors.Wrap(err, "failed to obtain migration tx hash") |
| 107 | + } |
| 108 | + if txHash == "" { |
| 109 | + cfg.Log().Info("local party is not a part of the resharing session") |
| 110 | + return nil |
| 111 | + } |
| 112 | + |
| 113 | + cfg.Log().Info("bitcoin resharing session successfully completed") |
| 114 | + cfg.Log().Info(fmt.Sprintf("Migration transaction hash: %s", txHash)) |
| 115 | + |
| 116 | + return nil |
| 117 | + }) |
| 118 | + |
| 119 | + return errGroup.Wait() |
| 120 | + }, |
| 121 | +} |
0 commit comments