Skip to content

Commit 76acb6b

Browse files
authored
Merge pull request #18 from hyle-team/dev/resharing-btc
Dev/resharing btc
2 parents 48aa8a6 + 2837f7e commit 76acb6b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1525
-392
lines changed

build/docker-compose.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ services:
7474
volumes:
7575
- ./configs/tss1.local.yaml:/config.yaml
7676
- ./configs/shares/preparams1.json:/preparams.json
77-
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign"
77+
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign" #reshare bitcoin mjMvBFWrjoGNPkQV6YJgUz2MghnMUVi1VN --fee-rate=2 --outputs-count=5 --max-inputs-count=5"
7878
depends_on:
7979
vault_init:
8080
condition: service_completed_successfully
@@ -94,7 +94,7 @@ services:
9494
volumes:
9595
- ./configs/tss2.local.yaml:/config.yaml
9696
- ./configs/shares/preparams2.json:/preparams.json
97-
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign"
97+
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign" #reshare bitcoin mjMvBFWrjoGNPkQV6YJgUz2MghnMUVi1VN --fee-rate=2 --outputs-count=5 --max-inputs-count=5"
9898
depends_on:
9999
vault_init:
100100
condition: service_completed_successfully
@@ -114,7 +114,7 @@ services:
114114
volumes:
115115
- ./configs/tss3.local.yaml:/config.yaml
116116
- ./configs/shares/preparams3.json:/preparams.json
117-
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign"
117+
entrypoint: sh -c "tss-svc service migrate up && tss-svc service run sign" #reshare bitcoin mjMvBFWrjoGNPkQV6YJgUz2MghnMUVi1VN --fee-rate=2 --outputs-count=5 --max-inputs-count=5"
118118
depends_on:
119119
vault_init:
120120
condition: service_completed_successfully

cmd/service/run/keygen.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/hyle-team/tss-svc/internal/secrets"
1515
"github.com/hyle-team/tss-svc/internal/secrets/vault"
1616
"github.com/hyle-team/tss-svc/internal/tss"
17-
"github.com/hyle-team/tss-svc/internal/tss/session"
17+
keygenSession "github.com/hyle-team/tss-svc/internal/tss/session/keygen"
1818
"github.com/pkg/errors"
1919
"github.com/spf13/cobra"
2020
"golang.org/x/sync/errgroup"
@@ -60,7 +60,7 @@ var keygenCmd = &cobra.Command{
6060
cfg.Log().WithField("component", "connection_manager"),
6161
)
6262

