-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: bls remote signer #745
Conversation
283dc0e
to
0b23714
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. Added a bunch of nits
node/config.go
Outdated
BLSRemoteSignerUrl string | ||
BLSPublicKeyHex string | ||
BLSKeyPassword string | ||
BLSSignerTLSCertFilePath string | ||
UseBLSRemoteSigner bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BLSRemoteSignerUrl string | |
BLSPublicKeyHex string | |
BLSKeyPassword string | |
BLSSignerTLSCertFilePath string | |
UseBLSRemoteSigner bool | |
BLSRemoteSignerEnabled bool | |
BLSRemoteSignerUrl string | |
BLSPublicKeyHex string | |
BLSKeyPassword string | |
BLSSignerTLSCertFilePath string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally prefer to keep same naming convention for all vars, and to have the enabled
var at the top.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe consider creating subconfigs also? The config for the node is crazy long.
node/config.go
Outdated
@@ -143,14 +152,20 @@ func NewConfig(ctx *cli.Context) (*Config, error) { | |||
ethClientConfig = geth.ReadEthClientConfig(ctx) | |||
} | |||
|
|||
// check if BLS remote signer configuration is provided | |||
useBLSRemoteSigner := ctx.GlobalString(flags.BLSRemoteSignerUrlFlag.Name) != "" && ctx.GlobalString(flags.BLSPublicKeyHexFlag.Name) != "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally prefer to have an explicit flag to turn a feature on/off
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BLSPublicKeyHexFlag = cli.StringFlag{ | ||
Name: common.PrefixFlag(FlagPrefix, "bls-public-key-hex"), | ||
Usage: "The hex-encoded public key of the BLS signer", | ||
Required: false, | ||
EnvVar: common.PrefixEnvVar(EnvVarPrefix, "BLS_PUBLIC_KEY_HEX"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does bls signer do auth? Or does it just store a bunch of private keys and if I have access to its endpoint then I can just ask it to sign from any private key just by giving it the respective public key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right now it doesn't support auth - you can ask for any public key hex. but I think we will support it eventually.
node/grpc/server.go
Outdated
@@ -283,7 +283,10 @@ func (s *Server) AttestBatch(ctx context.Context, in *pb.AttestBatchRequest) (*p | |||
if err != nil { | |||
return nil, fmt.Errorf("failed to get the batch header hash: %w", err) | |||
} | |||
sig := s.node.KeyPair.SignMessage(batchHeaderHash) | |||
sig, err := s.node.GetSignature(ctx, batchHeaderHash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider renaming GetSignature
to just Sign
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea - good suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node/node.go
Outdated
return signature, nil | ||
} | ||
|
||
func (n *Node) GetSignature(ctx context.Context, data [32]byte) (*core.Signature, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (n *Node) GetSignature(ctx context.Context, data [32]byte) (*core.Signature, error) { | |
func (n *Node) SignMessage(ctx context.Context, data [32]byte) (*core.Signature, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename to SignMessage to match the keypair.SignMessage function?
if config.PrivateBls != "" { | ||
nodeLogger.Info("using local keystore private key for BLS signing") | ||
// Generate BLS keys | ||
keyPair, err = core.MakeKeyPairFromString(config.PrivateBls) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
config.ID = keyPair.GetPubKeyG1().GetOperatorID() | ||
} else { | ||
pkBytes, err := hex.DecodeString(config.BLSPublicKeyHex) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally find this a bit confusing to read.
Is the intention that:
- test mode: bls private key
- prod mode: bls sk file OR bls remote signer
?
in config.go above you first check if !testmode, then build the bls remote signer, so I think here you should also duplicate the logic (for redundancy and future buggy refactor proofing) - check
if !testMode && config.PrivateBls != ""
or something. Haven't thought this through, but I personally don't like any implicit stuff (like implicitly turning bls remote signer when some other flag is present. Prefer everything to have an "enabled" switch. Perhaps you can have a SignerType
flag, and then crash when that thing is set to private-key and testMode is set to disabled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test mode: bls private key
prod mode: bls sk file OR bls remote signer
?
Yes - I am not aware where test mode is used? maybe I think in inabox testing but yes that's the intention - in prod you can use either encrypted sk file or remote signer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so what I can do is - have an explicit flag which switches between sk file and bls remote signer. PrivateBls
is not really used in prod. maybe @ian-shim can confirm but I think thats true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should eventually remove out test node and use either sk file or remote signer as that clearly mimics prod usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the ugly thing about testMode and prod mode with sk file is - both these cases populate privateBls
and that's why checking testMode is not going to work here. since privateBls
is populated in non testMode too. https://github.com/Layr-Labs/eigenda/pull/745/files#diff-923e406f4251573464f7748834b59f4747b3f6ec4eadda667614e2875a3b811aR166-R174
I think ideal would be to remove this testMode and eventually put the prod signing behind eigensdk as I said in above comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test mode I think is just used to allow passing a sk directly? Think it should be allowed to simplify tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if that would remain - in current way - privateBls
will be populated for both. I guess we could change eventually when we abstract out signing behind eigensdk
}, | ||
) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to sign data: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
security check: are you sure that the error returned from your bls remote signer never leaks any sensitive info?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope it does not. nothing ever returns any sensitive information from the signer itself.
return nil, err | ||
} | ||
} | ||
conn, err := grpc.NewClient( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if this connection gets broken while node is running?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A grpc « connection » is really a virtual connection. It’s not 1-1 with the underlying tcp connection. If tcp conn drops the grpc runtime dials a new connection.
don’t think grpc « connection » can ever be disconnected. But worth checking if there are conditions that need to be checked/handled.
@@ -114,6 +116,47 @@ func NewNode(reg *prometheus.Registry, config *Config, pubIPProvider pubip.Provi | |||
// Create ChainState Client | |||
cst := eth.NewChainState(tx, client) | |||
|
|||
var keyPair *core.KeyPair | |||
var blsClient blssignerV1.SignerClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this one-of pattern where one is expected to be nil and the other is not is very brittle.
There is this pattern in Config
where PrivateBls
can be empty and here where one of either keyPair
or blsClient
is nil.
Downstream, these attributes can't be assumed to be non-nil and there needs to be if/else nil check whenever they're accessed (or worse, forgetting to check this would result in panic).
Is there a blsClient abstraction that allows local signing with private bls key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! This is what I was trying to describe in #745 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a blsClient abstraction that allows local signing with private bls key?
I am thinking of having this abstraction in eigensdk and then you just initialize signer and based on config it would sign. Once I do that - we can switch it out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that will be done & reflected in this PR? Or in a future PR?
0b23714
to
4077779
Compare
4077779
to
abe83f8
Compare
Bump go-ethereum to latet to resolve unit tests go-verkle was causing unit test failures with
Resolve grpc.Dial deprecations due to cerbereus bumping grpc from v1.59.0 -> v1.64.1
see https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md for why |
update docker file for private repo remove the go private deps api fix deps fix flags fix convert support latest signer support latest signer support latest signer replace with cerberus add cert file path operator id move log up move function up move function up fix incorrect logic clean and and make backward compatible clean up
go-verkle was causing unit test failures with `type *banderwagon.Element has no field or method BytesUncompressed` ``` go mod graph | grep go-verkle github.com/Layr-Labs/eigenda github.com/gballet/[email protected] github.com/ethereum/[email protected] github.com/gballet/[email protected] github.com/gballet/[email protected] github.com/crate-crypto/[email protected] github.com/gballet/[email protected] golang.org/x/[email protected] github.com/gballet/[email protected] github.com/bits-and-blooms/[email protected] github.com/gballet/[email protected] github.com/consensys/[email protected] github.com/gballet/[email protected] github.com/consensys/[email protected] github.com/gballet/[email protected] github.com/mmcloughlin/[email protected] github.com/gballet/[email protected] golang.org/x/[email protected] github.com/gballet/[email protected] rsc.io/[email protected] ``` Resolve grpc.Dial deprecations due to cerbereus bumping grpc from v1.59.0 -> v1.64.1 - Updates `grpc.Dial` -> `grpc.NewClient` - Removes `withBlock()` option from `grpcConnection.Dial` used by syntetic checks. see https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md for why `withBlock()` was deprecated.
abe83f8
to
caa6681
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one last comment
return nil, fmt.Errorf("could not read or decrypt the BLS private key: %v", err) | ||
// If remote signer fields are empty then try to read the BLS key from the file | ||
if !blsRemoteSignerEnabled { | ||
kp, err := bls.ReadPrivateKeyFromFile(ctx.GlobalString(flags.BlsKeyFileFlag.Name), ctx.GlobalString(flags.BlsKeyPasswordFlag.Name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BlsKeyFileFlag
is still a required flag. Does it need to be an optional field now?
Why are these changes needed?
Checks