-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathclient.rs
154 lines (126 loc) · 4.96 KB
/
client.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use std::sync::Arc;
use alloy::rpc::types::beacon::BlsSignature;
use eyre::WrapErr;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde::Deserialize;
use url::Url;
use super::{
constants::{GENERATE_PROXY_KEY_PATH, GET_PUBKEYS_PATH, REQUEST_SIGNATURE_PATH},
error::SignerClientError,
request::{
EncryptionScheme, GenerateProxyRequest, GetPubkeysResponse, PublicKey,
SignConsensusRequest, SignProxyRequest, SignRequest, SignedProxyDelegation,
},
};
use crate::{
signer::{BlsPublicKey, EcdsaPublicKey, EcdsaSignature},
DEFAULT_REQUEST_TIMEOUT,
};
/// Client used by commit modules to request signatures via the Signer API
#[derive(Debug, Clone)]
pub struct SignerClient {
/// Url endpoint of the Signer Module
url: Arc<Url>,
client: reqwest::Client,
}
impl SignerClient {
/// Create a new SignerClient
pub fn new(signer_server_url: Url, jwt: &str) -> eyre::Result<Self> {
let mut headers = HeaderMap::new();
let mut auth_value =
HeaderValue::from_str(&format!("Bearer {}", jwt)).wrap_err("invalid jwt")?;
auth_value.set_sensitive(true);
headers.insert(AUTHORIZATION, auth_value);
let client = reqwest::Client::builder()
.timeout(DEFAULT_REQUEST_TIMEOUT)
.default_headers(headers)
.build()?;
Ok(Self { url: signer_server_url.into(), client })
}
/// Request a list of validator pubkeys for which signatures can be
/// requested.
// TODO: add more docs on how proxy keys work
pub async fn get_pubkeys(&self) -> Result<GetPubkeysResponse, SignerClientError> {
let url = self.url.join(GET_PUBKEYS_PATH)?;
let res = self.client.get(url).send().await?;
if !res.status().is_success() {
return Err(SignerClientError::FailedRequest {
status: res.status().as_u16(),
error_msg: String::from_utf8_lossy(&res.bytes().await?).into_owned(),
});
}
Ok(serde_json::from_slice(&res.bytes().await?)?)
}
/// Send a signature request
async fn request_signature<T>(&self, request: &SignRequest) -> Result<T, SignerClientError>
where
T: for<'de> Deserialize<'de>,
{
let url = self.url.join(REQUEST_SIGNATURE_PATH)?;
let res = self.client.post(url).json(&request).send().await?;
let status = res.status();
let response_bytes = res.bytes().await?;
if !status.is_success() {
return Err(SignerClientError::FailedRequest {
status: status.as_u16(),
error_msg: String::from_utf8_lossy(&response_bytes).into_owned(),
});
}
let signature = serde_json::from_slice(&response_bytes)?;
Ok(signature)
}
pub async fn request_consensus_signature(
&self,
request: SignConsensusRequest,
) -> Result<BlsSignature, SignerClientError> {
self.request_signature(&request.into()).await
}
pub async fn request_proxy_signature_ecdsa(
&self,
request: SignProxyRequest<EcdsaPublicKey>,
) -> Result<EcdsaSignature, SignerClientError> {
self.request_signature(&request.into()).await
}
pub async fn request_proxy_signature_bls(
&self,
request: SignProxyRequest<BlsPublicKey>,
) -> Result<BlsSignature, SignerClientError> {
self.request_signature(&request.into()).await
}
async fn generate_proxy_key<T>(
&self,
request: &GenerateProxyRequest,
) -> Result<SignedProxyDelegation<T>, SignerClientError>
where
T: PublicKey + for<'de> Deserialize<'de>,
{
let url = self.url.join(GENERATE_PROXY_KEY_PATH)?;
let res = self.client.post(url).json(&request).send().await?;
let status = res.status();
let response_bytes = res.bytes().await?;
if !status.is_success() {
return Err(SignerClientError::FailedRequest {
status: status.as_u16(),
error_msg: String::from_utf8_lossy(&response_bytes).into_owned(),
});
}
let signed_proxy_delegation = serde_json::from_slice(&response_bytes)?;
Ok(signed_proxy_delegation)
}
pub async fn generate_proxy_key_bls(
&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_proxy_key_ecdsa(
&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)
}
}