This repository has been archived by the owner on May 10, 2023. It is now read-only.
/
key_rotate.go
167 lines (139 loc) · 4.26 KB
/
key_rotate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package cmd
import (
"fmt"
"io"
"code.vegaprotocol.io/vegawallet/cmd/cli"
"code.vegaprotocol.io/vegawallet/cmd/flags"
"code.vegaprotocol.io/vegawallet/cmd/printer"
"code.vegaprotocol.io/vegawallet/wallet"
"code.vegaprotocol.io/vegawallet/wallets"
"github.com/spf13/cobra"
)
var (
rotateKeyLong = cli.LongDesc(`
Build a signed key rotation transaction as a Base64 encoded string.
Choose a public key to rotate to and target block height.
The generated transaction can be sent using the command: "tx send".
`)
rotateKeyExample = cli.Examples(`
# Build signed transaction for rotating to new key public key
vegawallet key rotate --wallet WALLET --tx-height TX_HEIGHT --target-height TARGET_HEIGHT --pubkey PUBLIC_KEY --current-pubkey CURRENT_PUBLIC_KEY
`)
)
type RotateKeyHandler func(*wallet.RotateKeyRequest) (*wallet.RotateKeyResponse, error)
func NewCmdRotateKey(w io.Writer, rf *RootFlags) *cobra.Command {
h := func(req *wallet.RotateKeyRequest) (*wallet.RotateKeyResponse, error) {
s, err := wallets.InitialiseStore(rf.Home)
if err != nil {
return nil, fmt.Errorf("couldn't initialise wallets store: %w", err)
}
return wallet.RotateKey(s, req)
}
return BuildCmdRotateKey(w, h, rf)
}
func BuildCmdRotateKey(w io.Writer, handler RotateKeyHandler, rf *RootFlags) *cobra.Command {
f := RotateKeyFlags{}
cmd := &cobra.Command{
Use: "rotate",
Short: "Build a signed key rotation transaction",
Long: rotateKeyLong,
Example: rotateKeyExample,
RunE: func(_ *cobra.Command, args []string) error {
req, err := f.Validate()
if err != nil {
return err
}
resp, err := handler(req)
if err != nil {
return err
}
switch rf.Output {
case flags.InteractiveOutput:
PrintRotateKeyResponse(w, resp)
case flags.JSONOutput:
return printer.FprintJSON(w, resp)
}
return nil
},
}
cmd.Flags().StringVarP(&f.Wallet,
"wallet", "w",
"",
"Wallet holding the master key and new public key",
)
cmd.Flags().StringVarP(&f.PassphraseFile,
"passphrase-file", "p",
"",
"Path to the file containing the wallet's passphrase",
)
cmd.Flags().StringVar(&f.NewPublicKey,
"new-pubkey",
"",
"A public key to rotate to. Should be generated by wallet's 'generate' command.",
)
cmd.Flags().StringVar(&f.CurrentPubKey,
"current-pubkey",
"",
"A public key to rotate from. Should be currently used public key.",
)
cmd.Flags().Uint64Var(&f.TxBlockHeight,
"tx-height",
0,
"It should be close to the current block height when the transaction is applied, with a threshold of ~ - 150 blocks.",
)
cmd.Flags().Uint64Var(&f.TargetBlockHeight,
"target-height",
0,
"Height of block where the public key change will take effect",
)
autoCompleteWallet(cmd, rf.Home)
return cmd
}
type RotateKeyFlags struct {
Wallet string
PassphraseFile string
NewPublicKey string
CurrentPubKey string
TxBlockHeight uint64
TargetBlockHeight uint64
}
func (f *RotateKeyFlags) Validate() (*wallet.RotateKeyRequest, error) {
req := &wallet.RotateKeyRequest{}
if f.NewPublicKey == "" {
return nil, flags.FlagMustBeSpecifiedError("new-pubkey")
}
req.NewPublicKey = f.NewPublicKey
if f.CurrentPubKey == "" {
return nil, flags.FlagMustBeSpecifiedError("current-pubkey")
}
req.CurrentPublicKey = f.CurrentPubKey
if f.TargetBlockHeight == 0 {
return nil, flags.FlagMustBeSpecifiedError("target-height")
}
req.TargetBlockHeight = f.TargetBlockHeight
if f.TxBlockHeight == 0 {
return nil, flags.FlagMustBeSpecifiedError("tx-height")
}
req.TxBlockHeight = f.TxBlockHeight
if req.TargetBlockHeight <= req.TxBlockHeight {
return nil, flags.FlagRequireLessThanFlagError("tx-height", "target-height")
}
if len(f.Wallet) == 0 {
return nil, flags.FlagMustBeSpecifiedError("wallet")
}
req.Wallet = f.Wallet
passphrase, err := flags.GetPassphrase(f.PassphraseFile)
if err != nil {
return nil, err
}
req.Passphrase = passphrase
return req, nil
}
func PrintRotateKeyResponse(w io.Writer, req *wallet.RotateKeyResponse) {
p := printer.NewInteractivePrinter(w)
p.CheckMark().SuccessText("Key rotation succeeded").NextSection()
p.Text("Transaction (base64-encoded):").NextLine()
p.Text(req.Base64Transaction).NextLine()
p.Text("Master public key used:").NextLine()
p.Text(req.MasterPublicKey).NextLine()
}