mirror of
https://github.com/wealdtech/ethdo.git
synced 2026-01-11 15:08:05 -05:00
Compare commits
4 Commits
exit-valid
...
v1.31.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbe45d5c27 | ||
|
|
c963ea8ba5 | ||
|
|
484361c034 | ||
|
|
d65f51d5af |
@@ -2,6 +2,8 @@ dev:
|
||||
- initial support for deneb
|
||||
- add "--generate-keystore" option for "account derive"
|
||||
- update "validator exit" command to be able to generate multiple exits
|
||||
- support for 12-word and 18-word mnemonics with single-word (no whitespace) passphrases
|
||||
- add JSON output for "validator expectation"
|
||||
|
||||
1.30.0:
|
||||
- add "chain spec" command
|
||||
|
||||
@@ -15,9 +15,12 @@ package validatorexpectation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
"github.com/hako/durafmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -26,6 +29,7 @@ type command struct {
|
||||
quiet bool
|
||||
verbose bool
|
||||
debug bool
|
||||
json bool
|
||||
|
||||
// Beacon node connection.
|
||||
timeout time.Duration
|
||||
@@ -38,18 +42,43 @@ type command struct {
|
||||
// Data access.
|
||||
eth2Client eth2client.Service
|
||||
validatorsProvider eth2client.ValidatorsProvider
|
||||
activeValidators int
|
||||
|
||||
// Output.
|
||||
// Results.
|
||||
res *results
|
||||
}
|
||||
|
||||
type results struct {
|
||||
activeValidators uint64
|
||||
timeBetweenProposals time.Duration
|
||||
timeBetweenSyncCommittees time.Duration
|
||||
}
|
||||
|
||||
type resultsJSON struct {
|
||||
ActiveValidators string `json:"active_validators"`
|
||||
TimeBetweenProposals string `json:"time_between_proposals"`
|
||||
SecsBetweenProposals string `json:"secs_between_proposals"`
|
||||
TimeBetweenSyncCommittees string `json:"time_between_sync_committees"`
|
||||
SecsBetweenSyncCommittees string `json:"secs_between_sync_committees"`
|
||||
}
|
||||
|
||||
func (r *results) MarshalJSON() ([]byte, error) {
|
||||
data := &resultsJSON{
|
||||
ActiveValidators: fmt.Sprintf("%d", r.activeValidators),
|
||||
TimeBetweenProposals: durafmt.Parse(r.timeBetweenProposals).LimitFirstN(2).String(),
|
||||
SecsBetweenProposals: fmt.Sprintf("%d", int64(r.timeBetweenProposals.Seconds())),
|
||||
TimeBetweenSyncCommittees: durafmt.Parse(r.timeBetweenSyncCommittees).LimitFirstN(2).String(),
|
||||
SecsBetweenSyncCommittees: fmt.Sprintf("%d", int64(r.timeBetweenSyncCommittees.Seconds())),
|
||||
}
|
||||
return json.Marshal(data)
|
||||
}
|
||||
|
||||
func newCommand(_ context.Context) (*command, error) {
|
||||
c := &command{
|
||||
quiet: viper.GetBool("quiet"),
|
||||
verbose: viper.GetBool("verbose"),
|
||||
debug: viper.GetBool("debug"),
|
||||
json: viper.GetBool("json"),
|
||||
res: &results{},
|
||||
}
|
||||
|
||||
// Timeout.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright © 2021 Weald Technology Trading.
|
||||
// Copyright © 2021, 2023 Weald Technology Trading.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -15,24 +15,42 @@ package validatorexpectation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hako/durafmt"
|
||||
)
|
||||
|
||||
func (c *command) output(_ context.Context) (string, error) {
|
||||
func (c *command) output(ctx context.Context) (string, error) {
|
||||
if c.quiet {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if c.json {
|
||||
return c.outputJSON(ctx)
|
||||
}
|
||||
return c.outputTxt(ctx)
|
||||
}
|
||||
|
||||
func (c *command) outputJSON(_ context.Context) (string, error) {
|
||||
data, err := json.Marshal(c.res)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s\n", string(data)), nil
|
||||
}
|
||||
|
||||
func (c *command) outputTxt(_ context.Context) (string, error) {
|
||||
builder := strings.Builder{}
|
||||
|
||||
builder.WriteString("Expected time between block proposals: ")
|
||||
builder.WriteString(durafmt.Parse(c.timeBetweenProposals).LimitFirstN(2).String())
|
||||
builder.WriteString(durafmt.Parse(c.res.timeBetweenProposals).LimitFirstN(2).String())
|
||||
builder.WriteString("\n")
|
||||
|
||||
builder.WriteString("Expected time between sync committees: ")
|
||||
builder.WriteString(durafmt.Parse(c.timeBetweenSyncCommittees).LimitFirstN(2).String())
|
||||
builder.WriteString(durafmt.Parse(c.res.timeBetweenSyncCommittees).LimitFirstN(2).String())
|
||||
builder.WriteString("\n")
|
||||
|
||||
return builder.String(), nil
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright © 2021 Weald Technology Trading.
|
||||
// Copyright © 2021, 2023 Weald Technology Trading.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -31,7 +31,7 @@ func (c *command) process(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if c.debug {
|
||||
fmt.Printf("Active validators: %d\n", c.activeValidators)
|
||||
fmt.Printf("Active validators: %d\n", c.res.activeValidators)
|
||||
}
|
||||
|
||||
if err := c.calculateProposalChance(ctx); err != nil {
|
||||
@@ -59,7 +59,7 @@ func (c *command) calculateProposalChance(ctx context.Context) error {
|
||||
return errors.New("SECONDS_PER_SLOT of incorrect type")
|
||||
}
|
||||
|
||||
c.timeBetweenProposals = slotDuration * time.Duration(c.activeValidators) / time.Duration(c.validators)
|
||||
c.res.timeBetweenProposals = slotDuration * time.Duration(c.res.activeValidators) / time.Duration(c.validators)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -109,12 +109,12 @@ func (c *command) calculateSyncCommitteeChance(ctx context.Context) error {
|
||||
return errors.New("EPOCHS_PER_SYNC_COMMITTEE_PERIOD of incorrect type")
|
||||
}
|
||||
|
||||
periodsBetweenSyncCommittees := uint64(c.activeValidators) / syncCommitteeSize
|
||||
periodsBetweenSyncCommittees := c.res.activeValidators / syncCommitteeSize
|
||||
if c.debug {
|
||||
fmt.Printf("Sync committee periods between inclusion: %d\n", periodsBetweenSyncCommittees)
|
||||
}
|
||||
|
||||
c.timeBetweenSyncCommittees = slotDuration * time.Duration(slotsPerEpoch*epochsPerPeriod) * time.Duration(periodsBetweenSyncCommittees) / time.Duration(c.validators)
|
||||
c.res.timeBetweenSyncCommittees = slotDuration * time.Duration(slotsPerEpoch*epochsPerPeriod) * time.Duration(periodsBetweenSyncCommittees) / time.Duration(c.validators)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func (c *command) setup(ctx context.Context) error {
|
||||
for _, validator := range validators {
|
||||
if validator.Validator.ActivationEpoch <= currentEpoch &&
|
||||
validator.Validator.ExitEpoch > currentEpoch {
|
||||
c.activeValidators++
|
||||
c.res.activeValidators++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,23 @@ var mnemonicWordLists = [][]string{
|
||||
|
||||
// SeedFromMnemonic creates a seed from a mnemonic.
|
||||
func SeedFromMnemonic(mnemonic string) ([]byte, error) {
|
||||
// If there are more than 24 words we treat the additional characters as the passphrase.
|
||||
// Handle situations where there may be a passphrase with the mnemonic.
|
||||
mnemonicParts := strings.Split(mnemonic, " ")
|
||||
mnemonicPassphrase := ""
|
||||
if len(mnemonicParts) > 24 {
|
||||
switch {
|
||||
case len(mnemonicParts) == 13:
|
||||
// Assume that passphrase is a single word here.
|
||||
mnemonic = strings.Join(mnemonicParts[:12], " ")
|
||||
mnemonicPassphrase = mnemonicParts[12]
|
||||
case len(mnemonicParts) == 19:
|
||||
// Assume that passphrase is a single word here.
|
||||
mnemonic = strings.Join(mnemonicParts[:18], " ")
|
||||
mnemonicPassphrase = mnemonicParts[18]
|
||||
case len(mnemonicParts) > 24:
|
||||
mnemonic = strings.Join(mnemonicParts[:24], " ")
|
||||
mnemonicPassphrase = strings.Join(mnemonicParts[24:], " ")
|
||||
}
|
||||
|
||||
// Normalise the input.
|
||||
mnemonic = string(norm.NFKD.Bytes([]byte(mnemonic)))
|
||||
mnemonicPassphrase = string(norm.NFKD.Bytes([]byte(mnemonicPassphrase)))
|
||||
|
||||
@@ -42,10 +42,35 @@ func TestSeedFromMnemonic(t *testing.T) {
|
||||
err: "mnemonic is invalid",
|
||||
},
|
||||
{
|
||||
name: "Default",
|
||||
name: "Twelve",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
||||
seed: bytesStr("0x5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4"),
|
||||
},
|
||||
{
|
||||
name: "TwelvePlusPassphrase",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about passphrase",
|
||||
seed: bytesStr("0x4865438d10636e1453b2d3c06444c669b80fb1ae77111f1f91b64278ed4d493465276d2e00f93be2a8e82c2f72555370a4bf31bcf1f9addaf0a31499a3baeeae"),
|
||||
},
|
||||
{
|
||||
name: "Eighteen",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
|
||||
seed: bytesStr("0x4975bb3d1faf5308c86a30893ee903a976296609db223fd717e227da5a813a34dc1428b71c84a787fc51f3b9f9dc28e9459f48c08bd9578e9d1b170f2d7ea506"),
|
||||
},
|
||||
{
|
||||
name: "EighteenPlusPassphrase",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent passphrase",
|
||||
seed: bytesStr("0xbea1dd48440f3a8a7c02d0f7977fe03ba1dd409dda1ce971e80adc38f750c51d0959bd15c48cca2649cbcba8160d8a6c4026f2ee22dd387aa9b005041a5b8ea2"),
|
||||
},
|
||||
{
|
||||
name: "TwentyFour",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
seed: bytesStr("0x408b285c123836004f4b8842c89324c1f01382450c0d439af345ba7fc49acf705489c6fc77dbd4e3dc1dd8cc6bc9f043db8ada1e243c4a0eafb290d399480840"),
|
||||
},
|
||||
{
|
||||
name: "TwentyFourPlusPassphrase",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art passphrase",
|
||||
seed: bytesStr("0x3b9096d658962052e9e778a18e7fddb8f530cbf783f38b26cf3e89fff6bf385728028ea0e906d47c24f88b666d61a59bdb88a7fc11b9e302ae75482c9562c282"),
|
||||
},
|
||||
{
|
||||
name: "English",
|
||||
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
|
||||
|
||||
Reference in New Issue
Block a user