Skip to content
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(signer): add ECDSA proxy keys #87

Merged
merged 38 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
02acf38
refactor(signer)!: generalize for other signature schemes than BLS
David-Petrov Aug 9, 2024
a7c76df
feat(signer)!: add support for ECDSA proxy keys
David-Petrov Aug 13, 2024
5530567
Merge branch 'main' into feat/ecdsa-proxy-keys
David-Petrov Aug 13, 2024
a5450b6
chore(clippy): infallible instead of fallible conversions
David-Petrov Aug 14, 2024
a9ff828
chore(signer): resolve TODOs
David-Petrov Aug 14, 2024
4e96742
refactor(signer)!: move around
David-Petrov Aug 14, 2024
4b283e2
chore(signer)!: rename associated type and type alias
David-Petrov Aug 14, 2024
9d70712
choer(signer): rename client `Signature` type
David-Petrov Aug 14, 2024
287da33
refactor(signer)!: remove default type parameter in `Signer`
David-Petrov Aug 14, 2024
431f189
chore(clippy): remove unnecessary nested reference
David-Petrov Aug 14, 2024
8041e0f
chore: remove commented code
David-Petrov Aug 15, 2024
23437a2
refactor(signer/ecdsa): derive unnecessary trait impls
David-Petrov Aug 15, 2024
9078e25
style: remove unnecessary constraint duplication
David-Petrov Aug 15, 2024
377aa78
refactor(signer)!: rename module `signers` to `signer` and constrain …
David-Petrov Aug 15, 2024
b83841e
refactor(loader): unify `ConsensusSigner` type alias usage
David-Petrov Aug 15, 2024
7e1bf44
chore!: remove forgotten debug
David-Petrov Aug 20, 2024
eba97b0
refactor(signer)!: [WIP] simplify proxy keys
David-Petrov Aug 21, 2024
ad6d373
refactor(signer)!: separate BLS and ECDSA types in client SDK
David-Petrov Aug 21, 2024
fede09c
chore(signer)!: reformat & clean up
David-Petrov Aug 21, 2024
68fce43
refactor(signer/manager): remove enum `GenericProxySigner`
David-Petrov Aug 22, 2024
a7d53a1
refactor(signer)!: make `SignedProxyDelegation` generic in the public…
David-Petrov Aug 22, 2024
780299e
refactor(signer/request): make `SignProxyRequest` generic in the publ…
David-Petrov Aug 23, 2024
7ddcd3a
refactor(signer/manager)!: split generic `get_delegation` into two se…
David-Petrov Aug 23, 2024
b8f228b
refactor(signer/client): remove unnecessary `Vec<u8>` deserialization
David-Petrov Aug 27, 2024
635f620
feat(signer): add tests for ECDSA proxies
David-Petrov Aug 27, 2024
dd864ec
refactor(signer/api)!: proper struct serde
David-Petrov Aug 28, 2024
b3286d5
refactor(signer): remove unnecessary module
David-Petrov Aug 28, 2024
7dedbcf
refactor(signer)!: remove `GenericPubkey`
David-Petrov Aug 28, 2024
f075db9
refactor(signer/request): move `GetPubkeysResponse`
David-Petrov Aug 28, 2024
9c4f412
refactor(signer): reduce code duplication around `SignRequest`
David-Petrov Aug 28, 2024
4e652d9
style/refactor(signer): reduce method size
David-Petrov Aug 28, 2024
9907059
refactor(deps)!: revert version updates
David-Petrov Aug 28, 2024
0ff2091
chore(deps)!: remove unused deps
David-Petrov Aug 28, 2024
dea0b0c
chore(signer): add TODO for `BlsPublicKey` wrapper
David-Petrov Aug 29, 2024
5fc50ae
refactor(signer)!: re-export request types properly from prelude
David-Petrov Aug 29, 2024
0bcd2d7
feat(signer/api): update api docs
David-Petrov Aug 29, 2024
f103c8d
refactor(signer/client): re-export bls types and rename methods for c…
David-Petrov Aug 29, 2024
da550d3
chore(docs): update md files in book
David-Petrov Aug 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cb-signer = { path = "crates/signer" }
alloy = { version = "0.2.0", features = ["rpc-types-beacon"] }
ethereum_ssz = "0.5"
ethereum_ssz_derive = "0.5.3"
ssz_types = "0.5"
ssz_types = "0.6.0"
ethereum_serde_utils = "0.5.2"
ethereum-types = "0.14.1"