63-
session := session.NewKeygenSession(
63+
session := keygenSession.NewKeygenSession(
6464
tss.LocalKeygenParty{
6565
PreParams: *preParams,
6666
Address: account.CosmosAddress(),

cmd/service/run/reshare/bitcoin.go

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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+
}

cmd/service/run/reshare/reshare.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package reshare
2+
3+
import "github.com/spf13/cobra"
4+
5+
func init() {
6+
registerCommands(Cmd)
7+
}
8+
9+
var Cmd = &cobra.Command{
10+
Use: "reshare",
11+
Short: "Command for service migration during key resharing",
12+
}
13+
14+
func registerCommands(cmd *cobra.Command) {
15+
cmd.AddCommand(reshareBtcCmd)
16+
}

cmd/service/run/run.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package run
22

33
import (
4+
"github.com/hyle-team/tss-svc/cmd/service/run/reshare"
45
"github.com/spf13/cobra"
56
)
67

@@ -14,6 +15,5 @@ var Cmd = &cobra.Command{
1415
}
1516

1617
func registerCommands(cmd *cobra.Command) {
17-
cmd.AddCommand(keygenCmd)
18-
cmd.AddCommand(signCmd)
18+
cmd.AddCommand(keygenCmd, signCmd, reshare.Cmd)
1919
}

cmd/service/run/sign.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/hyle-team/tss-svc/internal/secrets/vault"
2323
"github.com/hyle-team/tss-svc/internal/tss"
2424
"github.com/hyle-team/tss-svc/internal/tss/session"
25+
"github.com/hyle-team/tss-svc/internal/tss/session/signing"
2526
"github.com/pkg/errors"
2627
"github.com/spf13/cobra"
2728
)
@@ -114,7 +115,7 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou
114115
var sess RunnableTssSession
115116
switch chain.Type {
116117
case chains.TypeEVM:
117-
evmSession := session.NewEvmSigningSession(
118+
evmSession := signing.NewEvmSigningSession(
118119
tss.LocalSignParty{
119120
Address: account.CosmosAddress(),
120121
Share: share,
@@ -125,9 +126,12 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou
125126
db,
126127
logger.WithField("component", "signing_session"),
127128
).WithDepositFetcher(fetcher).WithClient(client.(*evm.Client)).WithCoreConnector(connector)
129+
if err = evmSession.Build(); err != nil {
130+
return errors.Wrap(err, "failed to build EVM session")
131+
}
128132
sess = evmSession
129133
case chains.TypeZano:
130-
zanoSession := session.NewZanoSigningSession(
134+
zanoSession := signing.NewZanoSigningSession(
131135
tss.LocalSignParty{
132136
Address: account.CosmosAddress(),
133137
Share: share,
@@ -138,9 +142,12 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou
138142
db,
139143
logger.WithField("component", "signing_session"),
140144
).WithDepositFetcher(fetcher).WithClient(client.(*zano.Client)).WithCoreConnector(connector)
145+
if err = zanoSession.Build(); err != nil {
146+
return errors.Wrap(err, "failed to build Zano session")
147+
}
141148
sess = zanoSession
142149
case chains.TypeBitcoin:
143-
btcSession := session.NewBitcoinSigningSession(
150+
btcSession := signing.NewBitcoinSigningSession(
144151
tss.LocalSignParty{
145152
Address: account.CosmosAddress(),
146153
Share: share,
@@ -151,6 +158,9 @@ func runSigningService(ctx context.Context, cfg config.Config, wg *sync.WaitGrou
151158
db,
152159
logger.WithField("component", "signing_session"),
153160
).WithDepositFetcher(fetcher).WithClient(client.(*bitcoin.Client)).WithCoreConnector(connector)
161+
if err = btcSession.Build(); err != nil {
162+
return errors.Wrap(err, "failed to build Bitcoin session")
163+
}
154164
sess = btcSession
155165
}
156166

cmd/service/sign.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/hyle-team/tss-svc/internal/p2p"
1515
"github.com/hyle-team/tss-svc/internal/secrets/vault"
1616
"github.com/hyle-team/tss-svc/internal/tss"
17-
"github.com/hyle-team/tss-svc/internal/tss/session"
17+
"github.com/hyle-team/tss-svc/internal/tss/session/signing"
1818
"github.com/pkg/errors"
1919
"github.com/spf13/cobra"
2020
"golang.org/x/sync/errgroup"
@@ -68,13 +68,13 @@ var signCmd = &cobra.Command{
6868

6969
connectionManager := p2p.NewConnectionManager(cfg.Parties(), p2p.PartyStatus_PS_SIGN, cfg.Log().WithField("component", "connection_manager"))
7070

71-
session := session.NewDefaultSigningSession(
71+
session := signing.NewDefaultSigningSession(
7272
tss.LocalSignParty{
7373
Address: account.CosmosAddress(),
7474
Share: localSaveData,
7575
Threshold: cfg.TssSessionParams().Threshold,
7676
},
77-
session.DefaultSigningSessionParams{
77+
signing.DefaultSigningSessionParams{
7878
SessionParams: cfg.TssSessionParams(),
7979
SigningData: []byte(dataToSign),
8080
},

docs/01_overview.md

+9
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,13 @@ Check the available commands and flags in the [CLI documentation](../cmd/README.
7171

7272
Check the [Running service documentation](./05_running-service.md) for more details on how to run the service in different modes.
7373

74+
---
75+
76+
## Key Resharing
77+
78+
To add or remove the parties from the TSS network, the key resharing process should be executed.
79+
It means that the secret shares of the new general system private key should be redistributed among the old/new parties.
80+
Also, the entire ecosystem should be reconfigured and the funds should be migrated to the new system.
81+
82+
Check the [Key Resharing](./06_key-resharing.md) documentation for more details on how to perform the key resharing process.
7483

docs/05_running-service.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ tss-svc service run keygen -c ./configs/config.yaml -o vault
2525
```
2626

2727
## Signing mode
28+
TODO: ADD

docs/06_key-resharing.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Key resharing
2+
3+
## Description
4+
Key resharing is the process that is executed when the number of parties in the TSS network is changed.
5+
It involves the whole ecosystem reconfiguration and funds migration to the new accounts.
6+
There are several steps that should be executed one by one to ensure the correct system operation.
7+
TODO: DESCRIBE ALL STEPS
8+
9+
## Steps
10+
11+
### 1. New key generation
12+
13+
### 2. EVM networks reconfiguration
14+
15+
### 3. Bitcoin network reconfiguration
16+
17+
#### 3.x. Funds migration to the new TSS bitcoin account
18+
Once the Bitcoin address was derived from the new general system public key, the funds should be migrated to it.
19+
Each TSS party should be configured with the new funds receiving address and be ready to start the service in Bitcoin resharing mode.
20+
Additionally, parties should agree on the max number of inputs to include for a single migration transaction and a tx commission rate before the resharing process wil be started.
21+
22+
If the total amount of UTXOs is greater than the maximum number of inputs, the Bitcoin resharing mode can and should be started several times until all the funds are migrated.
23+
24+
### 4. Zano network reconfiguration
25+
26+
### 5. Bridge module settings reconfiguration
27+
28+
### 6. Local TSS reconfiguration
29+
30+
### 7. TSS Vault secrets reconfiguration
31+
32+
### 8. System restart

internal/api/common/common.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func ValidateIdentifier(identifier *types.DepositIdentifier, client clients.Clie
2929
if client.Type() == chains.TypeZano {
3030
identifier.TxNonce = 0
3131
}
32-
32+
3333
return nil
3434
}
3535

internal/api/grpc/submit_withdraw.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package grpc
22

33
import (
44
"context"
5+
56
"github.com/hyle-team/tss-svc/internal/api/common"
67
"github.com/hyle-team/tss-svc/internal/api/ctx"
78
"github.com/hyle-team/tss-svc/internal/bridge"
89
"github.com/hyle-team/tss-svc/internal/bridge/clients"
910
"github.com/hyle-team/tss-svc/internal/db"
1011
"github.com/hyle-team/tss-svc/internal/p2p"
1112
"github.com/hyle-team/tss-svc/internal/types"
13+
"github.com/pkg/errors"
1214
"google.golang.org/grpc/codes"
1315
"google.golang.org/grpc/status"
1416
"google.golang.org/protobuf/types/known/anypb"
@@ -36,21 +38,20 @@ func (Implementation) SubmitWithdrawal(ctxt context.Context, identifier *types.D
3638
return nil, status.Error(codes.InvalidArgument, err.Error())
3739
}
3840

39-
d, err := coreConnector.GetDepositInfo(identifier)
41+
existingDeposit, err := coreConnector.GetDepositInfo(identifier)
4042
if err != nil {
4143
logger.WithError(err).Error("error checking deposit info on core")
4244
return nil, ErrInternal
4345
}
44-
if d != nil {
45-
return nil, ErrTxAlreadySubmitted
46+
if existingDeposit != nil {
47+
return nil, status.Error(codes.AlreadyExists, "deposit already exists")
4648
}
4749

4850
id := db.DepositIdentifier{
4951
ChainId: identifier.ChainId,
5052
TxHash: identifier.TxHash,
5153
TxNonce: int(identifier.TxNonce),
5254
}
53-
5455
deposit, err := data.Get(id)
5556
if err != nil {
5657
logger.WithError(err).Error("error getting deposit")
@@ -83,6 +84,10 @@ func (Implementation) SubmitWithdrawal(ctxt context.Context, identifier *types.D
8384
}
8485

8586
if _, err = data.Insert(*deposit); err != nil {
87+
if errors.Is(err, db.ErrAlreadySubmitted) {
88+
return nil, ErrTxAlreadySubmitted
89+
}
90+
8691
logger.WithError(err).Error("failed to save deposit")
8792
return nil, ErrInternal
8893
}

0 commit comments

Comments
 (0)