Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 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
Aug 9, 2024
a7c76df
feat(signer)!: add support for ECDSA proxy keys
Aug 13, 2024
5530567
Merge branch 'main' into feat/ecdsa-proxy-keys
Aug 13, 2024
a5450b6
chore(clippy): infallible instead of fallible conversions
Aug 14, 2024
a9ff828
chore(signer): resolve TODOs
Aug 14, 2024
4e96742
refactor(signer)!: move around
Aug 14, 2024
4b283e2
chore(signer)!: rename associated type and type alias
Aug 14, 2024
9d70712
choer(signer): rename client `Signature` type
Aug 14, 2024
287da33
refactor(signer)!: remove default type parameter in `Signer`
Aug 14, 2024
431f189
chore(clippy): remove unnecessary nested reference
Aug 14, 2024
8041e0f
chore: remove commented code
Aug 15, 2024
23437a2
refactor(signer/ecdsa): derive unnecessary trait impls
Aug 15, 2024
9078e25
style: remove unnecessary constraint duplication
Aug 15, 2024
377aa78
refactor(signer)!: rename module `signers` to `signer` and constrain …
Aug 15, 2024
b83841e
refactor(loader): unify `ConsensusSigner` type alias usage
Aug 15, 2024
7e1bf44
chore!: remove forgotten debug
Aug 20, 2024
eba97b0
refactor(signer)!: [WIP] simplify proxy keys
Aug 21, 2024
ad6d373
refactor(signer)!: separate BLS and ECDSA types in client SDK
Aug 21, 2024
fede09c
chore(signer)!: reformat & clean up
Aug 21, 2024
68fce43
refactor(signer/manager): remove enum `GenericProxySigner`
Aug 22, 2024
a7d53a1
refactor(signer)!: make `SignedProxyDelegation` generic in the public…
Aug 22, 2024
780299e
refactor(signer/request): make `SignProxyRequest` generic in the publ…
Aug 23, 2024
7ddcd3a
refactor(signer/manager)!: split generic `get_delegation` into two se…
Aug 23, 2024
b8f228b
refactor(signer/client): remove unnecessary `Vec<u8>` deserialization
Aug 27, 2024
635f620
feat(signer): add tests for ECDSA proxies
Aug 27, 2024
dd864ec
refactor(signer/api)!: proper struct serde
Aug 28, 2024
b3286d5
refactor(signer): remove unnecessary module
Aug 28, 2024
7dedbcf
refactor(signer)!: remove `GenericPubkey`
Aug 28, 2024
f075db9
refactor(signer/request): move `GetPubkeysResponse`
Aug 28, 2024
9c4f412
refactor(signer): reduce code duplication around `SignRequest`
Aug 28, 2024
4e652d9
style/refactor(signer): reduce method size
Aug 28, 2024
9907059
refactor(deps)!: revert version updates
Aug 28, 2024
0ff2091
chore(deps)!: remove unused deps
Aug 28, 2024
dea0b0c
chore(signer): add TODO for `BlsPublicKey` wrapper
Aug 29, 2024
5fc50ae
refactor(signer)!: re-export request types properly from prelude
Aug 29, 2024
0bcd2d7
feat(signer/api): update api docs
Aug 29, 2024
f103c8d
refactor(signer/client): re-export bls types and rename methods for c…
Aug 29, 2024
da550d3
chore(docs): update md files in book
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"
Comment thread
David-Petrov marked this conversation as resolved.
Outdated
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
99 changes: 85 additions & 14 deletions crates/common/src/commit/client.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
use std::sync::Arc;

use alloy::rpc::types::beacon::{BlsPublicKey, BlsSignature};
use alloy::rpc::types::beacon::BlsSignature;
use eyre::WrapErr;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
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, PublicKey, SignConsensusRequest,
SignProxyBlsRequest, SignProxyEcdsaRequest, SignProxyRequest, SignRequest,
SignedProxyDelegation,
},
};
use crate::{
signer::{
schemes::{bls::BlsPublicKey, ecdsa::EcdsaSignature},
EcdsaPublicKey, 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 +55,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 +77,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 +91,58 @@ impl SignerClient {
});
}

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

Ok(signature)
}

pub async fn request_consensus_signature(
Comment thread
David-Petrov marked this conversation as 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);
Comment thread
David-Petrov marked this conversation as resolved.
Outdated

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");
Comment thread
David-Petrov marked this conversation as resolved.
Outdated
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<T>(
&self,
pubkey: BlsPublicKey,
) -> Result<SignedProxyDelegation, SignerClientError> {
request: &GenerateProxyRequest,
) -> Result<SignedProxyDelegation<T>, SignerClientError>
where
T: PublicKey + for<'de> Deserialize<'de>,
{
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 +159,26 @@ impl SignerClient {

Ok(signed_proxy_delegation)
}

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

let bls_signed_proxy_delegation = self.generate_proxy_key(&request).await?;

Ok(bls_signed_proxy_delegation)
}

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

let ecdsa_signed_proxy_delegation = self.generate_proxy_key(&request).await?;

Ok(ecdsa_signed_proxy_delegation)
}
}
Loading