Expand Down Expand Up @@ -59,9 +59,12 @@ prometheus = "0.13.4"

# crypto
blst = "0.3.11"
tree_hash = "0.5"
tree_hash_derive = "0.5"
tree_hash = "0.6.0"
tree_hash_derive = "0.6.0"
David-Petrov marked this conversation as resolved.
Show resolved Hide resolved
eth2_keystore = { git = "https://github.com/sigp/lighthouse", rev = "9e12c21f268c80a3f002ae0ca27477f9f512eb6f" }
elliptic-curve = { version = "0.13", features = ["serde"] }
generic-array = { version = "0.14.7", features = ["serde"] }
k256 = "0.13"

# docker
docker-compose-types = "0.12.0"
Expand All @@ -79,4 +82,4 @@ dotenvy = "0.15.7"
indexmap = "2.2.6"
lazy_static = "1.5.0"
bimap = { version = "0.6.3", features = ["serde"] }
derive_more = "0.99.18"
derive_more = { version = "1.0.0", features = ["from", "into", "deref", "display"] }
6 changes: 5 additions & 1 deletion bin/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
pub mod prelude {
pub use cb_common::{
commit,
commit::request::{SignRequest, SignedProxyDelegation},
commit::request::{
SignConsensusRequest, SignedProxyDelegation, SignedProxyDelegationBls,
SignedProxyDelegationEcdsa,
},
config::{
load_builder_module_config, load_commit_module_config, load_pbs_config,
load_pbs_custom_config, StartCommitModuleConfig,
},
pbs::{BuilderEvent, BuilderEventClient, OnBuilderApiEvent},
signer::{EcdsaPublicKey, EcdsaSignature},
utils::{
initialize_pbs_tracing_log, initialize_tracing_log, utcnow_ms, utcnow_ns, utcnow_sec,
utcnow_us,
Expand Down
17 changes: 9 additions & 8 deletions config.example.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The main configuration file for the Commit-Boost sidecar.
# The main configuration file for the Commit-Boost sidecar.
# Some fields are optional and can be omitted, in which case the default value, if present, will be used.

# Chain spec id. Supported values: Mainnet, Holesky, Helder
Expand All @@ -18,7 +18,7 @@ port = 18550
# Whether to forward `status` calls to relays or skip and return 200
# OPTIONAL, DEFAULT: true
relay_check = true
# Timeout in milliseconds for the `get_header` call to relays. Note that the CL has also a timeout (e.g. 1 second) so
# Timeout in milliseconds for the `get_header` call to relays. Note that the CL has also a timeout (e.g. 1 second) so
# this should be lower than that, leaving some margin for overhead
# OPTIONAL, DEFAULT: 950
timeout_get_header_ms = 950
Expand All @@ -34,10 +34,11 @@ skip_sigverify = false
# Minimum bid in ETH that will be accepted from `get_header`
# OPTIONAL, DEFAULT: 0.0
min_bid_eth = 0.0
# How late in milliseconds in the slot is "late". This impacts the `get_header` requests, by shortening timeouts for `get_header` calls to
# List of URLs of relay monitors to send registrations to
# OPTIONAL
relay_monitors = []
# How late in milliseconds in the slot is "late". This impacts the `get_header` requests, by shortening timeouts for `get_header` calls to
# How late in milliseconds in the slot is "late". This impacts the `get_header` requests, by shortening timeouts for `get_header` calls to
# relays and make sure a header is returned within this deadline. If the request from the CL comes later in the slot, then fetching headers is skipped
# to force local building and miniminzing the risk of missed slots. See also the timing games section below
# OPTIONAL, DEFAULT: 2000
Expand All @@ -55,12 +56,12 @@ url = "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb
headers = { X-MyCustomHeader = "MyCustomValue" }
# Whether to enable timing games, as tuned by `target_first_request_ms` and `frequency_get_header_ms`.
# These values should be carefully chosen for each relay, as each relay has different latency and timing games setups.
# They should only be used by advanced users, and if mis-configured can result in unforeseen effects, e.g. fetching a lower header value,
# They should only be used by advanced users, and if mis-configured can result in unforeseen effects, e.g. fetching a lower header value,
# or getting a temporary IP ban.
#
#
# EXAMPLES
# Assuming: timeout_get_header_ms = 950, frequency_get_header_ms = 300, target_first_request_ms = 200, late_in_slot_time_ms = 2000
#
#
# 1) CL request comes at 100ms in the slot (max timeout 1050ms in the slot), then:
# - sleep for 100ms
# - send request at 200ms with 850ms timeout
Expand Down Expand Up @@ -112,13 +113,13 @@ id = "DA_COMMIT"
type = "commit"
# Docker image of the module
docker_image = "test_da_commit"
# Additional config needed by the business logic of the module should also be set here.
# Additional config needed by the business logic of the module should also be set here.
# See also `examples/da_commit/src/main.rs` for more information
sleep_secs = 5

# Configuration for how metrics should be collected and scraped
[metrics]
# Path to a `prometheus.yml` file to use in Prometheus. If using a custom config file, be sure to add a
# Path to a `prometheus.yml` file to use in Prometheus. If using a custom config file, be sure to add a
# file discovery section as follows:
# ```yml
# file_sd_configs:
Expand Down
3 changes: 3 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ blst.workspace = true
tree_hash.workspace = true
tree_hash_derive.workspace = true
eth2_keystore.workspace = true
elliptic-curve.workspace = true
generic-array.workspace = true
k256.workspace = true

# misc
thiserror.workspace = true
Expand Down
97 changes: 85 additions & 12 deletions crates/common/src/commit/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ use serde::{Deserialize, Serialize};
use super::{
constants::{GENERATE_PROXY_KEY_PATH, GET_PUBKEYS_PATH, REQUEST_SIGNATURE_PATH},
error::SignerClientError,
request::{GenerateProxyRequest, SignRequest, SignedProxyDelegation},
request::{
EncryptionScheme, GenerateProxyRequest, SignConsensusRequest, SignProxyBlsRequest,
SignProxyEcdsaRequest, SignProxyRequest, SignRequest, SignedProxyDelegation,
SignedProxyDelegationBls, SignedProxyDelegationEcdsa,
},
};
use crate::{
signer::{schemes::ecdsa::EcdsaSignature, GenericPubkey},
DEFAULT_REQUEST_TIMEOUT,
};
use crate::DEFAULT_REQUEST_TIMEOUT;

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct GetPubkeysResponse {
pub consensus: Vec<BlsPublicKey>,
pub proxy: Vec<BlsPublicKey>,
pub proxy: Vec<GenericPubkey>,
}

/// Client used by commit modules to request signatures via the Signer API
Expand Down Expand Up @@ -45,7 +52,8 @@ impl SignerClient {
}

/// Request a list of validator pubkeys for which signatures can be
/// requested. TODO: add more docs on how proxy keys work
/// requested.
// TODO: add more docs on how proxy keys work
pub async fn get_pubkeys(&self) -> Result<GetPubkeysResponse, SignerClientError> {
let url = format!("{}{}", self.url, GET_PUBKEYS_PATH);
let res = self.client.get(&url).send().await?;
Expand All @@ -66,10 +74,7 @@ impl SignerClient {
}

/// Send a signature request
pub async fn request_signature(
&self,
request: &SignRequest,
) -> Result<BlsSignature, SignerClientError> {
async fn request_signature(&self, request: &SignRequest) -> Result<Vec<u8>, SignerClientError> {
let url = format!("{}{}", self.url, REQUEST_SIGNATURE_PATH);
let res = self.client.post(&url).json(&request).send().await?;

Expand All @@ -83,17 +88,55 @@ impl SignerClient {
});
}

let signature: BlsSignature = serde_json::from_slice(&response_bytes)?;
let signature: Vec<u8> = serde_json::from_slice(&response_bytes)?;
David-Petrov marked this conversation as resolved.
Show resolved Hide resolved

Ok(signature)
}

pub async fn request_consensus_signature(
David-Petrov marked this conversation as resolved.
Show resolved Hide resolved
&self,
request: SignConsensusRequest,
) -> Result<BlsSignature, SignerClientError> {
let request = SignRequest::Consensus(request);
let raw_signature = self.request_signature(&request).await?;

let signature = BlsSignature::from_slice(&raw_signature);
David-Petrov marked this conversation as resolved.
Show resolved Hide resolved

Ok(signature)
}

async fn request_proxy_signature(
&self,
request: SignProxyRequest,
) -> Result<Vec<u8>, SignerClientError> {
let request = SignRequest::Proxy(request);
self.request_signature(&request).await
}

pub async fn request_proxy_ecdsa_signature(
&self,
request: SignProxyEcdsaRequest,
) -> Result<EcdsaSignature, SignerClientError> {
let raw_signature = self.request_proxy_signature(request.into()).await?;
let signature = EcdsaSignature::try_from(raw_signature.as_ref())
.expect("requested signature should be ECDSA");
David-Petrov marked this conversation as resolved.
Show resolved Hide resolved
Ok(signature)
}

pub async fn request_proxy_bls_signature(
&self,
request: SignProxyBlsRequest,
) -> Result<BlsSignature, SignerClientError> {
let raw_signature = self.request_proxy_signature(request.into()).await?;
let signature = BlsSignature::from_slice(&raw_signature);
Ok(signature)
}

pub async fn generate_proxy_key(
async fn generate_proxy_key(
&self,
pubkey: BlsPublicKey,
request: &GenerateProxyRequest,
) -> Result<SignedProxyDelegation, SignerClientError> {
let url = format!("{}{}", self.url, GENERATE_PROXY_KEY_PATH);
let request = GenerateProxyRequest::new(pubkey);
let res = self.client.post(&url).json(&request).send().await?;

let status = res.status();
Expand All @@ -110,4 +153,34 @@ impl SignerClient {

Ok(signed_proxy_delegation)
}

pub async fn generate_bls_proxy_key(
&self,
consensus_pubkey: BlsPublicKey,
) -> Result<SignedProxyDelegationBls, SignerClientError> {
let request = GenerateProxyRequest::new(consensus_pubkey, EncryptionScheme::Bls);

let bls_signed_proxy_delegation = self
.generate_proxy_key(&request)
.await?
.try_into()
.expect("generated proxy delegation should be BLS");

Ok(bls_signed_proxy_delegation)
}

pub async fn generate_ecdsa_proxy_key(
&self,
consensus_pubkey: BlsPublicKey,
) -> Result<SignedProxyDelegationEcdsa, SignerClientError> {
let request = GenerateProxyRequest::new(consensus_pubkey, EncryptionScheme::Ecdsa);

let ecdsa_signed_proxy_delegation = self
.generate_proxy_key(&request)
.await?
.try_into()
.expect("generated proxy delegation should be BLS");

Ok(ecdsa_signed_proxy_delegation)
}
}
Loading
Loading