diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e8ebe..6abca3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ dev: - show all slots with 'synccommittee inclusion' + - add "wallet batch" command 1.32.0: - fix incorrect error when "deposit verify" is not given a withdrawal address diff --git a/cmd/root.go b/cmd/root.go index 7ca98ff..81e753c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -76,6 +76,7 @@ var bindings = map[string]func(cmd *cobra.Command){ "validator/yield": validatorYieldBindings, "validator/expectation": validatorExpectationBindings, "validator/withdrawal": validatorWithdrawalBindings, + "wallet/batch": walletBatchBindings, "wallet/create": walletCreateBindings, "wallet/import": walletImportBindings, "wallet/sharedexport": walletSharedExportBindings, diff --git a/cmd/wallet/batch/command.go b/cmd/wallet/batch/command.go new file mode 100644 index 0000000..86883e4 --- /dev/null +++ b/cmd/wallet/batch/command.go @@ -0,0 +1,62 @@ +// Copyright © 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 +// +// 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 walletbatch + +import ( + "context" + "time" + + "github.com/pkg/errors" + "github.com/spf13/viper" + "github.com/wealdtech/ethdo/util" +) + +type command struct { + quiet bool + verbose bool + debug bool + + timeout time.Duration + + // Operation. + walletName string + passphrases []string + batchPassphrase string +} + +func newCommand(_ context.Context) (*command, error) { + c := &command{ + quiet: viper.GetBool("quiet"), + verbose: viper.GetBool("verbose"), + debug: viper.GetBool("debug"), + timeout: viper.GetDuration("timeout"), + walletName: viper.GetString("wallet"), + passphrases: util.GetPassphrases(), + batchPassphrase: viper.GetString("batch-passphrase"), + } + + if c.timeout == 0 { + return nil, errors.New("timeout is required") + } + + if c.walletName == "" { + return nil, errors.New("wallet is required") + } + + if c.batchPassphrase == "" { + return nil, errors.New("batch passphrase is required") + } + + return c, nil +} diff --git a/cmd/wallet/batch/output.go b/cmd/wallet/batch/output.go new file mode 100644 index 0000000..3ba5c34 --- /dev/null +++ b/cmd/wallet/batch/output.go @@ -0,0 +1,22 @@ +// Copyright © 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 +// +// 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 walletbatch + +import ( + "context" +) + +func (c *command) output(_ context.Context) (string, error) { + return "", nil +} diff --git a/cmd/wallet/batch/process.go b/cmd/wallet/batch/process.go new file mode 100644 index 0000000..0b42de3 --- /dev/null +++ b/cmd/wallet/batch/process.go @@ -0,0 +1,43 @@ +// Copyright © 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 +// +// 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 walletbatch + +import ( + "context" + + "github.com/pkg/errors" + "github.com/wealdtech/ethdo/util" + e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2" +) + +func (c *command) process(ctx context.Context) error { + // Obtain the wallet. + opCtx, cancel := context.WithTimeout(ctx, c.timeout) + wallet, err := util.WalletFromInput(opCtx) + cancel() + if err != nil { + return errors.Wrap(err, "failed to obtain wallet") + } + batchCreator, isBatchCreator := wallet.(e2wtypes.WalletBatchCreator) + if !isBatchCreator { + return errors.New("wallet does not support batching") + } + + // Create the batch. + if err := batchCreator.BatchWallet(ctx, util.GetPassphrases(), c.batchPassphrase); err != nil { + return errors.Wrap(err, "failed to batch wallet") + } + + return nil +} diff --git a/cmd/wallet/batch/process_internal_test.go b/cmd/wallet/batch/process_internal_test.go new file mode 100644 index 0000000..b93b4fc --- /dev/null +++ b/cmd/wallet/batch/process_internal_test.go @@ -0,0 +1,63 @@ +// Copyright © 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 +// +// 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 walletbatch + +import ( + "context" + "os" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/require" +) + +func TestProcess(t *testing.T) { + if os.Getenv("ETHDO_TEST_CONNECTION") == "" { + t.Skip("ETHDO_TEST_CONNECTION not configured; cannot run tests") + } + + tests := []struct { + name string + vars map[string]interface{} + err string + }{ + { + name: "NoBlock", + vars: map[string]interface{}{ + "timeout": "60s", + "connection": os.Getenv("ETHDO_TEST_CONNECTION"), + "blockid": "invalid", + }, + err: "failed to obtain beacon block: failed to request signed beacon block: GET failed with status 400: {\"code\":400,\"message\":\"Invalid block: invalid\"}", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + viper.Reset() + + for k, v := range test.vars { + viper.Set(k, v) + } + cmd, err := newCommand(context.Background()) + require.NoError(t, err) + err = cmd.process(context.Background()) + if test.err != "" { + require.EqualError(t, err, test.err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/cmd/wallet/batch/run.go b/cmd/wallet/batch/run.go new file mode 100644 index 0000000..82b3e2a --- /dev/null +++ b/cmd/wallet/batch/run.go @@ -0,0 +1,50 @@ +// Copyright © 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 +// +// 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 walletbatch + +import ( + "context" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// Run runs the command. +func Run(cmd *cobra.Command) (string, error) { + ctx := context.Background() + + c, err := newCommand(ctx) + if err != nil { + return "", errors.Wrap(err, "failed to set up command") + } + + // Further errors do not need a usage report. + cmd.SilenceUsage = true + + if err := c.process(ctx); err != nil { + return "", errors.Wrap(err, "failed to process") + } + + if viper.GetBool("quiet") { + return "", nil + } + + results, err := c.output(ctx) + if err != nil { + return "", errors.Wrap(err, "failed to obtain output") + } + + return results, nil +} diff --git a/cmd/walletbatch.go b/cmd/walletbatch.go new file mode 100644 index 0000000..225f35f --- /dev/null +++ b/cmd/walletbatch.go @@ -0,0 +1,54 @@ +// Copyright © 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 +// +// 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 cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + walletbatch "github.com/wealdtech/ethdo/cmd/wallet/batch" +) + +var walletBatchCmd = &cobra.Command{ + Use: "batch", + Short: "Batch a wallet", + Long: `Batch a wallet. For example: + + ethdo wallet batch --wallet="Primary wallet" --passphrase=accounts-secret --batch-passphrase=batch-secret + +In quiet mode this will return 0 if the wallet is batched successfully, otherwise 1.`, + RunE: func(cmd *cobra.Command, args []string) error { + res, err := walletbatch.Run(cmd) + if err != nil { + return err + } + if res != "" { + fmt.Println(res) + } + return nil + }, +} + +func init() { + walletCmd.AddCommand(walletBatchCmd) + walletFlags(walletBatchCmd) + walletBatchCmd.Flags().String("batch-passphrase", "", "The passphrase to use for the batch") +} + +func walletBatchBindings(cmd *cobra.Command) { + if err := viper.BindPFlag("batch-passphrase", cmd.Flags().Lookup("batch-passphrase")); err != nil { + panic(err) + } +} diff --git a/docs/usage.md b/docs/usage.md index 7a4925c..bbc7f12 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -29,12 +29,25 @@ Auctions: 0x812f340269c315c1d882ae7c13cdaddf862dbdbd482b1836798b2070160dd1e19408 Operations: 0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670 Spending: 0x85dfc6dcee4c9da36f6473ec02fda283d6c920c641fc8e3a76113c5c227d4aeeb100efcfec977b12d20d571907d05650 ``` + +#### `batch` + +`ethdo wallet batch` batches the accounts in a wallet into a single file to allow faster decryption. Options for batching a wallet include: + +- `wallet`: the name of the wallet to batch +- `passphrase`: the passphrase for of the accounts in the wallet +- `batch-passphrase`: the passphrase for the batch. Note that this can be the same as the passphrase for the accounts + +```sh +$ ethdo wallet batch --wallet="Validators" ---passphrase="my account secret" --batch-passphrase="my batch secret" +``` + #### `create` `ethdo wallet create` creates a new wallet with the given parameters. Options for creating a wallet include: - `wallet`: the name of the wallet to create -- `type`: the type of wallet to create. This can be either "nd" for a non-deterministic wallet, where private keys are generated randomly, or "hd" for a hierarchical deterministic wallet, where private keys are generated from a seed and path as per [ERC-2333](https://github.com/CarlBeek/EIPs/blob/bls_path/EIPS/eip-2334.md) (defaults to "nd") +- `type`: the type of wallet to create. This can be either "nd" for a non-deterministic wallet, where private keys are generated randomly, or "hd" for a hierarchical deterministic wallet, where private keys are generated from a seed and path as per [EIP-2333](https://eips.ethereum.org/EIPS/eip-2333) (defaults to "nd") - `wallet-passphrase`: the passphrase for of the wallet. This is required for hierarchical deterministic wallets, to protect the seed - `mnemonic`: for hierarchical deterministic wallets only, use a pre-defined 24-word [BIP-39 seed phrase](https://en.bitcoin.it/wiki/Seed_phrase) to create the wallet, along with an additional "seed extension" phrase if required. **Warning** The same mnemonic can be used to create multiple wallets, in which case they will generate the same keys. diff --git a/go.mod b/go.mod index 2d0c4aa..8f16d38 100644 --- a/go.mod +++ b/go.mod @@ -25,22 +25,22 @@ require ( github.com/wealdtech/go-ecodec v1.1.4 github.com/wealdtech/go-eth2-types/v2 v2.8.2 github.com/wealdtech/go-eth2-util v1.8.2 - github.com/wealdtech/go-eth2-wallet v1.15.1 + github.com/wealdtech/go-eth2-wallet v1.16.0 github.com/wealdtech/go-eth2-wallet-dirk v1.4.4 - github.com/wealdtech/go-eth2-wallet-distributed v1.1.5 + github.com/wealdtech/go-eth2-wallet-distributed v1.2.1 github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1 - github.com/wealdtech/go-eth2-wallet-hd/v2 v2.6.1 - github.com/wealdtech/go-eth2-wallet-nd/v2 v2.4.1 + github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.0 + github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.0 github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1 github.com/wealdtech/go-eth2-wallet-store-s3 v1.12.0 github.com/wealdtech/go-eth2-wallet-store-scratch v1.7.2 github.com/wealdtech/go-eth2-wallet-types/v2 v2.11.0 github.com/wealdtech/go-string2eth v1.2.1 - golang.org/x/text v0.11.0 + golang.org/x/text v0.12.0 ) require ( - github.com/aws/aws-sdk-go v1.44.316 // indirect + github.com/aws/aws-sdk-go v1.44.317 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -85,10 +85,10 @@ require ( go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect - golang.org/x/crypto v0.11.0 // indirect + golang.org/x/crypto v0.12.0 // indirect golang.org/x/net v0.13.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect @@ -100,3 +100,11 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/wealdtech/go-eth2-wallet-distributed => ../go-eth2-wallet-distributed + +replace github.com/wealdtech/go-eth2-wallet-hd/v2 => ../go-eth2-wallet-hd + +replace github.com/wealdtech/go-eth2-wallet-nd/v2 => ../go-eth2-wallet-nd + +replace github.com/wealdtech/go-eth2-wallet => ../go-eth2-wallet diff --git a/go.sum b/go.sum index d2f835a..4a90dd1 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/attestantio/go-eth2-client v0.18.1 h1:WZYYpIpWgoGA+dXDMB4rBvaxR/zPOOeBIfDC6h8knGU= github.com/attestantio/go-eth2-client v0.18.1/go.mod h1:KSVlZSW1A3jUg5H8O89DLtqxgJprRfTtI7k89fLdhu0= -github.com/aws/aws-sdk-go v1.44.316 h1:UC3alCEyzj2XU13ZFGIOHW3yjCNLGTIGVauyetl9fwE= -github.com/aws/aws-sdk-go v1.44.316/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.317 h1:+8XWrLmGMwPPXSRSLPzhgcGnzJ2mYkgkrcB9C/GnSOU= +github.com/aws/aws-sdk-go v1.44.317/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -306,19 +306,11 @@ github.com/wealdtech/go-eth2-types/v2 v2.8.2 h1:b5aXlNBLKgjAg/Fft9VvGlqAUCQMP5Lz github.com/wealdtech/go-eth2-types/v2 v2.8.2/go.mod h1:IAz9Lz1NVTaHabQa+4zjk2QDKMv8LVYo0n46M9o/TXw= github.com/wealdtech/go-eth2-util v1.8.2 h1:gq+JMrnadifyKadUr75wmfP7+usiqMu9t3VVoob5Dvo= github.com/wealdtech/go-eth2-util v1.8.2/go.mod h1:/80GAK0K/3+PqUBZHvaOPd3b1sjHeimxQh1nrJzgaPk= -github.com/wealdtech/go-eth2-wallet v1.15.1 h1:gtjl5EE5XgJBEs7s6s4XenIyGsn2d4TQCmXj9anP7Gc= -github.com/wealdtech/go-eth2-wallet v1.15.1/go.mod h1:FoUxyJQ1xNNdUJkb9KfNTM79MmItX682EujqbcnVLdc= github.com/wealdtech/go-eth2-wallet-dirk v1.4.4 h1:zPhDCJJvDn98/psfOwtlyDa0r+8c6u8MgXrOnMmcAtA= github.com/wealdtech/go-eth2-wallet-dirk v1.4.4/go.mod h1:f5CupAod/d5xa0yOQlfxonpkqsh5XJG38RTkZJBKDiA= -github.com/wealdtech/go-eth2-wallet-distributed v1.1.5 h1:kUpESVq2dVGeI4GXUy/LfoP5fycl3LGYTUcta7VTIjE= -github.com/wealdtech/go-eth2-wallet-distributed v1.1.5/go.mod h1:zaATC9jRC3bn7jAmB2+MaCiyyJcavHGzSq5OCd7h/tM= github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1 h1:9j7bpwjT9wmwBb54ZkBhTm1uNIlFFcCJXefd/YskZPw= github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1/go.mod h1:+tI1VD76E1WINI+Nstg7RVGpUolL5ql10nu2YztMO/4= -github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.1 h1:x6bq8cVgRgfhwtSQSYo/9AqJ8qEeaS6af28cW0cVj5U= -github.com/wealdtech/go-eth2-wallet-hd/v2 v2.6.1 h1:pEVfJCHB5T02oVtOumpcwU9H4zC2vWsJEQl09moh+n0= -github.com/wealdtech/go-eth2-wallet-hd/v2 v2.6.1/go.mod h1:11BHG8gt2FqQC02MrT4KN2+EV1ZTsn9SmSVme1HWp7E= -github.com/wealdtech/go-eth2-wallet-nd/v2 v2.4.1 h1:LvgLIYaP+WqZ8xcrN4e0CAIGDtjKhzpBqAhjExQzqb4= -github.com/wealdtech/go-eth2-wallet-nd/v2 v2.4.1/go.mod h1:279Gj7DqpQBar9eoo82RcC6SgD0fiZs1Dc6SffsDZM0= +github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.2 h1:IMIyl70hbJlxOkgTcCK//3vKe5ylhGIk6oUlIlK9xp0= github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1 h1:Ceq74WL57jdBQnrZJFJyGRBKOOFI5wwq9VoxeAbjoEk= github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1/go.mod h1:woTpldN8qThnmya/0yeD+a3u/3Zj42u6/ijgF9CGaz8= github.com/wealdtech/go-eth2-wallet-store-s3 v1.12.0 h1:noknYCbHw2soPhwke1LvC99Kk/2CLN787KcgxdZ7OGo= @@ -359,8 +351,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -506,8 +498,8 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -521,8 +513,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=