mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Compare commits
48 Commits
c6c9414d8b
...
web3signer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54482a7772 | ||
|
|
8f9b2e990b | ||
|
|
d37c777a30 | ||
|
|
00623ac8a7 | ||
|
|
3c390027e2 | ||
|
|
f025bafba5 | ||
|
|
fc1d8a7d12 | ||
|
|
0bdf731b53 | ||
|
|
362b8868d2 | ||
|
|
38ef97acef | ||
|
|
9dcb458a18 | ||
|
|
7617d86edd | ||
|
|
d27705b3a3 | ||
|
|
bc39b42b0f | ||
|
|
4a78174fad | ||
|
|
7df6f9efbc | ||
|
|
352b5a1085 | ||
|
|
c0b1402df9 | ||
|
|
4f31fbc3c6 | ||
|
|
f5093d06bf | ||
|
|
01d63502a1 | ||
|
|
3e1785e69a | ||
|
|
4a0042af10 | ||
|
|
4f060cbec8 | ||
|
|
301b869229 | ||
|
|
79f9840c02 | ||
|
|
c24806be79 | ||
|
|
b984e85a1d | ||
|
|
2dfaf7103b | ||
|
|
b84c5fc100 | ||
|
|
494968fe05 | ||
|
|
16f6b174b8 | ||
|
|
b6693530e1 | ||
|
|
bb9de8ca10 | ||
|
|
ae42f65c27 | ||
|
|
16b63bbe6f | ||
|
|
4098215800 | ||
|
|
f81841b2a9 | ||
|
|
97b98d2b7b | ||
|
|
2e8a872e91 | ||
|
|
5f8152921a | ||
|
|
1d5832c385 | ||
|
|
a0a5dff2c0 | ||
|
|
358e92c316 | ||
|
|
e98c373716 | ||
|
|
3acb7d2c89 | ||
|
|
17970a8f8e | ||
|
|
37fdb340cc |
@@ -51,6 +51,7 @@ var (
|
||||
Name: "tls-cert",
|
||||
Usage: "Certificate for secure gRPC. Pass this and the tls-key flag in order to use gRPC securely.",
|
||||
}
|
||||
|
||||
// EnableRPCFlag enables controlling the validator client via gRPC (without web UI).
|
||||
EnableRPCFlag = &cli.BoolFlag{
|
||||
Name: "rpc",
|
||||
@@ -264,6 +265,7 @@ var (
|
||||
Usage: "Disables TLS when connecting to a remote signer. (WARNING! This will result in insecure requests!)",
|
||||
Value: false,
|
||||
}
|
||||
|
||||
// RemoteSignerCertPathFlag defines the path to a client.crt file for a wallet to connect to
|
||||
// a secure signer via TLS and gRPC.
|
||||
RemoteSignerCertPathFlag = &cli.StringFlag{
|
||||
@@ -303,6 +305,24 @@ var (
|
||||
Usage: "comma separated list of public keys OR an external url endpoint for the validator to retrieve public keys from for usage with web3signer",
|
||||
}
|
||||
|
||||
// Web3SignerClientCertFLag is used to specify the PKCS12 client certificate and key in PFX (.p12) format.
|
||||
Web3SignerClientCertFLag = &cli.StringFlag{
|
||||
Name: "validators-external-signer-client-cert",
|
||||
Usage: "PKCS12 client cert and key in PFX (.p12 format. web3signer only supports PKCS12 ",
|
||||
}
|
||||
|
||||
// Web3SignerClientCertPasswordFlag is used to specify the password for the PKCS12 client certificate specified in the "validators-external-signer-client-cert" flag.
|
||||
Web3SignerClientCertPasswordFlag = &cli.StringFlag{
|
||||
Name: "validators-external-signer-client-cert-password",
|
||||
Usage: "path to password for the provided PKCS12 client cert from --validators-external-signer-client-cert",
|
||||
}
|
||||
|
||||
// Web3SignerCACertFLag is used to specify the CA certificate in .pem format.
|
||||
Web3SignerCACertFLag = &cli.StringFlag{
|
||||
Name: "validators-external-signer-ca-cert",
|
||||
Usage: "CA cert used in .pem format",
|
||||
}
|
||||
|
||||
// KeymanagerKindFlag defines the kind of keymanager desired by a user during wallet creation.
|
||||
KeymanagerKindFlag = &cli.StringFlag{
|
||||
Name: "keymanager-kind",
|
||||
|
||||
@@ -75,6 +75,9 @@ var appFlags = []cli.Flag{
|
||||
// Consensys' Web3Signer flags
|
||||
flags.Web3SignerURLFlag,
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
flags.Web3SignerCACertFLag,
|
||||
flags.Web3SignerClientCertPasswordFlag,
|
||||
flags.Web3SignerClientCertFLag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.ProposerSettingsFlag,
|
||||
|
||||
@@ -108,6 +108,9 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.GraffitiFileFlag,
|
||||
flags.Web3SignerURLFlag,
|
||||
flags.Web3SignerPublicValidatorKeysFlag,
|
||||
flags.Web3SignerCACertFLag,
|
||||
flags.Web3SignerClientCertPasswordFlag,
|
||||
flags.Web3SignerClientCertFLag,
|
||||
flags.ProposerSettingsFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
"web3remotesigner.go",
|
||||
],
|
||||
data = [
|
||||
"//testing/endtoend/static-files/certs:web3signer-certs",
|
||||
"//testing/endtoend/static-files/eth1:eth1data",
|
||||
"@lighthouse//:lighthouse_bin",
|
||||
],
|
||||
@@ -45,6 +46,7 @@ go_library(
|
||||
"@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library",
|
||||
"@in_gopkg_yaml_v2//:go_default_library",
|
||||
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
|
||||
"@org_golang_x_crypto//pkcs12:go_default_library",
|
||||
"@org_golang_x_sync//errgroup:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -313,7 +313,6 @@ func (node *BeaconNode) Start(ctx context.Context) error {
|
||||
}
|
||||
node.peerID = peerId
|
||||
}
|
||||
|
||||
// Mark node as ready.
|
||||
close(node.started)
|
||||
|
||||
|
||||
@@ -253,10 +253,17 @@ func (v *ValidatorNode) Start(ctx context.Context) error {
|
||||
args = append(args, features.E2EValidatorFlags...)
|
||||
}
|
||||
if v.config.UseWeb3RemoteSigner {
|
||||
args = append(args, fmt.Sprintf("--%s=http://localhost:%d", flags.Web3SignerURLFlag.Name, Web3RemoteSignerPort))
|
||||
args = append(args, fmt.Sprintf("--%s=https://localhost:%d", flags.Web3SignerURLFlag.Name, Web3RemoteSignerPort))
|
||||
// Write the pubkeys as comma separated hex strings with 0x prefix.
|
||||
// See: https://docs.teku.consensys.net/en/latest/HowTo/External-Signer/Use-External-Signer/
|
||||
args = append(args, fmt.Sprintf("--%s=%s", flags.Web3SignerPublicValidatorKeysFlag.Name, strings.Join(validatorHexPubKeys, ",")))
|
||||
pa, err := bazel.RunfilesPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args = append(args, fmt.Sprintf("--%s=%s", flags.Web3SignerClientCertFLag.Name, pa+"/testing/endtoend/static-files/certs/prysm_client_identity.p12"))
|
||||
args = append(args, fmt.Sprintf("--%s=%s", flags.Web3SignerClientCertPasswordFlag.Name, pa+"/testing/endtoend/static-files/certs/pass.txt"))
|
||||
args = append(args, fmt.Sprintf("--%s=%s", flags.Web3SignerCACertFLag.Name, pa+"/testing/endtoend/static-files/certs/cacerts.pem"))
|
||||
} else {
|
||||
// When not using remote key signer, use interop keys.
|
||||
args = append(args,
|
||||
|
||||
@@ -2,8 +2,11 @@ package components
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -15,6 +18,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
|
||||
"github.com/bazelbuild/rules_go/go/tools/bazel"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
@@ -80,13 +85,21 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
|
||||
// A file path to yaml config file is acceptable network argument.
|
||||
network = testDir
|
||||
}
|
||||
|
||||
pa, err := bazel.RunfilesPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args := []string{
|
||||
// Global flags
|
||||
fmt.Sprintf("--key-store-path=%s", keystorePath),
|
||||
fmt.Sprintf("--data-path=%s", websignerDataDir),
|
||||
fmt.Sprintf("--http-listen-port=%d", Web3RemoteSignerPort),
|
||||
"--logging=ALL",
|
||||
fmt.Sprintf("--tls-keystore-file=%s", pa+"/testing/endtoend/static-files/certs/web3signer_keystore.p12"),
|
||||
fmt.Sprintf("--tls-keystore-password-file=%s", pa+"/testing/endtoend/static-files/certs/pass.txt"),
|
||||
//"--tls-allow-any-client=true",
|
||||
//"--tls-allow-ca-clients=true",
|
||||
fmt.Sprintf("--tls-known-clients-file=%s", pa+"/testing/endtoend/static-files/certs/knownClients.txt"),
|
||||
// Command
|
||||
"eth2",
|
||||
// Command flags
|
||||
@@ -97,6 +110,7 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
|
||||
|
||||
cmd := exec.CommandContext(ctx, binaryPath, args...) // #nosec G204 -- Test code is safe to do this.
|
||||
w.cmd = cmd
|
||||
|
||||
// Write stderr to log files.
|
||||
stderr, err := os.Create(path.Join(e2e.TestParams.LogPath, "web3signer.stderr.log"))
|
||||
if err != nil {
|
||||
@@ -108,17 +122,70 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
|
||||
}
|
||||
}()
|
||||
cmd.Stderr = stderr
|
||||
// Write stdout to log files.
|
||||
stdout, err := os.Create(path.Join(e2e.TestParams.LogPath, "web3signer.stdout.log"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := stdout.Close(); err != nil {
|
||||
log.WithError(err).Error("Failed to close stdout file")
|
||||
}
|
||||
}()
|
||||
cmd.Stdout = stdout
|
||||
|
||||
log.Infof("Starting web3signer with flags: %s %s", binaryPath, strings.Join(args, " "))
|
||||
if err = cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go w.monitorStart()
|
||||
tlsConfig, err := getTLSconfig(pa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go w.monitorStart(tlsConfig)
|
||||
|
||||
return cmd.Wait()
|
||||
}
|
||||
|
||||
func getTLSconfig(runpath string) (*tls.Config, error) {
|
||||
tlsConfig := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
|
||||
p12, err := os.ReadFile(filepath.Clean(runpath + "/testing/endtoend/static-files/certs/prysm_client_identity.p12"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p12pass, err := os.ReadFile(filepath.Clean(runpath + "/testing/endtoend/static-files/certs/pass.txt"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blocks, err := pkcs12.ToPEM(p12, string(p12pass))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "pkcs12 to PEM conversion failed")
|
||||
}
|
||||
var pemData []byte
|
||||
for _, b := range blocks {
|
||||
pemData = append(pemData, pem.EncodeToMemory(b)...)
|
||||
}
|
||||
|
||||
clientPair, err := tls.X509KeyPair(pemData, pemData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to obtain client's certificate and/or key")
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{clientPair}
|
||||
cp := x509.NewCertPool()
|
||||
pemc, err := os.ReadFile(filepath.Clean(runpath + "/testing/endtoend/static-files/certs/cacerts.pem"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cp.AppendCertsFromPEM(pemc)
|
||||
tlsConfig.RootCAs = cp
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
func (w *Web3RemoteSigner) Started() <-chan struct{} {
|
||||
return w.started
|
||||
}
|
||||
@@ -139,15 +206,17 @@ func (w *Web3RemoteSigner) Stop() error {
|
||||
}
|
||||
|
||||
// monitorStart by polling server until it returns a 200 at /upcheck.
|
||||
func (w *Web3RemoteSigner) monitorStart() {
|
||||
client := &http.Client{}
|
||||
func (w *Web3RemoteSigner) monitorStart(config *tls.Config) {
|
||||
client := &http.Client{Transport: &http.Transport{TLSClientConfig: config}}
|
||||
for {
|
||||
req, err := http.NewRequestWithContext(w.ctx, "GET", fmt.Sprintf("http://localhost:%d/upcheck", Web3RemoteSignerPort), nil)
|
||||
req, err := http.NewRequestWithContext(w.ctx, "GET", fmt.Sprintf("https://localhost:%d/upcheck", Web3RemoteSignerPort), nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res, err := client.Do(req)
|
||||
_ = err
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Web3signer upcheck failed, attempting again until time out...")
|
||||
}
|
||||
if res != nil && res.StatusCode == 200 {
|
||||
close(w.started)
|
||||
return
|
||||
@@ -170,9 +239,21 @@ func (w *Web3RemoteSigner) wait(ctx context.Context) {
|
||||
// PublicKeys queries the web3signer and returns the response keys.
|
||||
func (w *Web3RemoteSigner) PublicKeys(ctx context.Context) ([]bls.PublicKey, error) {
|
||||
w.wait(ctx)
|
||||
pa, err := bazel.RunfilesPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tlsConfig, err := getTLSconfig(pa)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("http://localhost:%d/api/v1/eth2/publicKeys", Web3RemoteSignerPort), nil)
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://localhost:%d/api/v1/eth2/publicKeys", Web3RemoteSignerPort), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu-portable.tar.g
|
||||
def e2e_deps():
|
||||
http_archive(
|
||||
name = "web3signer",
|
||||
urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/22.8.1/web3signer-22.8.1.tar.gz"],
|
||||
sha256 = "ec888222484c4d1b6203bd6d248890adf713f8bf47fb362fb36e8d47a98cb401",
|
||||
urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/23.1.0/web3signer-23.1.0.tar.gz"],
|
||||
sha256 = "47b6ff266d0c99185e4a4a595bc2e0578f0f722fb08baa80df462938f2f8fe74",
|
||||
build_file = "@prysm//testing/endtoend:web3signer.BUILD",
|
||||
strip_prefix = "web3signer-22.8.1",
|
||||
strip_prefix = "web3signer-23.1.0",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
|
||||
12
testing/endtoend/static-files/certs/BUILD.bazel
Normal file
12
testing/endtoend/static-files/certs/BUILD.bazel
Normal file
@@ -0,0 +1,12 @@
|
||||
filegroup(
|
||||
name = "web3signer-certs",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"cacerts.pem",
|
||||
"knownClients.txt",
|
||||
"pass.txt",
|
||||
"prysm_client_identity.p12",
|
||||
"web3signer_keystore.p12",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
38
testing/endtoend/static-files/certs/cacerts.pem
Normal file
38
testing/endtoend/static-files/certs/cacerts.pem
Normal file
@@ -0,0 +1,38 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDDDCCAfSgAwIBAgIEAaZvuDANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJy
|
||||
b290Lm15Y29tcGFueS5jb20wHhcNMjMwMTE3MjIyNDAyWhcNMjMwNDE3MjIyNDAy
|
||||
WjAdMRswGQYDVQQDExJyb290Lm15Y29tcGFueS5jb20wggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQCEDj2ZTxcd5rfm/ULK+b2jGjR3aaDh8HCLs3DV9ZPx
|
||||
N7VyWduEkE6mIJqTw0inZS1d9czVgH5klY5yZ5Xw6vKcrbN0JXm8TrShkpzfGADu
|
||||
9enKqyk97XtHALqx6Ie1IB/agmeMiwPr5il7Y/1EFu2f9ocfE+2mBhvhjGEo9USm
|
||||
EtsXAjsSAivCU1szALFBk2rrU8GPG6945PmD7no9YfAJNYPfLCG8zOTUPK/oBmXm
|
||||
+NhZ+kbNP0PsgfgrKI6fC2qxQ9HI6GyDidSHvntSVq5RSi33PwFc2zfjMWOb1MXR
|
||||
fnoPp4Z1M9NSxxScZ4DNnTaPWm+gvfUuEo5jvuQ1Gn8hAgMBAAGjVDBSMB0GA1Ud
|
||||
DgQWBBSG533gVFLJywsRI8boDs2fUm26MTAgBgNVHREEGTAXgglsb2NhbGhvc3SH
|
||||
BH8AAAGHBAoAAAUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
fVJc1FCUjBQ/MY6D5j4o2JYAxu1Gl4EFN/dOhUzhnvUihz3DfRzlxKLHoMCG+2Ew
|
||||
e3HoMIrHBJskp6zw3UawlrBikS6HNther1DXpz5HshSmqBKUAxAI4/Dg74z8kyUt
|
||||
GsEB0vwWX5m9ErIGmsaYKK86ucIDgQeyK3SOxHy2Ob1kmjluox9RoJGH9PU0FoxV
|
||||
D+9PSypqh7dFaiCiiTMxPJW7cpEkF9DDLvXIwHOigNkglB32pUaURIYVtqgd7RzM
|
||||
7FdqCSHTlAZskyBm+Vu8B1ez7JUfDyRVVaXNPoea/4y1Csj8bQrcBfw9d8uO9uLi
|
||||
tLArdWb0jpS3jjwCWIjfrw==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDKzCCAhOgAwIBAgIEdnJ86zANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJy
|
||||
b290Lm15Y29tcGFueS5jb20wHhcNMjMwMTE3MjIyNDU2WhcNMjMwNDE3MjIyNDU2
|
||||
WjAbMRkwFwYDVQQDExBjYS5teWNvbXBhbnkuY29tMIIBIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAQ8AMIIBCgKCAQEAl0zBNXzYWIZS5zF74EXdFAuyh7l8K6GBQTDvAczbKQoX
|
||||
tPrANE1mHhbqLYGFrtThEaNxFxsN/mzatp88L6yw/LdMviCvYTPUEvai0tWe3ATc
|
||||
i43o6GI8/0Yvp8s0vSd5STuSR3B7pvrK3G1RVAr8ZmwKFaDJvxgYiYEItpra3U9+
|
||||
AdRmQV6WRH/QRLs0xA8rAJMIUPvHzYJSiUHNop1FaOnWEEsH+dQhax0GGrSOGvcC
|
||||
GTRPKY8exoZ4W/UYs/Entc0vdVKch0T3OkWeSOqEXBz2drTVah7gjbJ6cB54BM9t
|
||||
6wy0gZE8AD3jUbZTTfMw9aa5MCtoKUqXss+cp/dctwIDAQABo3UwczAdBgNVHQ4E
|
||||
FgQUCxe24+bRbxpjNrMlfVT8P43Qv2kwIAYDVR0RBBkwF4IJbG9jYWxob3N0hwR/
|
||||
AAABhwQKAAAFMA8GA1UdEwQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUhud94FRSycsL
|
||||
ESPG6A7Nn1JtujEwDQYJKoZIhvcNAQELBQADggEBABGqa3RncfzhfwbH1dYiBPrs
|
||||
EahzGvNfgkcvZGWYy2j/uo5HL3O0TnvpiZKo5mcAvGQvtMXFVU27dK+Prk0LBLLJ
|
||||
TXlT7H788SVRgt0HJec/NNvnzOA72F4S9w33eyazGCcafx9Zr4vf+jTtQbh995wT
|
||||
QhLuSQ4yIVBUMDLoq+1gjeEnj7nMatNgQ3ThWYE7sl7EOip7ZTLt7p3LCEDkzHvC
|
||||
yhQKcaQ454k0HW4OLNrdEIkFiuBHVEV67ufZ+Vpunr9GftpUddCPXiU0MXayMo95
|
||||
Nmsv4ojp9w3xPH0oIUadJT8YM50Ui6KcvJ6cIcJZFCE29Yq6nl7hzeGTsz/twu4=
|
||||
-----END CERTIFICATE-----
|
||||
1
testing/endtoend/static-files/certs/knownClients.txt
Normal file
1
testing/endtoend/static-files/certs/knownClients.txt
Normal file
@@ -0,0 +1 @@
|
||||
prysm DB:6D:20:46:3A:54:56:18:BB:EC:FF:BA:9F:55:5D:BF:A9:A2:96:BC:2F:8B:5F:9A:D8:4D:13:EF:BF:D7:90:5A
|
||||
1
testing/endtoend/static-files/certs/pass.txt
Executable file
1
testing/endtoend/static-files/certs/pass.txt
Executable file
@@ -0,0 +1 @@
|
||||
changeit
|
||||
BIN
testing/endtoend/static-files/certs/prysm_client_identity.p12
Normal file
BIN
testing/endtoend/static-files/certs/prysm_client_identity.p12
Normal file
Binary file not shown.
BIN
testing/endtoend/static-files/certs/web3signer_keystore.p12
Normal file
BIN
testing/endtoend/static-files/certs/web3signer_keystore.p12
Normal file
Binary file not shown.
@@ -29,12 +29,16 @@ go_library(
|
||||
"@com_github_prometheus_client_golang//prometheus:go_default_library",
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_x_crypto//pkcs12:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["keymanager_test.go"],
|
||||
data = [
|
||||
"//testing/endtoend/static-files/certs:web3signer-certs",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
@@ -42,10 +46,10 @@ go_test(
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/eth/service:go_default_library",
|
||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//validator/keymanager/remote-web3signer/internal:go_default_library",
|
||||
"//validator/keymanager/remote-web3signer/v1/mock:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_stretchr_testify//assert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -28,8 +28,8 @@ go_test(
|
||||
srcs = ["client_test.go"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_stretchr_testify//assert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package internal
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -46,8 +47,25 @@ type ApiClient struct {
|
||||
RestClient *http.Client
|
||||
}
|
||||
|
||||
// ApiClientOpt is a functional option for the Client type (http.Client wrapper)
|
||||
type ApiClientOpt func(*ApiClient)
|
||||
|
||||
// WithTls Enables two-way TLS on the API using the provided cert information.
|
||||
func WithTls(config *tls.Config) ApiClientOpt {
|
||||
return func(c *ApiClient) {
|
||||
if c.RestClient.Transport == nil {
|
||||
c.RestClient.Transport = &http.Transport{TLSClientConfig: config}
|
||||
} else {
|
||||
if tpt, ok := c.RestClient.Transport.(*http.Transport); ok {
|
||||
tpt.TLSClientConfig = config
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// NewApiClient method instantiates a new ApiClient object.
|
||||
func NewApiClient(baseEndpoint string) (*ApiClient, error) {
|
||||
func NewApiClient(baseEndpoint string, opts ...ApiClientOpt) (*ApiClient, error) {
|
||||
u, err := url.ParseRequestURI(baseEndpoint)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid format, unable to parse url")
|
||||
@@ -55,10 +73,14 @@ func NewApiClient(baseEndpoint string) (*ApiClient, error) {
|
||||
if u.Scheme == "" || u.Host == "" {
|
||||
return nil, fmt.Errorf("web3signer url must be in the format of http(s)://host:port url used: %v", baseEndpoint)
|
||||
}
|
||||
return &ApiClient{
|
||||
c := &ApiClient{
|
||||
BaseURL: u,
|
||||
RestClient: &http.Client{},
|
||||
}, nil
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Sign is a wrapper method around the web3signer sign api.
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v3/validator/keymanager/remote-web3signer/internal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// mockTransport is the mock Transport object
|
||||
@@ -47,8 +47,8 @@ func TestClient_Sign_HappyPath(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest)
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal()))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal()))
|
||||
}
|
||||
|
||||
func TestClient_Sign_HappyPath_Jsontype(t *testing.T) {
|
||||
@@ -76,8 +76,8 @@ func TestClient_Sign_HappyPath_Jsontype(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest)
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal()))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "0xb3baa751d0a9132cfe93e4e3d5ff9075111100e3789dca219ade5a24d27e19d16b3353149da1833e9b691bb38634e8dc04469be7032132906c927d7e1a49b414730612877bc6b2810c8f202daf793d1ab0d6b5cb21d52f9e52e883859887a5d9", fmt.Sprintf("%#x", resp.Marshal()))
|
||||
}
|
||||
|
||||
func TestClient_Sign_500(t *testing.T) {
|
||||
@@ -95,7 +95,7 @@ func TestClient_Sign_500(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, nil, resp)
|
||||
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func TestClient_Sign_412(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, nil, resp)
|
||||
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func TestClient_Sign_400(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
resp, err := cl.Sign(context.Background(), "a2b5aaad9c6efefe7bb9b1243a043404f3362937cfb6b31833929833173f476630ea2cfeb0d9ddf15f97ca8685948820", jsonRequest)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, nil, resp)
|
||||
|
||||
}
|
||||
|
||||
@@ -151,9 +151,9 @@ func TestClient_GetPublicKeys_HappyPath(t *testing.T) {
|
||||
cl := internal.ApiClient{BaseURL: u, RestClient: &http.Client{Transport: mock}}
|
||||
resp, err := cl.GetPublicKeys(context.Background(), "example.com/api/publickeys")
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.NoError(t, err)
|
||||
// we would like them as 48byte base64 without 0x
|
||||
assert.EqualValues(t, "[162 181 170 173 156 110 254 254 123 185 177 36 58 4 52 4 243 54 41 55 207 182 179 24 51 146 152 51 23 63 71 102 48 234 44 254 176 217 221 241 95 151 202 134 133 148 136 32]", fmt.Sprintf("%v", resp[0][:]))
|
||||
assert.Equal(t, "[162 181 170 173 156 110 254 254 123 185 177 36 58 4 52 4 243 54 41 55 207 182 179 24 51 146 152 51 23 63 71 102 48 234 44 254 176 217 221 241 95 151 202 134 133 148 136 32]", fmt.Sprintf("%v", resp[0][:]))
|
||||
}
|
||||
|
||||
func TestClient_GetPublicKeys_EncodingError(t *testing.T) {
|
||||
@@ -170,7 +170,7 @@ func TestClient_GetPublicKeys_EncodingError(t *testing.T) {
|
||||
cl := internal.ApiClient{BaseURL: u, RestClient: &http.Client{Transport: mock}}
|
||||
resp, err := cl.GetPublicKeys(context.Background(), "example.com/api/publickeys")
|
||||
assert.Equal(t, err.Error(), "failed to decode from Hex from the following public key index locations: 0, 1, 2, ")
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, 0, len(resp))
|
||||
}
|
||||
|
||||
// TODO: not really in use, should be revisited
|
||||
@@ -183,7 +183,7 @@ func TestClient_ReloadSignerKeys_HappyPath(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
cl := internal.ApiClient{BaseURL: u, RestClient: &http.Client{Transport: mock}}
|
||||
err = cl.ReloadSignerKeys(context.Background())
|
||||
assert.Nil(t, err)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: not really in use, should be revisited
|
||||
@@ -199,5 +199,5 @@ func TestClient_GetServerStatus_HappyPath(t *testing.T) {
|
||||
cl := internal.ApiClient{BaseURL: u, RestClient: &http.Client{Transport: mock}}
|
||||
resp, err := cl.GetServerStatus(context.Background())
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,12 @@ package remote_web3signer
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
@@ -22,6 +26,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/validator/keymanager/remote-web3signer/internal"
|
||||
web3signerv1 "github.com/prysmaticlabs/prysm/v3/validator/keymanager/remote-web3signer/v1"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
||||
// SetupConfig includes configuration values for initializing.
|
||||
@@ -40,6 +45,10 @@ type SetupConfig struct {
|
||||
// a static list of public keys to be passed by the user to determine what accounts should sign.
|
||||
// This will provide a layer of safety against slashing if the web3signer is shared across validators.
|
||||
ProvidedPublicKeys [][48]byte
|
||||
|
||||
ClientCertPath string
|
||||
ClientCertPasswordPath string
|
||||
CACertPath string
|
||||
}
|
||||
|
||||
// Keymanager defines the web3signer keymanager.
|
||||
@@ -58,7 +67,16 @@ func NewKeymanager(_ context.Context, cfg *SetupConfig) (*Keymanager, error) {
|
||||
if cfg.BaseEndpoint == "" || !bytesutil.IsValidRoot(cfg.GenesisValidatorsRoot) {
|
||||
return nil, fmt.Errorf("invalid setup config, one or more configs are empty: BaseEndpoint: %v, GenesisValidatorsRoot: %#x", cfg.BaseEndpoint, cfg.GenesisValidatorsRoot)
|
||||
}
|
||||
client, err := internal.NewApiClient(cfg.BaseEndpoint)
|
||||
options := make([]internal.ApiClientOpt, 0)
|
||||
tlsOpt, err := configureTLSOpt(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tlsOpt != nil {
|
||||
options = append(options, tlsOpt)
|
||||
}
|
||||
|
||||
client, err := internal.NewApiClient(cfg.BaseEndpoint, options...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create apiClient")
|
||||
}
|
||||
@@ -73,6 +91,60 @@ func NewKeymanager(_ context.Context, cfg *SetupConfig) (*Keymanager, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func configureTLSOpt(cfg *SetupConfig) (internal.ApiClientOpt, error) {
|
||||
if cfg.ClientCertPath != "" || cfg.ClientCertPasswordPath != "" || cfg.CACertPath != "" {
|
||||
tlsConfig := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
if cfg.ClientCertPath != "" || cfg.ClientCertPasswordPath != "" {
|
||||
if cfg.ClientCertPath == "" {
|
||||
return nil, errors.New("PKCS12 client certificate is required")
|
||||
}
|
||||
if cfg.ClientCertPasswordPath == "" {
|
||||
return nil, errors.New("PKCS12 client certificate password is required")
|
||||
}
|
||||
p12, err := os.ReadFile(filepath.Clean(cfg.ClientCertPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p12pass, err := os.ReadFile(filepath.Clean(cfg.ClientCertPasswordPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blocks, err := pkcs12.ToPEM(p12, string(p12pass))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "pkcs12 to PEM conversion failed")
|
||||
}
|
||||
var pemData []byte
|
||||
for _, b := range blocks {
|
||||
pemData = append(pemData, pem.EncodeToMemory(b)...)
|
||||
}
|
||||
|
||||
clientPair, err := tls.X509KeyPair(pemData, pemData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to obtain client's certificate and/or key")
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{clientPair}
|
||||
}
|
||||
|
||||
cp := x509.NewCertPool()
|
||||
// Load the CA for the server certificate if present.
|
||||
if cfg.CACertPath != "" {
|
||||
serverCA, err := os.ReadFile(cfg.CACertPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to obtain server's CA certificate")
|
||||
}
|
||||
if !cp.AppendCertsFromPEM(serverCA) {
|
||||
return nil, errors.Wrap(err, "failed to add server's CA certificate to pool")
|
||||
}
|
||||
}
|
||||
tlsConfig.RootCAs = cp
|
||||
return internal.WithTls(tlsConfig), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// FetchValidatingPublicKeys fetches the validating public keys
|
||||
// from the remote server or from the provided keys if there are no existing public keys set
|
||||
// or provides the existing keys in the keymanager.
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||
ethpbservice "github.com/prysmaticlabs/prysm/v3/proto/eth/service"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/validator-client"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v3/validator/keymanager/remote-web3signer/internal"
|
||||
"github.com/prysmaticlabs/prysm/v3/validator/keymanager/remote-web3signer/v1/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type MockClient struct {
|
||||
@@ -212,8 +212,8 @@ func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithKeyList(t *testing.T
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, resp, keys)
|
||||
assert.NoError(t, err)
|
||||
require.DeepEqual(t, resp, keys)
|
||||
}
|
||||
|
||||
func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithExternalURL(t *testing.T) {
|
||||
@@ -247,8 +247,8 @@ func TestKeymanager_FetchValidatingPublicKeys_HappyPath_WithExternalURL(t *testi
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
assert.NotNil(t, resp)
|
||||
assert.Nil(t, err)
|
||||
assert.EqualValues(t, resp, keys)
|
||||
assert.NoError(t, err)
|
||||
require.DeepEqual(t, resp, keys)
|
||||
}
|
||||
|
||||
func TestKeymanager_FetchValidatingPublicKeys_WithExternalURL_ThrowsError(t *testing.T) {
|
||||
@@ -273,7 +273,7 @@ func TestKeymanager_FetchValidatingPublicKeys_WithExternalURL_ThrowsError(t *tes
|
||||
km.client = client
|
||||
resp, err := km.FetchValidatingPublicKeys(ctx)
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, 0, len(resp))
|
||||
assert.Equal(t, "could not get public keys from remote server url: http://example2.com/api/v1/eth2/publicKeys: mock error", fmt.Sprintf("%v", err))
|
||||
}
|
||||
|
||||
@@ -345,3 +345,82 @@ func TestKeymanager_DeletePublicKeys(t *testing.T) {
|
||||
require.Equal(t, ethpbservice.DeletedRemoteKeysStatus_NOT_FOUND, status.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKeymanager_Certificates(t *testing.T) {
|
||||
// web3signer only supports PKCS12
|
||||
base := "../../../testing/endtoend/static-files/certs/"
|
||||
clientcert := "prysm_client_identity.p12"
|
||||
cacert := "cacerts.pem"
|
||||
tests := []struct {
|
||||
name string
|
||||
opts *SetupConfig
|
||||
err string
|
||||
}{
|
||||
{
|
||||
name: "skips tls",
|
||||
opts: &SetupConfig{},
|
||||
},
|
||||
{
|
||||
name: "NoClientPass",
|
||||
opts: &SetupConfig{
|
||||
ClientCertPath: base + clientcert,
|
||||
},
|
||||
err: "PKCS12 client certificate password is required",
|
||||
},
|
||||
{
|
||||
name: "happy path tls activated",
|
||||
opts: &SetupConfig{
|
||||
ClientCertPath: base + clientcert,
|
||||
ClientCertPasswordPath: base + "pass.txt",
|
||||
CACertPath: base + cacert,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "BadClientCert",
|
||||
opts: &SetupConfig{
|
||||
ClientCertPath: base + "pass.txt",
|
||||
ClientCertPasswordPath: base + "pass.txt",
|
||||
},
|
||||
err: "pkcs12 to PEM conversion failed",
|
||||
},
|
||||
{
|
||||
name: "BadClientPassword",
|
||||
opts: &SetupConfig{
|
||||
ClientCertPath: base + clientcert,
|
||||
ClientCertPasswordPath: base + cacert,
|
||||
},
|
||||
err: "pkcs12 to PEM conversion failed: pkcs12: decryption password incorrect",
|
||||
},
|
||||
{
|
||||
name: "MissingCACert",
|
||||
opts: &SetupConfig{
|
||||
ClientCertPath: base + clientcert,
|
||||
ClientCertPasswordPath: base + "pass.txt",
|
||||
CACertPath: `bad`,
|
||||
},
|
||||
err: "failed to obtain server's CA certificate: open bad: no such file or directory",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
root, err := hexutil.Decode("0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69")
|
||||
if err != nil {
|
||||
fmt.Printf("error: %v", err)
|
||||
}
|
||||
_, err = NewKeymanager(context.Background(), &SetupConfig{
|
||||
BaseEndpoint: "http://example.com",
|
||||
GenesisValidatorsRoot: root,
|
||||
PublicKeysURL: "http://example2.com/api/v1/eth2/publicKeys",
|
||||
ClientCertPath: test.opts.ClientCertPath,
|
||||
ClientCertPasswordPath: test.opts.ClientCertPasswordPath,
|
||||
CACertPath: test.opts.CACertPath,
|
||||
})
|
||||
if test.err == "" {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.ErrorContains(t, test.err, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,6 +456,12 @@ func Web3SignerConfig(cliCtx *cli.Context) (*remoteweb3signer.SetupConfig, error
|
||||
BaseEndpoint: u.String(),
|
||||
GenesisValidatorsRoot: nil,
|
||||
}
|
||||
|
||||
// set up TLS if required
|
||||
web3signerConfig.ClientCertPath = cliCtx.String(flags.Web3SignerClientCertFLag.Name)
|
||||
web3signerConfig.ClientCertPasswordPath = cliCtx.String(flags.Web3SignerClientCertPasswordFlag.Name)
|
||||
web3signerConfig.CACertPath = cliCtx.String(flags.Web3SignerCACertFLag.Name)
|
||||
|
||||
if cliCtx.IsSet(flags.WalletPasswordFileFlag.Name) {
|
||||
log.Warnf("%s was provided while using web3signer and will be ignored", flags.WalletPasswordFileFlag.Name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user