From 4d718f614cf60b64b1308d997757829422e136b7 Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Wed, 12 Jan 2022 15:07:07 +0000 Subject: [PATCH] Tidy up tests, standardise error messages. --- cmd/attester/duties/input.go | 2 +- cmd/attester/duties/input_internal_test.go | 2 +- cmd/attester/inclusion/input.go | 2 +- cmd/attester/inclusion/input_internal_test.go | 6 +- cmd/attester/inclusion/process.go | 59 +------------- cmd/block/info/input.go | 2 +- cmd/block/info/input_internal_test.go | 4 +- cmd/block/info/process_internal_test.go | 2 +- cmd/chain/time/process_internal_test.go | 53 ++++++++----- cmd/node/events/input.go | 2 +- cmd/node/events/input_internal_test.go | 4 +- cmd/slot/time/input.go | 2 +- cmd/slot/time/input_internal_test.go | 2 +- cmd/synccommittee/inclusion/process.go | 57 +------------ cmd/synccommittee/members/input.go | 2 +- .../members/input_internal_test.go | 2 +- .../members/process_internal_test.go | 2 +- cmd/validator/duties/process.go | 60 +------------- .../expectation/process_internal_test.go | 2 +- util/validator.go | 79 +++++++++++++++++++ 20 files changed, 138 insertions(+), 208 deletions(-) create mode 100644 util/validator.go diff --git a/cmd/attester/duties/input.go b/cmd/attester/duties/input.go index 10585f5..49cdb35 100644 --- a/cmd/attester/duties/input.go +++ b/cmd/attester/duties/input.go @@ -63,7 +63,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } // Epoch diff --git a/cmd/attester/duties/input_internal_test.go b/cmd/attester/duties/input_internal_test.go index e038441..f0e60c8 100644 --- a/cmd/attester/duties/input_internal_test.go +++ b/cmd/attester/duties/input_internal_test.go @@ -73,7 +73,7 @@ func TestInput(t *testing.T) { "timeout": "5s", "pubkey": "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, } diff --git a/cmd/attester/inclusion/input.go b/cmd/attester/inclusion/input.go index a19c222..fbafc06 100644 --- a/cmd/attester/inclusion/input.go +++ b/cmd/attester/inclusion/input.go @@ -71,7 +71,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } config, err := data.eth2Client.(eth2client.SpecProvider).Spec(ctx) diff --git a/cmd/attester/inclusion/input_internal_test.go b/cmd/attester/inclusion/input_internal_test.go index 2c1c2c1..c44302f 100644 --- a/cmd/attester/inclusion/input_internal_test.go +++ b/cmd/attester/inclusion/input_internal_test.go @@ -61,11 +61,11 @@ func TestInput(t *testing.T) { err: "timeout is required", }, { - name: "AccountMissing", + name: "IndexMissing", vars: map[string]interface{}{ "timeout": "5s", }, - err: "account or pubkey is required", + err: "account, index or pubkey is required", }, { name: "ConnectionMissing", @@ -73,7 +73,7 @@ func TestInput(t *testing.T) { "timeout": "5s", "pubkey": "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, } diff --git a/cmd/attester/inclusion/process.go b/cmd/attester/inclusion/process.go index 2472a65..9923deb 100644 --- a/cmd/attester/inclusion/process.go +++ b/cmd/attester/inclusion/process.go @@ -1,4 +1,4 @@ -// Copyright © 2019, 2020 Weald Technology Trading +// Copyright © 2019 - 2022 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 @@ -16,10 +16,7 @@ package attesterinclusion import ( "bytes" "context" - "encoding/hex" "fmt" - "strconv" - "strings" eth2client "github.com/attestantio/go-eth2-client" api "github.com/attestantio/go-eth2-client/api/v1" @@ -27,7 +24,6 @@ import ( "github.com/pkg/errors" standardchaintime "github.com/wealdtech/ethdo/services/chaintime/standard" "github.com/wealdtech/ethdo/util" - e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2" ) func process(ctx context.Context, data *dataIn) (*dataOut, error) { @@ -46,7 +42,7 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) { return nil, errors.Wrap(err, "failed to set up chaintime service") } - validatorIndex, err := validatorIndex(ctx, data.eth2Client, data) + validatorIndex, err := util.ValidatorIndex(ctx, data.eth2Client, data.account, data.pubKey, data.index) if err != nil { return nil, errors.Wrap(err, "failed to obtain validator index") } @@ -194,54 +190,3 @@ func duty(ctx context.Context, eth2Client eth2client.Service, validator *api.Val return duties[0], nil } - -// validatorIndex obtains the index of a validator -func validatorIndex(ctx context.Context, eth2Client eth2client.Service, data *dataIn) (phase0.ValidatorIndex, error) { - switch { - case data.account != "": - ctx, cancel := context.WithTimeout(context.Background(), data.timeout) - defer cancel() - _, account, err := util.WalletAndAccountFromPath(ctx, data.account) - if err != nil { - return 0, errors.Wrap(err, "failed to obtain account") - } - return accountToIndex(ctx, account, eth2Client) - case data.pubKey != "": - pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(data.pubKey, "0x")) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("failed to decode public key %s", data.pubKey)) - } - account, err := util.NewScratchAccount(nil, pubKeyBytes) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("invalid public key %s", data.pubKey)) - } - return accountToIndex(ctx, account, eth2Client) - case data.index != "": - val, err := strconv.ParseUint(data.index, 10, 64) - if err != nil { - return 0, err - } - return phase0.ValidatorIndex(val), nil - default: - return 0, errors.New("no validator") - } -} - -func accountToIndex(ctx context.Context, account e2wtypes.Account, eth2Client eth2client.Service) (phase0.ValidatorIndex, error) { - pubKey, err := util.BestPublicKey(account) - if err != nil { - return 0, err - } - - pubKeys := make([]phase0.BLSPubKey, 1) - copy(pubKeys[0][:], pubKey.Marshal()) - validators, err := eth2Client.(eth2client.ValidatorsProvider).ValidatorsByPubKey(ctx, "head", pubKeys) - if err != nil { - return 0, err - } - - for index := range validators { - return index, nil - } - return 0, errors.New("validator not found") -} diff --git a/cmd/block/info/input.go b/cmd/block/info/input.go index b63e8c1..a3804d0 100644 --- a/cmd/block/info/input.go +++ b/cmd/block/info/input.go @@ -54,7 +54,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } if viper.GetString("blockid") == "" { diff --git a/cmd/block/info/input_internal_test.go b/cmd/block/info/input_internal_test.go index 9677701..b233805 100644 --- a/cmd/block/info/input_internal_test.go +++ b/cmd/block/info/input_internal_test.go @@ -66,7 +66,7 @@ func TestInput(t *testing.T) { vars: map[string]interface{}{ "timeout": "5s", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, { name: "ConnectionBad", @@ -79,7 +79,7 @@ func TestInput(t *testing.T) { timeout: 5 * time.Second, blockID: "justified", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, { name: "BlockIDNil", diff --git a/cmd/block/info/process_internal_test.go b/cmd/block/info/process_internal_test.go index a40c527..6679a26 100644 --- a/cmd/block/info/process_internal_test.go +++ b/cmd/block/info/process_internal_test.go @@ -47,7 +47,7 @@ func TestProcess(t *testing.T) { dataIn: &dataIn{ eth2Client: eth2Client, }, - err: "failed to output block: failed to generate text: no block supplied", + err: "empty beacon block", }, } diff --git a/cmd/chain/time/process_internal_test.go b/cmd/chain/time/process_internal_test.go index 7fb304c..a88c00c 100644 --- a/cmd/chain/time/process_internal_test.go +++ b/cmd/chain/time/process_internal_test.go @@ -15,6 +15,7 @@ package chaintime import ( "context" + "fmt" "os" "testing" "time" @@ -46,11 +47,16 @@ func TestProcess(t *testing.T) { slot: "1", }, expected: &dataOut{ - epochStart: time.Unix(1606824023, 0), - epochEnd: time.Unix(1606824407, 0), - slot: 1, - slotStart: time.Unix(1606824035, 0), - slotEnd: time.Unix(1606824047, 0), + epochStart: time.Unix(1606824023, 0), + epochEnd: time.Unix(1606824407, 0), + slot: 1, + slotStart: time.Unix(1606824035, 0), + slotEnd: time.Unix(1606824047, 0), + syncCommitteePeriod: 0, + syncCommitteePeriodStart: time.Unix(1606824023, 0), + syncCommitteePeriodEnd: time.Unix(1606921943, 0), + syncCommitteePeriodEpochStart: 0, + syncCommitteePeriodEpochEnd: 255, }, }, { @@ -62,12 +68,17 @@ func TestProcess(t *testing.T) { epoch: "2", }, expected: &dataOut{ - epoch: 2, - epochStart: time.Unix(1606824791, 0), - epochEnd: time.Unix(1606825175, 0), - slot: 64, - slotStart: time.Unix(1606824791, 0), - slotEnd: time.Unix(1606824803, 0), + epoch: 2, + epochStart: time.Unix(1606824791, 0), + epochEnd: time.Unix(1606825175, 0), + slot: 64, + slotStart: time.Unix(1606824791, 0), + slotEnd: time.Unix(1606824803, 0), + syncCommitteePeriod: 0, + syncCommitteePeriodStart: time.Unix(1606824023, 0), + syncCommitteePeriodEnd: time.Unix(1606921943, 0), + syncCommitteePeriodEpochStart: 0, + syncCommitteePeriodEpochEnd: 255, }, }, { @@ -76,15 +87,20 @@ func TestProcess(t *testing.T) { connection: os.Getenv("ETHDO_TEST_CONNECTION"), timeout: 10 * time.Second, allowInsecureConnections: true, - timestamp: "2021-01-01T00:00:00", + timestamp: "2021-01-01T00:00:00+0000", }, expected: &dataOut{ - epoch: 6862, - epochStart: time.Unix(1609459031, 0), - epochEnd: time.Unix(1609459415, 0), - slot: 219598, - slotStart: time.Unix(1609459199, 0), - slotEnd: time.Unix(1609459211, 0), + epoch: 6862, + epochStart: time.Unix(1609459031, 0), + epochEnd: time.Unix(1609459415, 0), + slot: 219598, + slotStart: time.Unix(1609459199, 0), + slotEnd: time.Unix(1609459211, 0), + syncCommitteePeriod: 26, + syncCommitteePeriodStart: time.Unix(1609379927, 0), + syncCommitteePeriodEnd: time.Unix(1609477847, 0), + syncCommitteePeriodEpochStart: 6656, + syncCommitteePeriodEpochEnd: 6911, }, }, } @@ -96,6 +112,7 @@ func TestProcess(t *testing.T) { require.EqualError(t, err, test.err) } else { require.NoError(t, err) + fmt.Printf("****** %d %d\n", res.syncCommitteePeriodStart.Unix(), res.syncCommitteePeriodEnd.Unix()) require.Equal(t, test.expected, res) } }) diff --git a/cmd/node/events/input.go b/cmd/node/events/input.go index a78d7f5..8bf80f9 100644 --- a/cmd/node/events/input.go +++ b/cmd/node/events/input.go @@ -52,7 +52,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } return data, nil diff --git a/cmd/node/events/input_internal_test.go b/cmd/node/events/input_internal_test.go index 55c115a..a92b0ca 100644 --- a/cmd/node/events/input_internal_test.go +++ b/cmd/node/events/input_internal_test.go @@ -66,7 +66,7 @@ func TestInput(t *testing.T) { vars: map[string]interface{}{ "timeout": "5s", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, { name: "ConnectionBad", @@ -75,7 +75,7 @@ func TestInput(t *testing.T) { "connection": "localhost:1", "topics": []string{"one", "two"}, }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, { name: "TopicsNil", diff --git a/cmd/slot/time/input.go b/cmd/slot/time/input.go index 5374b6d..d4eb157 100644 --- a/cmd/slot/time/input.go +++ b/cmd/slot/time/input.go @@ -54,7 +54,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } return data, nil diff --git a/cmd/slot/time/input_internal_test.go b/cmd/slot/time/input_internal_test.go index 4c02b8c..ec1c63b 100644 --- a/cmd/slot/time/input_internal_test.go +++ b/cmd/slot/time/input_internal_test.go @@ -73,7 +73,7 @@ func TestInput(t *testing.T) { "timeout": "5s", "slot": "1", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, } diff --git a/cmd/synccommittee/inclusion/process.go b/cmd/synccommittee/inclusion/process.go index 56cb3c0..d864a91 100644 --- a/cmd/synccommittee/inclusion/process.go +++ b/cmd/synccommittee/inclusion/process.go @@ -15,10 +15,7 @@ package inclusion import ( "context" - "encoding/hex" "fmt" - "strconv" - "strings" eth2client "github.com/attestantio/go-eth2-client" "github.com/attestantio/go-eth2-client/spec" @@ -27,7 +24,6 @@ import ( "github.com/pkg/errors" standardchaintime "github.com/wealdtech/ethdo/services/chaintime/standard" "github.com/wealdtech/ethdo/util" - e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2" ) func (c *command) process(ctx context.Context) error { @@ -38,7 +34,7 @@ func (c *command) process(ctx context.Context) error { firstSlot, lastSlot := c.calculateSlots(ctx) - validatorIndex, err := c.validatorIndex(ctx) + validatorIndex, err := util.ValidatorIndex(ctx, c.eth2Client, c.account, c.pubKey, c.index) if err != nil { return err } @@ -114,57 +110,6 @@ func (c *command) setup(ctx context.Context) error { return nil } -// validatorIndex obtains the index of a validator. -func (c *command) validatorIndex(ctx context.Context) (phase0.ValidatorIndex, error) { - switch { - case c.account != "": - ctx, cancel := context.WithTimeout(context.Background(), c.timeout) - defer cancel() - _, account, err := util.WalletAndAccountFromPath(ctx, c.account) - if err != nil { - return 0, errors.Wrap(err, "failed to obtain account") - } - return accountToIndex(ctx, account, c.eth2Client) - case c.pubKey != "": - pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(c.pubKey, "0x")) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("failed to decode public key %s", c.pubKey)) - } - account, err := util.NewScratchAccount(nil, pubKeyBytes) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("invalid public key %s", c.pubKey)) - } - return accountToIndex(ctx, account, c.eth2Client) - case c.index != "": - val, err := strconv.ParseUint(c.index, 10, 64) - if err != nil { - return 0, err - } - return phase0.ValidatorIndex(val), nil - default: - return 0, errors.New("no validator") - } -} - -func accountToIndex(ctx context.Context, account e2wtypes.Account, eth2Client eth2client.Service) (phase0.ValidatorIndex, error) { - pubKey, err := util.BestPublicKey(account) - if err != nil { - return 0, err - } - - pubKeys := make([]phase0.BLSPubKey, 1) - copy(pubKeys[0][:], pubKey.Marshal()) - validators, err := eth2Client.(eth2client.ValidatorsProvider).ValidatorsByPubKey(ctx, "head", pubKeys) - if err != nil { - return 0, err - } - - for index := range validators { - return index, nil - } - return 0, errors.New("validator not found") -} - func (c *command) calculateSlots(ctx context.Context) (phase0.Slot, phase0.Slot) { var firstSlot phase0.Slot var lastSlot phase0.Slot diff --git a/cmd/synccommittee/members/input.go b/cmd/synccommittee/members/input.go index 3c3d581..160158c 100644 --- a/cmd/synccommittee/members/input.go +++ b/cmd/synccommittee/members/input.go @@ -53,7 +53,7 @@ func input(ctx context.Context) (*dataIn, error) { var err error data.eth2Client, err = util.ConnectToBeaconNode(ctx, viper.GetString("connection"), viper.GetDuration("timeout"), viper.GetBool("allow-insecure-connections")) if err != nil { - return nil, errors.Wrap(err, "failed to connect to Ethereum 2 beacon node") + return nil, err } // Chain time. diff --git a/cmd/synccommittee/members/input_internal_test.go b/cmd/synccommittee/members/input_internal_test.go index 01b33ae..0e42102 100644 --- a/cmd/synccommittee/members/input_internal_test.go +++ b/cmd/synccommittee/members/input_internal_test.go @@ -65,7 +65,7 @@ func TestInput(t *testing.T) { vars: map[string]interface{}{ "timeout": "5s", }, - err: "failed to connect to Ethereum 2 beacon node: failed to connect to beacon node: problem with parameters: no address specified", + err: "failed to connect to beacon node: failed to connect to Ethereum 2 client with any known method", }, } diff --git a/cmd/synccommittee/members/process_internal_test.go b/cmd/synccommittee/members/process_internal_test.go index aabd527..d3bdda8 100644 --- a/cmd/synccommittee/members/process_internal_test.go +++ b/cmd/synccommittee/members/process_internal_test.go @@ -56,7 +56,7 @@ func TestProcess(t *testing.T) { dataIn: &dataIn{ eth2Client: eth2Client, chainTime: chainTime, - epoch: 61650, + epoch: -1, }, }, } diff --git a/cmd/validator/duties/process.go b/cmd/validator/duties/process.go index 32b4dc3..3e49c91 100644 --- a/cmd/validator/duties/process.go +++ b/cmd/validator/duties/process.go @@ -1,4 +1,4 @@ -// Copyright © 2019, 2020 Weald Technology Trading +// Copyright © 2019 - 2022 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,10 +15,6 @@ package validatorduties import ( "context" - "encoding/hex" - "fmt" - "strconv" - "strings" "time" eth2client "github.com/attestantio/go-eth2-client" @@ -26,7 +22,6 @@ import ( spec "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/pkg/errors" "github.com/wealdtech/ethdo/util" - e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2" ) func process(ctx context.Context, data *dataIn) (*dataOut, error) { @@ -46,7 +41,7 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) { verbose: data.verbose, } - validatorIndex, err := validatorIndex(ctx, eth2Client, data) + validatorIndex, err := util.ValidatorIndex(ctx, eth2Client, data.account, data.pubKey, data.index) if err != nil { return nil, errors.Wrap(err, "failed to obtain validator index") } @@ -132,54 +127,3 @@ func currentEpoch(ctx context.Context, eth2Client eth2client.Service) (spec.Epoc } return spec.Epoch(uint64(time.Since(genesis.GenesisTime).Seconds()) / (uint64(slotDuration.Seconds()) * slotsPerEpoch)), nil } - -// validatorIndex obtains the index of a validator -func validatorIndex(ctx context.Context, eth2Client eth2client.Service, data *dataIn) (spec.ValidatorIndex, error) { - switch { - case data.account != "": - ctx, cancel := context.WithTimeout(context.Background(), data.timeout) - defer cancel() - _, account, err := util.WalletAndAccountFromPath(ctx, data.account) - if err != nil { - return 0, errors.Wrap(err, "failed to obtain account") - } - return accountToIndex(ctx, account, eth2Client) - case data.pubKey != "": - pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(data.pubKey, "0x")) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("failed to decode public key %s", data.pubKey)) - } - account, err := util.NewScratchAccount(nil, pubKeyBytes) - if err != nil { - return 0, errors.Wrap(err, fmt.Sprintf("invalid public key %s", data.pubKey)) - } - return accountToIndex(ctx, account, eth2Client) - case data.index != "": - val, err := strconv.ParseUint(data.index, 10, 64) - if err != nil { - return 0, err - } - return spec.ValidatorIndex(val), nil - default: - return 0, errors.New("no validator") - } -} - -func accountToIndex(ctx context.Context, account e2wtypes.Account, eth2Client eth2client.Service) (spec.ValidatorIndex, error) { - pubKey, err := util.BestPublicKey(account) - if err != nil { - return 0, err - } - - pubKeys := make([]spec.BLSPubKey, 1) - copy(pubKeys[0][:], pubKey.Marshal()) - validators, err := eth2Client.(eth2client.ValidatorsProvider).ValidatorsByPubKey(ctx, "head", pubKeys) - if err != nil { - return 0, err - } - - for index := range validators { - return index, nil - } - return 0, errors.New("validator not found") -} diff --git a/cmd/validator/expectation/process_internal_test.go b/cmd/validator/expectation/process_internal_test.go index a8f706d..6bb276c 100644 --- a/cmd/validator/expectation/process_internal_test.go +++ b/cmd/validator/expectation/process_internal_test.go @@ -35,7 +35,7 @@ func TestProcess(t *testing.T) { { name: "InvalidData", vars: map[string]interface{}{ - "timeout": "5s", + "timeout": "60s", "validators": "1", "data": "[[", "connection": os.Getenv("ETHDO_TEST_CONNECTION"), diff --git a/util/validator.go b/util/validator.go new file mode 100644 index 0000000..e368f71 --- /dev/null +++ b/util/validator.go @@ -0,0 +1,79 @@ +// Copyright © 2022 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 +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + "strings" + "time" + + consensusclient "github.com/attestantio/go-eth2-client" + "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/pkg/errors" + e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2" +) + +// ValidatorIndex obtains the index of a validator. +func ValidatorIndex(ctx context.Context, client consensusclient.Service, account string, pubKey string, index string) (phase0.ValidatorIndex, error) { + switch { + case account != "": + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _, account, err := WalletAndAccountFromPath(ctx, account) + if err != nil { + return 0, errors.Wrap(err, "failed to obtain account") + } + return accountToIndex(ctx, account, client) + case pubKey != "": + pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(pubKey, "0x")) + if err != nil { + return 0, errors.Wrap(err, fmt.Sprintf("failed to decode public key %s", pubKey)) + } + account, err := NewScratchAccount(nil, pubKeyBytes) + if err != nil { + return 0, errors.Wrap(err, fmt.Sprintf("invalid public key %s", pubKey)) + } + return accountToIndex(ctx, account, client) + case index != "": + val, err := strconv.ParseUint(index, 10, 64) + if err != nil { + return 0, err + } + return phase0.ValidatorIndex(val), nil + default: + return 0, errors.New("no validator") + } +} + +func accountToIndex(ctx context.Context, account e2wtypes.Account, client consensusclient.Service) (phase0.ValidatorIndex, error) { + pubKey, err := BestPublicKey(account) + if err != nil { + return 0, err + } + + pubKeys := make([]phase0.BLSPubKey, 1) + copy(pubKeys[0][:], pubKey.Marshal()) + validators, err := client.(consensusclient.ValidatorsProvider).ValidatorsByPubKey(ctx, "head", pubKeys) + if err != nil { + return 0, err + } + + for index := range validators { + return index, nil + } + return 0, errors.New("validator not found") +}