Skip to content

Commit 1c3e5c4

Browse files
authored
Merge pull request #127 from initia-labs/feat/keyfile-address
feat: add address to keyfile structs
2 parents 8e4848e + 248463b commit 1c3e5c4

File tree

7 files changed

+145
-72
lines changed

7 files changed

+145
-72
lines changed

cmd/opinit_bots.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ func handleWithConfig(cmd *cobra.Command, userHome, opInitHome, configPath, keyF
171171
return err
172172
}
173173

174-
var keyFile *weaveio.KeyFile
174+
var keyFile weaveio.KeyFile
175175
if isGenerateKeyFile {
176176
keyPath := filepath.Join(userHome, common.WeaveDataDirectory, fmt.Sprintf("%s.%s.keyfile", common.OpinitGeneratedKeyFilename, botName))
177-
keyFile, err = opinit_bots.GenerateMnemonicKeyfile(botName)
177+
keyFile, err = opinit_bots.GenerateMnemonicKeyfile(fileData, botName)
178178
if err != nil {
179179
return fmt.Errorf("error generating keyfile: %v", err)
180180
}
@@ -208,14 +208,14 @@ func handleWithConfig(cmd *cobra.Command, userHome, opInitHome, configPath, keyF
208208
}
209209

210210
// readAndUnmarshalKeyFile read and unmarshal the key file into the KeyFile struct
211-
func readAndUnmarshalKeyFile(keyFilePath string) (*weaveio.KeyFile, error) {
211+
func readAndUnmarshalKeyFile(keyFilePath string) (weaveio.KeyFile, error) {
212212
fileData, err := os.ReadFile(keyFilePath)
213213
if err != nil {
214214
return nil, err
215215
}
216216

217-
keyFile := &weaveio.KeyFile{}
218-
err = json.Unmarshal(fileData, keyFile)
217+
keyFile := weaveio.KeyFile{}
218+
err = json.Unmarshal(fileData, &keyFile)
219219
return keyFile, err
220220
}
221221

@@ -239,7 +239,7 @@ func handleExistingOpInitHome(opInitHome string, botName string, force bool) err
239239
}
240240

241241
// initializeBotWithConfig initialize a bot based on the provided config
242-
func initializeBotWithConfig(cmd *cobra.Command, fileData []byte, keyFile *weaveio.KeyFile, opInitHome, userHome, botName string) error {
242+
func initializeBotWithConfig(cmd *cobra.Command, fileData []byte, keyFile weaveio.KeyFile, opInitHome, userHome, botName string) error {
243243
var err error
244244

245245
switch botName {
@@ -345,9 +345,9 @@ func OPInitBotsInitCommand() *cobra.Command {
345345
initCmd.Flags().String(FlagMinitiaHome, filepath.Join(homeDir, common.MinitiaDirectory), "Rollup application directory to fetch artifacts from if existed")
346346
initCmd.Flags().String(FlagOPInitHome, filepath.Join(homeDir, common.OPinitDirectory), "OPInit bots home directory")
347347
initCmd.Flags().String(FlagWithConfig, "", "Bypass the interactive setup and initialize the bot by providing a path to a config file. Either --key-file or --generate-key-file has to be specified")
348-
initCmd.Flags().String(FlagKeyFile, "", "Use this flag to generate the bot keys. Cannot be specified together with --key-file")
348+
initCmd.Flags().String(FlagKeyFile, "", "Path to key-file.json. Cannot be specified together with --generate-key-file")
349349
initCmd.Flags().BoolP(FlagForce, "f", false, "Force the setup by deleting the existing .opinit directory if it exists")
350-
initCmd.Flags().BoolP(FlagGenerateKeyFile, "", false, "Path to key-file.json. Cannot be specified together with --generate-key-file")
350+
initCmd.Flags().BoolP(FlagGenerateKeyFile, "", false, "Use this flag to generate the bot keys. Cannot be specified together with --key-file")
351351

352352
return initCmd
353353
}

io/keyfile.go

+53-10
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,67 @@ import (
44
"encoding/json"
55
"fmt"
66
"os"
7+
8+
"github.com/initia-labs/weave/crypto"
79
)
810

9-
type KeyFile map[string]string
11+
type Key struct {
12+
Address string `json:"address"`
13+
Mnemonic string `json:"mnemonic"`
14+
}
15+
16+
func NewKey(address, mnemonic string) *Key {
17+
return &Key{
18+
Address: address,
19+
Mnemonic: mnemonic,
20+
}
21+
}
22+
23+
func GenerateKey(hrp string) (*Key, error) {
24+
mnemonic, err := crypto.GenerateMnemonic()
25+
if err != nil {
26+
return nil, fmt.Errorf("failed to generate mnemonic: %w", err)
27+
}
28+
29+
address, err := crypto.MnemonicToBech32Address(hrp, mnemonic)
30+
if err != nil {
31+
return nil, fmt.Errorf("failed to derive address: %w", err)
32+
}
33+
34+
return &Key{
35+
Mnemonic: mnemonic,
36+
Address: address,
37+
}, nil
38+
}
39+
40+
func RecoverKey(hrp, mnemonic string) (*Key, error) {
41+
address, err := crypto.MnemonicToBech32Address(hrp, mnemonic)
42+
if err != nil {
43+
return nil, fmt.Errorf("failed to derive address: %w", err)
44+
}
45+
46+
return &Key{
47+
Mnemonic: mnemonic,
48+
Address: address,
49+
}, nil
50+
}
51+
52+
type KeyFile map[string]*Key
1053

11-
func NewKeyFile() *KeyFile {
54+
func NewKeyFile() KeyFile {
1255
kf := make(KeyFile)
13-
return &kf
56+
return kf
1457
}
1558

16-
func (k *KeyFile) AddMnemonic(name, mnemonic string) {
17-
(*k)[name] = mnemonic
59+
func (k KeyFile) AddKey(name string, key *Key) {
60+
k[name] = key
1861
}
1962

20-
func (k *KeyFile) GetMnemonic(name string) string {
21-
return (*k)[name]
63+
func (k KeyFile) GetMnemonic(name string) string {
64+
return k[name].Mnemonic
2265
}
2366

24-
func (k *KeyFile) Write(filePath string) error {
67+
func (k KeyFile) Write(filePath string) error {
2568
data, err := json.MarshalIndent(k, "", " ")
2669
if err != nil {
2770
return fmt.Errorf("error marshaling KeyFile to JSON: %w", err)
@@ -31,7 +74,7 @@ func (k *KeyFile) Write(filePath string) error {
3174
}
3275

3376
// Load tries to load an existing key file into the struct if the file exists
34-
func (k *KeyFile) Load(filePath string) error {
77+
func (k KeyFile) Load(filePath string) error {
3578
if _, err := os.Stat(filePath); os.IsNotExist(err) {
3679
return nil
3780
}
@@ -41,7 +84,7 @@ func (k *KeyFile) Load(filePath string) error {
4184
return fmt.Errorf("error reading file: %w", err)
4285
}
4386

44-
err = json.Unmarshal(data, k)
87+
err = json.Unmarshal(data, &k)
4588
if err != nil {
4689
return fmt.Errorf("error unmarshaling JSON: %w", err)
4790
}

models/opinit_bots/config.go

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package opinit_bots
22

33
import (
4+
"encoding/json"
45
"fmt"
56

6-
"github.com/initia-labs/weave/crypto"
77
weaveio "github.com/initia-labs/weave/io"
88
)
99

@@ -59,45 +59,51 @@ type ExecutorConfig struct {
5959
DisableDeleteFutureWithdrawal bool `json:"disable_delete_future_withdrawal"`
6060
}
6161

62-
func GenerateMnemonicKeyfile(botName string) (*weaveio.KeyFile, error) {
62+
func GenerateMnemonicKeyfile(rawConfig []byte, botName string) (weaveio.KeyFile, error) {
6363
keyFile := weaveio.NewKeyFile()
6464

6565
switch botName {
6666
case "executor":
67-
bridgeExecutor, err := crypto.GenerateMnemonic()
67+
var config ExecutorConfig
68+
err := json.Unmarshal(rawConfig, &config)
6869
if err != nil {
69-
return &weaveio.KeyFile{}, fmt.Errorf("failed to generate bridge executor mnemonic: %w", err)
70+
return nil, fmt.Errorf("failed to unmarshal executor config: %v", err)
7071
}
71-
keyFile.AddMnemonic(BridgeExecutorKeyName, bridgeExecutor)
7272

73-
outputSubmitter, err := crypto.GenerateMnemonic()
73+
bridgeExecutor, err := weaveio.GenerateKey("init")
7474
if err != nil {
75-
return &weaveio.KeyFile{}, fmt.Errorf("failed to generate output submitter mnemonic: %w", err)
75+
return nil, fmt.Errorf("failed to generate bridge executor mnemonic: %w", err)
7676
}
77-
keyFile.AddMnemonic(OutputSubmitterKeyName, outputSubmitter)
77+
keyFile.AddKey(BridgeExecutorKeyName, bridgeExecutor)
7878

79-
batchSubmitter, err := crypto.GenerateMnemonic()
79+
outputSubmitter, err := weaveio.GenerateKey("init")
8080
if err != nil {
81-
return &weaveio.KeyFile{}, fmt.Errorf("failed to generate batch submitter mnemonic: %w", err)
81+
return nil, fmt.Errorf("failed to generate output submitter mnemonic: %w", err)
8282
}
83-
keyFile.AddMnemonic(BatchSubmitterKeyName, batchSubmitter)
83+
keyFile.AddKey(OutputSubmitterKeyName, outputSubmitter)
8484

85-
oracleBridgeExecutor, err := crypto.GenerateMnemonic()
85+
batchSubmitter, err := weaveio.GenerateKey(config.DANode.Bech32Prefix)
8686
if err != nil {
87-
return &weaveio.KeyFile{}, fmt.Errorf("failed to generate oracle bridge executor mnemonic: %w", err)
87+
return nil, fmt.Errorf("failed to generate batch submitter mnemonic: %w", err)
8888
}
89-
keyFile.AddMnemonic(OracleBridgeExecutorKeyName, oracleBridgeExecutor)
89+
keyFile.AddKey(BatchSubmitterKeyName, batchSubmitter)
90+
91+
oracleBridgeExecutor, err := weaveio.GenerateKey("init")
92+
if err != nil {
93+
return nil, fmt.Errorf("failed to generate oracle bridge executor mnemonic: %w", err)
94+
}
95+
keyFile.AddKey(OracleBridgeExecutorKeyName, oracleBridgeExecutor)
9096

9197
return keyFile, nil
9298
case "challenger":
93-
challenger, err := crypto.GenerateMnemonic()
99+
challenger, err := weaveio.GenerateKey("init")
94100
if err != nil {
95-
return &weaveio.KeyFile{}, fmt.Errorf("failed to generate challenger mnemonic: %w", err)
101+
return nil, fmt.Errorf("failed to generate challenger mnemonic: %w", err)
96102
}
97-
keyFile.AddMnemonic(ChallengerKeyName, challenger)
103+
keyFile.AddKey(ChallengerKeyName, challenger)
98104

99105
return keyFile, nil
100106
default:
101-
return &weaveio.KeyFile{}, fmt.Errorf("unsupported bot name: %s", botName)
107+
return nil, fmt.Errorf("unsupported bot name: %s", botName)
102108
}
103109
}

models/opinit_bots/init.go

+27-26
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,31 @@ func WaitStartingInitBot(ctx context.Context) tea.Cmd {
10991099
}
11001100
}
11011101

1102+
keyFilePath, err := weavecontext.GetOPInitKeyFileJson(ctx)
1103+
if err != nil {
1104+
return ui.NonRetryableErrorLoading{Err: fmt.Errorf("failed to get key file path for OPinit: %w", err)}
1105+
}
1106+
1107+
keyFile := io.NewKeyFile()
1108+
err = keyFile.Load(keyFilePath)
1109+
if err != nil {
1110+
return ui.NonRetryableErrorLoading{Err: fmt.Errorf("failed to load key file for OPinit: %w", err)}
1111+
}
1112+
1113+
for _, botName := range BotNames {
1114+
if res, ok := state.SetupOpinitResponses[botName]; ok {
1115+
keyInfo := strings.Split(res, "\n")
1116+
address := strings.Split(keyInfo[0], ": ")
1117+
mnemonic := keyInfo[1]
1118+
keyFile.AddKey(string(BotNameToKeyName[botName]), io.NewKey(address[1], mnemonic))
1119+
}
1120+
}
1121+
1122+
err = keyFile.Write(keyFilePath)
1123+
if err != nil {
1124+
return ui.NonRetryableErrorLoading{Err: fmt.Errorf("failed to write key file: %w", err)}
1125+
}
1126+
11021127
if state.InitExecutorBot {
11031128
srv, err := service.NewService(service.OPinitExecutor)
11041129
if err != nil {
@@ -1345,30 +1370,6 @@ func (m *SetupOPInitBotsMissingKey) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
13451370
return model, nil
13461371
}
13471372

1348-
keyFilePath, err := weavecontext.GetOPInitKeyFileJson(m.Ctx)
1349-
if err != nil {
1350-
return m, m.HandlePanic(fmt.Errorf("failed to get key file path for OPinit: %w", err))
1351-
}
1352-
1353-
keyFile := io.NewKeyFile()
1354-
err = keyFile.Load(keyFilePath)
1355-
if err != nil {
1356-
return m, m.HandlePanic(fmt.Errorf("failed to load key file for OPinit: %w", err))
1357-
}
1358-
1359-
for _, botName := range BotNames {
1360-
if res, ok := state.SetupOpinitResponses[botName]; ok {
1361-
keyInfo := strings.Split(res, "\n")
1362-
mnemonic := keyInfo[1]
1363-
keyFile.AddMnemonic(string(BotNameToKeyName[botName]), mnemonic)
1364-
}
1365-
}
1366-
1367-
err = keyFile.Write(keyFilePath)
1368-
if err != nil {
1369-
return m, m.HandlePanic(fmt.Errorf("failed to write key file: %w", err))
1370-
}
1371-
13721373
switch msg := msg.(type) {
13731374
case tea.KeyMsg:
13741375
if msg.String() == "enter" {
@@ -1451,7 +1452,7 @@ func WaitSetupOPInitBotsMissingKey(ctx context.Context) tea.Cmd {
14511452
}
14521453
}
14531454

1454-
func InitializeExecutorWithConfig(config ExecutorConfig, keyFile *io.KeyFile, opInitHome, userHome string) error {
1455+
func InitializeExecutorWithConfig(config ExecutorConfig, keyFile io.KeyFile, opInitHome, userHome string) error {
14551456
binaryPath, err := ensureOPInitBotsBinary(userHome)
14561457
if err != nil {
14571458
return err
@@ -1524,7 +1525,7 @@ func InitializeExecutorWithConfig(config ExecutorConfig, keyFile *io.KeyFile, op
15241525
return nil
15251526
}
15261527

1527-
func InitializeChallengerWithConfig(config ChallengerConfig, keyFile *io.KeyFile, opInitHome, userHome string) error {
1528+
func InitializeChallengerWithConfig(config ChallengerConfig, keyFile io.KeyFile, opInitHome, userHome string) error {
15281529
binaryPath, err := ensureOPInitBotsBinary(userHome)
15291530
if err != nil {
15301531
return err

models/opinit_bots/setup.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,9 @@ func (m *SetupOPInitBots) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
468468

469469
for botName, res := range state.SetupOpinitResponses {
470470
keyInfo := strings.Split(res, "\n")
471+
address := strings.Split(keyInfo[0], ": ")
471472
mnemonic := keyInfo[1]
472-
keyFile.AddMnemonic(string(BotNameToKeyName[botName]), mnemonic)
473+
keyFile.AddKey(string(BotNameToKeyName[botName]), io.NewKey(address[1], mnemonic))
473474
}
474475

475476
err = keyFile.Write(keyFilePath)

models/relayer/constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ const (
99

1010
DefaultL1RelayerBalance = "1000000"
1111
DefaultL2RelayerBalance = "1000000"
12+
DefaultL1RelayerKeyName = "weave_l1_relayer"
13+
DefaultL2RelayerKeyName = "weave_l2_relayer"
1214
)

models/relayer/init.go

+29-9
Original file line numberDiff line numberDiff line change
@@ -617,10 +617,19 @@ func (m *KeysMnemonicDisplayInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
617617
if done {
618618
state := weavecontext.PushPageAndGetState[State](m)
619619

620+
l1RelayerKey, err := weaveio.RecoverKey("init", state.l1RelayerMnemonic)
621+
if err != nil {
622+
return m, m.HandlePanic(fmt.Errorf("cannot recover l1 relayer key: %w", err))
623+
}
624+
l2RelayerKey, err := weaveio.RecoverKey("init", state.l2RelayerMnemonic)
625+
if err != nil {
626+
return m, m.HandlePanic(fmt.Errorf("cannot recover l2 relayer key: %w", err))
627+
}
628+
620629
keyFile := weaveio.NewKeyFile()
621-
keyFile.AddMnemonic("weave_l1_relayer", state.l1RelayerMnemonic)
622-
keyFile.AddMnemonic("weave_l2_relayer", state.l2RelayerMnemonic)
623-
err := keyFile.Write(m.keyFilePath)
630+
keyFile.AddKey(DefaultL1RelayerKeyName, l1RelayerKey)
631+
keyFile.AddKey(DefaultL2RelayerKeyName, l2RelayerKey)
632+
err = keyFile.Write(m.keyFilePath)
624633
if err != nil {
625634
return m, m.HandlePanic(fmt.Errorf("failed to write key file: %w", err))
626635
}
@@ -2735,24 +2744,35 @@ func (m *AddChallengerKeyToRelayer) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
27352744
if err != nil {
27362745
return m, m.HandlePanic(err)
27372746
}
2738-
relayerKey, err := cosmosutils.RecoverAndReplaceHermesKey(state.hermesBinaryPath, l1ChainId, state.minitiaConfig.SystemKeys.Challenger.Mnemonic)
2747+
l1RelayerKey, err := cosmosutils.RecoverAndReplaceHermesKey(state.hermesBinaryPath, l1ChainId, state.minitiaConfig.SystemKeys.Challenger.Mnemonic)
27392748
if err != nil {
27402749
return m, m.HandlePanic(err)
27412750
}
2742-
state.l1RelayerAddress = relayerKey.Address
2743-
state.l1RelayerMnemonic = relayerKey.Mnemonic
2751+
state.l1RelayerAddress = l1RelayerKey.Address
2752+
state.l1RelayerMnemonic = l1RelayerKey.Mnemonic
27442753

27452754
l2ChainId, err := GetL2ChainId(m.Ctx)
27462755
if err != nil {
27472756
return m, m.HandlePanic(err)
27482757
}
2749-
relayerKey, err = cosmosutils.RecoverAndReplaceHermesKey(state.hermesBinaryPath, l2ChainId, state.minitiaConfig.SystemKeys.Challenger.Mnemonic)
2758+
l2RelayerKey, err := cosmosutils.RecoverAndReplaceHermesKey(state.hermesBinaryPath, l2ChainId, state.minitiaConfig.SystemKeys.Challenger.Mnemonic)
27502759
if err != nil {
27512760
return m, m.HandlePanic(err)
27522761
}
27532762

2754-
state.l2RelayerAddress = relayerKey.Address
2755-
state.l2RelayerMnemonic = relayerKey.Mnemonic
2763+
state.l2RelayerAddress = l2RelayerKey.Address
2764+
state.l2RelayerMnemonic = l2RelayerKey.Mnemonic
2765+
2766+
userHome, _ := os.UserHomeDir()
2767+
hermesKeyFile := filepath.Join(userHome, common.HermesKeyFileJson)
2768+
2769+
keyFile := weaveio.NewKeyFile()
2770+
keyFile.AddKey(DefaultL1RelayerKeyName, weaveio.NewKey(l1RelayerKey.Address, l1RelayerKey.Mnemonic))
2771+
keyFile.AddKey(DefaultL2RelayerKeyName, weaveio.NewKey(l2RelayerKey.Address, l2RelayerKey.Mnemonic))
2772+
err = keyFile.Write(hermesKeyFile)
2773+
if err != nil {
2774+
return m, m.HandlePanic(fmt.Errorf("failed to write key file: %w", err))
2775+
}
27562776

27572777
state.weave.PushPreviousResponse(getRelayerSetSuccessMessage())
27582778
return NewTerminalState(weavecontext.SetCurrentState(m.Ctx, state)), tea.Quit

0 commit comments

Comments
 (0)