From 99d6683745fb33ac0838828313b3ba4671b98b04 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 14:56:46 -0700 Subject: [PATCH 1/9] Create main.go --- tools/vanilla-stake/main.go | 183 ++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 tools/vanilla-stake/main.go diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go new file mode 100644 index 000000000..ccbf8011b --- /dev/null +++ b/tools/vanilla-stake/main.go @@ -0,0 +1,183 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "log" + "math/big" + "os" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/urfave/cli/v2" + + vanillaregistry "github.com/primev/mev-commit/contracts-abi/clients/VanillaRegistry" + "github.com/primev/mev-commit/x/keysigner" +) + +var ( + optionKeystorePath = &cli.StringFlag{ + Name: "keystore-dir", + Usage: "directory where keystore file is stored", + EnvVars: []string{"KEYSTORE_DIR"}, + Required: true, + } + optionKeystorePassword = &cli.StringFlag{ + Name: "keystore-password", + Usage: "use to access keystore", + EnvVars: []string{"KEYSTORE_PASSWORD"}, + Required: true, + } + optionL1RPCURL = &cli.StringFlag{ + Name: "l1-rpc-url", + Usage: "URL of the L1 RPC server", + EnvVars: []string{"L1_RPC_URL"}, + Required: true, + } + optionPubkeyFilePath = &cli.StringFlag{ + Name: "pubkey-file-path", + Usage: "path to the file containing the public keys", + EnvVars: []string{"PUBKEY_FILE_PATH"}, + Required: true, + } + optionVanillaRegistryAddress = &cli.StringFlag{ + Name: "vanilla-registry-address", + Usage: "address of the vanilla registry contract", + EnvVars: []string{"VANILLA_REGISTRY_ADDRESS"}, + Value: "0x47afdcB2B089C16CEe354811EA1Bbe0DB7c335E9", + } +) + +func main() { + + flags := []cli.Flag{ + optionKeystorePath, + optionKeystorePassword, + optionL1RPCURL, + optionPubkeyFilePath, + } + + app := &cli.App{ + Name: "vanill-stake", + Usage: "Stake validators programmatically with the mev-commit vanilla registry", + Flags: flags, + Action: func(c *cli.Context) error { + return stakeVanilla(c) + }, + } + + if err := app.Run(os.Args); err != nil { + log.Fatal(err) + } +} + +func stakeVanilla(c *cli.Context) error { + keystoreDir := c.String(optionKeystorePath.Name) + keystorePassword := c.String(optionKeystorePassword.Name) + l1RpcUrl := c.String(optionL1RPCURL.Name) + pubkeyFilePath := c.String(optionPubkeyFilePath.Name) + vanillaRegistryAddress := c.String(optionVanillaRegistryAddress.Name) + + signer, err := keysigner.NewKeystoreSigner(keystoreDir, keystorePassword) + if err != nil { + return fmt.Errorf("failed to create signer: %w", err) + } + + client, err := ethclient.Dial(l1RpcUrl) + if err != nil { + return fmt.Errorf("failed to connect to the Ethereum client: %w", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + chainID, err := client.ChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chain ID: %w", err) + } + + vrt, err := vanillaregistry.NewVanillaregistryTransactor(common.HexToAddress(vanillaRegistryAddress), client) + if err != nil { + return fmt.Errorf("failed to create Vanilla Registry transactor: %w", err) + } + + pksAsBytes, err := readBLSPublicKeysFromFile(pubkeyFilePath) + if err != nil { + return fmt.Errorf("failed to read public keys from file: %w", err) + } + + batchSize := 20 + type Batch struct { + pubKeys [][]byte + } + batches := make([]Batch, 0) + for i := 0; i < len(pksAsBytes); i += batchSize { + end := i + batchSize + if end > len(pksAsBytes) { + end = len(pksAsBytes) + } + batches = append(batches, Batch{pubKeys: pksAsBytes[i:end]}) + } + + for idx, batch := range batches { + + opts, err := signer.GetAuth(chainID) + if err != nil { + return fmt.Errorf("failed to create transact opts: %w", err) + } + + amountPerValidator := new(big.Int) + amountPerValidator.SetString("100000000000000", 10) // TODO: make configurable + totalAmount := new(big.Int).Mul(amountPerValidator, big.NewInt(int64(batchSize))) + opts.Value = totalAmount + + tx, err := vrt.Stake(opts, batch.pubKeys) + if err != nil { + return fmt.Errorf("failed to stake: %w", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + receipt, err := bind.WaitMined(ctx, client, tx) + if err != nil { + return fmt.Errorf("failed to wait for stake tx to be mined: %w", err) + } + + if receipt.Status != types.ReceiptStatusSuccessful { + return fmt.Errorf("stake tx included, but failed") + } + + fmt.Println("-------------------") + fmt.Printf("Batch %d completed\n", idx+1) + fmt.Println("-------------------") + } + fmt.Println("All staking batches completed!") + return nil +} + +func readBLSPublicKeysFromFile(filePath string) ([][]byte, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, err + } + defer file.Close() + + var keys [][]byte + scanner := bufio.NewScanner(file) + for scanner.Scan() { + key := scanner.Text() + if len(key) > 2 && key[:2] == "0x" { + key = key[2:] + } + keyBytes := common.Hex2Bytes(key) + keys = append(keys, keyBytes) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + return keys, nil +} From 7945b9db38290fec4a4e473ec34c8fcfa77c05cb Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:12:24 -0700 Subject: [PATCH 2/9] Update main.go --- tools/vanilla-stake/main.go | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index ccbf8011b..f9e148da5 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -59,10 +59,11 @@ func main() { optionKeystorePassword, optionL1RPCURL, optionPubkeyFilePath, + optionVanillaRegistryAddress, } app := &cli.App{ - Name: "vanill-stake", + Name: "vanilla-stake", Usage: "Stake validators programmatically with the mev-commit vanilla registry", Flags: flags, Action: func(c *cli.Context) error { @@ -99,6 +100,16 @@ func stakeVanilla(c *cli.Context) error { return fmt.Errorf("failed to get chain ID: %w", err) } + vrc, err := vanillaregistry.NewVanillaregistryCaller(common.HexToAddress(vanillaRegistryAddress), client) + if err != nil { + return fmt.Errorf("failed to create Vanilla Registry caller: %w", err) + } + minStake, err := vrc.MinStake(&bind.CallOpts{Context: ctx}) + if err != nil { + return fmt.Errorf("failed to get min stake: %w", err) + } + fmt.Println("Min stake: ", minStake) + vrt, err := vanillaregistry.NewVanillaregistryTransactor(common.HexToAddress(vanillaRegistryAddress), client) if err != nil { return fmt.Errorf("failed to create Vanilla Registry transactor: %w", err) @@ -130,10 +141,20 @@ func stakeVanilla(c *cli.Context) error { } amountPerValidator := new(big.Int) - amountPerValidator.SetString("100000000000000", 10) // TODO: make configurable + amountPerValidator.Set(minStake) totalAmount := new(big.Int).Mul(amountPerValidator, big.NewInt(int64(batchSize))) opts.Value = totalAmount + balance, err := client.BalanceAt(ctx, signer.GetAddress(), nil) + if err != nil { + return fmt.Errorf("failed to get balance: %w", err) + } + if balance.Cmp(totalAmount) < 0 { + return fmt.Errorf("balance is less than total amount") + } + + fmt.Println("Staking batch", idx+1, "with total amount", totalAmount, "and", len(batch.pubKeys), "validators") + tx, err := vrt.Stake(opts, batch.pubKeys) if err != nil { return fmt.Errorf("failed to stake: %w", err) @@ -149,12 +170,9 @@ func stakeVanilla(c *cli.Context) error { if receipt.Status != types.ReceiptStatusSuccessful { return fmt.Errorf("stake tx included, but failed") } - - fmt.Println("-------------------") - fmt.Printf("Batch %d completed\n", idx+1) - fmt.Println("-------------------") + fmt.Println("Batch ", idx+1, " completed") } - fmt.Println("All staking batches completed!") + fmt.Println("All staking batches completed successfully") return nil } From 750857a34889d7c187f597d3b39f813e1624a7a0 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:18:58 -0700 Subject: [PATCH 3/9] Update main.go --- tools/vanilla-stake/main.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index f9e148da5..9764fb318 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -4,7 +4,6 @@ import ( "bufio" "context" "fmt" - "log" "math/big" "os" "time" @@ -72,7 +71,8 @@ func main() { } if err := app.Run(os.Args); err != nil { - log.Fatal(err) + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) } } @@ -110,6 +110,14 @@ func stakeVanilla(c *cli.Context) error { } fmt.Println("Min stake: ", minStake) + isWhitelisted, err := vrc.WhitelistedStakers(&bind.CallOpts{Context: ctx}, signer.GetAddress()) + if err != nil { + return fmt.Errorf("failed to check if whitelisted: %w", err) + } + if !isWhitelisted { + return fmt.Errorf("caller is not whitelisted") + } + vrt, err := vanillaregistry.NewVanillaregistryTransactor(common.HexToAddress(vanillaRegistryAddress), client) if err != nil { return fmt.Errorf("failed to create Vanilla Registry transactor: %w", err) @@ -170,7 +178,7 @@ func stakeVanilla(c *cli.Context) error { if receipt.Status != types.ReceiptStatusSuccessful { return fmt.Errorf("stake tx included, but failed") } - fmt.Println("Batch ", idx+1, " completed") + fmt.Println("Batch", idx+1, "completed") } fmt.Println("All staking batches completed successfully") return nil From 7f92cf956a9864bc227857193c985e951bb7abd5 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:34:59 -0700 Subject: [PATCH 4/9] Update main.go --- tools/vanilla-stake/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index 9764fb318..2ccd50494 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -195,10 +195,10 @@ func readBLSPublicKeysFromFile(filePath string) ([][]byte, error) { scanner := bufio.NewScanner(file) for scanner.Scan() { key := scanner.Text() - if len(key) > 2 && key[:2] == "0x" { - key = key[2:] + if len(key) != 98 && len(key) != 96 { + return nil, fmt.Errorf("invalid BLS public key: %s - ensure there are no extra characters, commas, or spaces besides the pubkey and a trailing newline", key) } - keyBytes := common.Hex2Bytes(key) + keyBytes := common.FromHex(key) keys = append(keys, keyBytes) } From 31e19c7a5577a1d6ca2e247bbf8fd6d80cd69f3b Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:45:09 -0700 Subject: [PATCH 5/9] bugfixes --- tools/vanilla-stake/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index 2ccd50494..d76129013 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -115,7 +115,7 @@ func stakeVanilla(c *cli.Context) error { return fmt.Errorf("failed to check if whitelisted: %w", err) } if !isWhitelisted { - return fmt.Errorf("caller is not whitelisted") + return fmt.Errorf("caller %v is not whitelisted", signer.GetAddress()) } vrt, err := vanillaregistry.NewVanillaregistryTransactor(common.HexToAddress(vanillaRegistryAddress), client) @@ -150,7 +150,7 @@ func stakeVanilla(c *cli.Context) error { amountPerValidator := new(big.Int) amountPerValidator.Set(minStake) - totalAmount := new(big.Int).Mul(amountPerValidator, big.NewInt(int64(batchSize))) + totalAmount := new(big.Int).Mul(amountPerValidator, big.NewInt(int64(len(batch.pubKeys)))) opts.Value = totalAmount balance, err := client.BalanceAt(ctx, signer.GetAddress(), nil) From e1787125031a87b2062963cd1637a0473a9caeb7 Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:50:14 -0700 Subject: [PATCH 6/9] Update main.go --- tools/vanilla-stake/main.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index d76129013..629844687 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -104,12 +104,16 @@ func stakeVanilla(c *cli.Context) error { if err != nil { return fmt.Errorf("failed to create Vanilla Registry caller: %w", err) } + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() minStake, err := vrc.MinStake(&bind.CallOpts{Context: ctx}) if err != nil { return fmt.Errorf("failed to get min stake: %w", err) } fmt.Println("Min stake: ", minStake) + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() isWhitelisted, err := vrc.WhitelistedStakers(&bind.CallOpts{Context: ctx}, signer.GetAddress()) if err != nil { return fmt.Errorf("failed to check if whitelisted: %w", err) @@ -153,6 +157,8 @@ func stakeVanilla(c *cli.Context) error { totalAmount := new(big.Int).Mul(amountPerValidator, big.NewInt(int64(len(batch.pubKeys)))) opts.Value = totalAmount + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() balance, err := client.BalanceAt(ctx, signer.GetAddress(), nil) if err != nil { return fmt.Errorf("failed to get balance: %w", err) @@ -195,6 +201,9 @@ func readBLSPublicKeysFromFile(filePath string) ([][]byte, error) { scanner := bufio.NewScanner(file) for scanner.Scan() { key := scanner.Text() + if key == "" { + continue // Empty lines skipped + } if len(key) != 98 && len(key) != 96 { return nil, fmt.Errorf("invalid BLS public key: %s - ensure there are no extra characters, commas, or spaces besides the pubkey and a trailing newline", key) } From cd90c90ea11a62750c6958fadf6cb05b75f8683f Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:51:38 -0700 Subject: [PATCH 7/9] Update main.go --- tools/vanilla-stake/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index 629844687..3e474c796 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -158,8 +158,8 @@ func stakeVanilla(c *cli.Context) error { opts.Value = totalAmount ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() balance, err := client.BalanceAt(ctx, signer.GetAddress(), nil) + cancel() if err != nil { return fmt.Errorf("failed to get balance: %w", err) } @@ -175,8 +175,8 @@ func stakeVanilla(c *cli.Context) error { } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() receipt, err := bind.WaitMined(ctx, client, tx) + cancel() if err != nil { return fmt.Errorf("failed to wait for stake tx to be mined: %w", err) } From 141057af82959b02116eff3ea27785fc0c93670c Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:57:00 -0700 Subject: [PATCH 8/9] Create example.txt --- tools/vanilla-stake/example.txt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tools/vanilla-stake/example.txt diff --git a/tools/vanilla-stake/example.txt b/tools/vanilla-stake/example.txt new file mode 100644 index 000000000..5c8f36c0c --- /dev/null +++ b/tools/vanilla-stake/example.txt @@ -0,0 +1,30 @@ +0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6 +0xb2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1 +0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2 +0xd4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3 +0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 +0xf6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5 +0xa2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7 +0xb3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2 +0xc4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3 +0xd5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4 +0xe6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5 +0xf7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6f7a2b3c4d5e6 +0xa3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8 +0xb4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3 +0xc5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4 +0xd6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5 +0xe7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6 +0xf8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7f8a3b4c5d6e7 +0xa4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9 +0xb5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4 +0xc6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5 +0xd7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6 +0xe8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7 +0xf9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8f9a4b5c6d7e8 +0xa5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0 +0xb6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5 +0xc7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6 +0xd8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7 +0xe9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8 +0xf0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9f0a5b6c7d8e9 From 7b95dbb8913536e91693522bb94b579eb45f6f9c Mon Sep 17 00:00:00 2001 From: Shawn <44221603+shaspitz@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:06:06 -0700 Subject: [PATCH 9/9] check err of file.Close() --- tools/vanilla-stake/main.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/vanilla-stake/main.go b/tools/vanilla-stake/main.go index 3e474c796..81d8218a6 100644 --- a/tools/vanilla-stake/main.go +++ b/tools/vanilla-stake/main.go @@ -195,7 +195,11 @@ func readBLSPublicKeysFromFile(filePath string) ([][]byte, error) { if err != nil { return nil, err } - defer file.Close() + defer func() { + if err := file.Close(); err != nil { + fmt.Fprintf(os.Stderr, "error closing file: %v\n", err) + } + }() var keys [][]byte scanner := bufio.NewScanner(file)