mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-02 16:21:42 +00:00
[Remote signer] Add signer consumer lib (#1763)
Adds a library `common/remote_signer_consumer`
This commit is contained in:
@@ -6,10 +6,14 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.3"
|
||||
client = { path = "../../remote_signer/client", package = "remote_signer_client" }
|
||||
environment = { path = "../../lighthouse/environment" }
|
||||
hex = "0.4.2"
|
||||
httpmock = "0.5.1"
|
||||
remote_signer_client = { path = "../../remote_signer/client" }
|
||||
remote_signer_consumer = { path = "../../common/remote_signer_consumer" }
|
||||
reqwest = { version = "0.10.8", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
serde_json = "1.0.58"
|
||||
tempdir = "0.3.7"
|
||||
tokio = { version = "0.2.22", features = ["time"] }
|
||||
types = { path = "../../consensus/types" }
|
||||
|
||||
138
testing/remote_signer_test/src/api_test_signer.rs
Normal file
138
testing/remote_signer_test/src/api_test_signer.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
use crate::*;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use environment::{Environment, EnvironmentBuilder};
|
||||
pub use local_signer_test_data::*;
|
||||
use remote_signer_client::Client;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use tempdir::TempDir;
|
||||
use types::EthSpec;
|
||||
|
||||
pub struct ApiTestSigner<E: EthSpec> {
|
||||
pub address: String,
|
||||
environment: Environment<E>,
|
||||
}
|
||||
|
||||
pub struct ApiTestResponse {
|
||||
pub status: u16,
|
||||
pub json: Value,
|
||||
}
|
||||
|
||||
impl ApiTestSigner<E> {
|
||||
pub fn new(arg_vec: Vec<&str>) -> Self {
|
||||
let matches = set_matches(arg_vec);
|
||||
let mut environment = get_environment(false);
|
||||
let runtime_context = environment.core_context();
|
||||
|
||||
let client = environment
|
||||
.runtime()
|
||||
.block_on(Client::new(runtime_context, &matches))
|
||||
.map_err(|e| format!("Failed to init Rest API: {}", e))
|
||||
.unwrap();
|
||||
|
||||
let address = get_address(&client);
|
||||
|
||||
Self {
|
||||
address,
|
||||
environment,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown(mut self) {
|
||||
self.environment.fire_signal()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_matches(arg_vec: Vec<&str>) -> ArgMatches<'static> {
|
||||
let matches = App::new("BLS_Remote_Signer")
|
||||
.arg(
|
||||
Arg::with_name("storage-raw-dir")
|
||||
.long("storage-raw-dir")
|
||||
.value_name("DIR"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("port")
|
||||
.long("port")
|
||||
.value_name("PORT")
|
||||
.default_value("9000")
|
||||
.takes_value(true),
|
||||
);
|
||||
|
||||
matches.get_matches_from(arg_vec)
|
||||
}
|
||||
|
||||
pub fn get_environment(is_log_active: bool) -> Environment<E> {
|
||||
let environment_builder = EnvironmentBuilder::mainnet();
|
||||
|
||||
let builder = if is_log_active {
|
||||
environment_builder.async_logger("info", None).unwrap()
|
||||
} else {
|
||||
environment_builder.null_logger().unwrap()
|
||||
};
|
||||
|
||||
builder
|
||||
.multi_threaded_tokio_runtime()
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn set_up_api_test_signer_raw_dir() -> (ApiTestSigner<E>, TempDir) {
|
||||
let tmp_dir = TempDir::new("bls-remote-signer-test").unwrap();
|
||||
let arg_vec = vec![
|
||||
"this_test",
|
||||
"--port",
|
||||
"0",
|
||||
"--storage-raw-dir",
|
||||
tmp_dir.path().to_str().unwrap(),
|
||||
];
|
||||
let test_signer = ApiTestSigner::new(arg_vec);
|
||||
|
||||
(test_signer, tmp_dir)
|
||||
}
|
||||
|
||||
pub fn set_up_api_test_signer_to_sign_message() -> (ApiTestSigner<E>, TempDir) {
|
||||
let (test_signer, tmp_dir) = set_up_api_test_signer_raw_dir();
|
||||
add_sub_dirs(&tmp_dir);
|
||||
add_key_files(&tmp_dir);
|
||||
add_non_key_files(&tmp_dir);
|
||||
add_mismatched_key_file(&tmp_dir);
|
||||
add_invalid_secret_key_file(&tmp_dir);
|
||||
|
||||
(test_signer, tmp_dir)
|
||||
}
|
||||
|
||||
pub fn http_get(url: &str) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::get(url).unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn http_post(url: &str, hashmap: HashMap<&str, &str>) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::Client::new()
|
||||
.post(url)
|
||||
.json(&hashmap)
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn http_post_custom_body(url: &str, body: &str) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::Client::new()
|
||||
.post(url)
|
||||
.body(body.to_string())
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
148
testing/remote_signer_test/src/consumer.rs
Normal file
148
testing/remote_signer_test/src/consumer.rs
Normal file
@@ -0,0 +1,148 @@
|
||||
use crate::*;
|
||||
use remote_signer_client::api_response::SignatureApiResponse;
|
||||
use remote_signer_consumer::{Error, RemoteSignerHttpConsumer, RemoteSignerObject, Url};
|
||||
use reqwest::ClientBuilder;
|
||||
use serde::Serialize;
|
||||
use tokio::runtime::Builder;
|
||||
use tokio::time::Duration;
|
||||
use types::{AttestationData, BeaconBlock, Epoch, EthSpec, Fork, Hash256};
|
||||
|
||||
pub fn set_up_test_consumer(test_signer_address: &str) -> RemoteSignerHttpConsumer {
|
||||
set_up_test_consumer_with_timeout(test_signer_address, 12)
|
||||
}
|
||||
|
||||
pub fn set_up_test_consumer_with_timeout(
|
||||
test_signer_address: &str,
|
||||
timeout: u64,
|
||||
) -> RemoteSignerHttpConsumer {
|
||||
let url: Url = test_signer_address.parse().unwrap();
|
||||
let reqwest_client = ClientBuilder::new()
|
||||
.timeout(Duration::from_secs(timeout))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
RemoteSignerHttpConsumer::from_components(url, reqwest_client)
|
||||
}
|
||||
|
||||
pub fn do_sign_request<E: EthSpec, T: RemoteSignerObject>(
|
||||
test_client: &RemoteSignerHttpConsumer,
|
||||
test_input: RemoteSignerTestData<E, T>,
|
||||
) -> Result<String, Error> {
|
||||
let mut runtime = Builder::new()
|
||||
.basic_scheduler()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
runtime.block_on(test_client.sign(
|
||||
&test_input.public_key,
|
||||
test_input.bls_domain,
|
||||
test_input.data,
|
||||
test_input.fork,
|
||||
test_input.genesis_validators_root,
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BlockRequestBody<E: EthSpec> {
|
||||
bls_domain: String,
|
||||
data: BeaconBlock<E>,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_block_body(seed: u64) -> String {
|
||||
let block: BeaconBlock<E> = get_block(seed);
|
||||
let epoch = block.epoch();
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let block_request_body = BlockRequestBody {
|
||||
bls_domain: "beacon_proposer".to_string(),
|
||||
data: block,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&block_request_body).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AttestationRequestBody {
|
||||
bls_domain: String,
|
||||
data: AttestationData,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_attestation_body(seed: u64) -> String {
|
||||
let attestation = get_attestation::<E>(seed);
|
||||
let epoch = attestation.target.epoch;
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let attestation_request_body = AttestationRequestBody {
|
||||
bls_domain: "beacon_attester".to_string(),
|
||||
data: attestation,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&attestation_request_body).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RandaoRequestBody {
|
||||
bls_domain: String,
|
||||
data: Epoch,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_randao_body(seed: u64) -> String {
|
||||
let epoch = Epoch::new(seed);
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let randao_request_body = RandaoRequestBody {
|
||||
bls_domain: "randao".to_string(),
|
||||
data: epoch,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&randao_request_body).unwrap()
|
||||
}
|
||||
|
||||
pub fn assert_sign_ok(resp: ApiTestResponse, expected_signature: &str) {
|
||||
assert_eq!(resp.status, 200);
|
||||
assert_eq!(
|
||||
serde_json::from_value::<SignatureApiResponse>(resp.json)
|
||||
.unwrap()
|
||||
.signature,
|
||||
expected_signature
|
||||
);
|
||||
}
|
||||
|
||||
pub fn assert_sign_error(resp: ApiTestResponse, http_status: u16, error_msg: &str) {
|
||||
assert_eq!(resp.status, http_status);
|
||||
assert_eq!(resp.json["error"].as_str().unwrap(), error_msg);
|
||||
}
|
||||
@@ -1,320 +1,18 @@
|
||||
mod api_test_signer;
|
||||
mod constants;
|
||||
mod objects;
|
||||
mod consumer;
|
||||
mod local_signer_test_data;
|
||||
mod mock;
|
||||
mod remote_signer_test_data;
|
||||
mod utils;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use client::api_response::SignatureApiResponse;
|
||||
use client::Client;
|
||||
pub use api_test_signer::*;
|
||||
pub use constants::*;
|
||||
use environment::{Environment, EnvironmentBuilder};
|
||||
pub use objects::*;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::{create_dir, File};
|
||||
use std::io::Write;
|
||||
use std::net::IpAddr::{V4, V6};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::Path;
|
||||
use tempdir::TempDir;
|
||||
use types::{AttestationData, BeaconBlock, Epoch, EthSpec, Fork, Hash256, MainnetEthSpec};
|
||||
pub use consumer::*;
|
||||
pub use local_signer_test_data::*;
|
||||
pub use mock::*;
|
||||
pub use remote_signer_test_data::*;
|
||||
use types::MainnetEthSpec;
|
||||
pub use utils::*;
|
||||
|
||||
pub type E = MainnetEthSpec;
|
||||
|
||||
pub struct ApiTestSigner<E: EthSpec> {
|
||||
pub address: String,
|
||||
environment: Environment<E>,
|
||||
}
|
||||
|
||||
pub struct ApiTestResponse {
|
||||
pub status: u16,
|
||||
pub json: Value,
|
||||
}
|
||||
|
||||
impl ApiTestSigner<MainnetEthSpec> {
|
||||
pub fn new(arg_vec: Vec<&str>) -> Self {
|
||||
let matches = set_matches(arg_vec);
|
||||
let mut environment = get_environment(false);
|
||||
let runtime_context = environment.core_context();
|
||||
|
||||
let client = environment
|
||||
.runtime()
|
||||
.block_on(Client::new(runtime_context, &matches))
|
||||
.map_err(|e| format!("Failed to init Rest API: {}", e))
|
||||
.unwrap();
|
||||
|
||||
let address = get_address(&client);
|
||||
|
||||
Self {
|
||||
address,
|
||||
environment,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown(mut self) {
|
||||
self.environment.fire_signal()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_matches(arg_vec: Vec<&str>) -> ArgMatches<'static> {
|
||||
let matches = App::new("BLS_Remote_Signer")
|
||||
.arg(
|
||||
Arg::with_name("storage-raw-dir")
|
||||
.long("storage-raw-dir")
|
||||
.value_name("DIR"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("port")
|
||||
.long("port")
|
||||
.value_name("PORT")
|
||||
.default_value("9000")
|
||||
.takes_value(true),
|
||||
);
|
||||
|
||||
matches.get_matches_from(arg_vec)
|
||||
}
|
||||
|
||||
pub fn get_environment(is_log_active: bool) -> Environment<E> {
|
||||
let environment_builder = EnvironmentBuilder::mainnet();
|
||||
|
||||
let builder = if is_log_active {
|
||||
environment_builder.async_logger("info", None).unwrap()
|
||||
} else {
|
||||
environment_builder.null_logger().unwrap()
|
||||
};
|
||||
|
||||
builder
|
||||
.multi_threaded_tokio_runtime()
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn set_up_api_test_signer_raw_dir() -> (ApiTestSigner<E>, TempDir) {
|
||||
let tmp_dir = TempDir::new("bls-remote-signer-test").unwrap();
|
||||
let arg_vec = vec![
|
||||
"this_test",
|
||||
"--port",
|
||||
"0",
|
||||
"--storage-raw-dir",
|
||||
tmp_dir.path().to_str().unwrap(),
|
||||
];
|
||||
let test_signer = ApiTestSigner::new(arg_vec);
|
||||
|
||||
(test_signer, tmp_dir)
|
||||
}
|
||||
|
||||
pub fn set_up_api_test_signer_to_sign_message() -> (ApiTestSigner<E>, TempDir) {
|
||||
let (test_signer, tmp_dir) = set_up_api_test_signer_raw_dir();
|
||||
add_sub_dirs(&tmp_dir);
|
||||
add_key_files(&tmp_dir);
|
||||
add_non_key_files(&tmp_dir);
|
||||
add_mismatched_key_file(&tmp_dir);
|
||||
add_invalid_secret_key_file(&tmp_dir);
|
||||
|
||||
(test_signer, tmp_dir)
|
||||
}
|
||||
|
||||
pub fn get_address(client: &Client) -> String {
|
||||
let listening_address = client.get_listening_address();
|
||||
let ip = match listening_address.ip() {
|
||||
V4(ip) => ip.to_string(),
|
||||
V6(ip) => ip.to_string(),
|
||||
};
|
||||
|
||||
format!("http://{}:{}", ip, listening_address.port())
|
||||
}
|
||||
|
||||
pub fn set_permissions(path: &Path, perm_octal: u32) {
|
||||
let metadata = fs::metadata(path).unwrap();
|
||||
let mut permissions = metadata.permissions();
|
||||
permissions.set_mode(perm_octal);
|
||||
fs::set_permissions(path, permissions).unwrap();
|
||||
}
|
||||
|
||||
pub fn add_key_files(tmp_dir: &TempDir) {
|
||||
let pairs = vec![
|
||||
(PUBLIC_KEY_1, SECRET_KEY_1),
|
||||
(PUBLIC_KEY_2, SECRET_KEY_2),
|
||||
(PUBLIC_KEY_3, SECRET_KEY_3),
|
||||
];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_mismatched_key_file(tmp_dir: &TempDir) {
|
||||
let pairs = vec![(MISMATCHED_PUBLIC_KEY, SECRET_KEY_1)];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_invalid_secret_key_file(tmp_dir: &TempDir) {
|
||||
let pairs = vec![(PUBLIC_KEY_FOR_INVALID_SECRET_KEY, INVALID_SECRET_KEY)];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_non_key_files(tmp_dir: &TempDir) {
|
||||
let pairs = vec![
|
||||
(SILLY_FILE_NAME_1, SILLY_CONTENT_1),
|
||||
(SILLY_FILE_NAME_2, SILLY_CONTENT_2),
|
||||
(SILLY_FILE_NAME_3, SILLY_CONTENT_3),
|
||||
];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
fn add_files(tmp_dir: &TempDir, pairs: Vec<(&str, &str)>) {
|
||||
for pair in pairs {
|
||||
let file_path = tmp_dir.path().join(pair.0);
|
||||
let mut tmp_file = File::create(file_path).unwrap();
|
||||
writeln!(tmp_file, "{}", pair.1).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_sub_dirs(tmp_dir: &TempDir) {
|
||||
let random_sub_dir_path = tmp_dir.path().join("random_sub_dir_name");
|
||||
create_dir(random_sub_dir_path).unwrap();
|
||||
|
||||
let another_sub_dir_path = tmp_dir.path().join(SUB_DIR_NAME);
|
||||
create_dir(another_sub_dir_path).unwrap();
|
||||
}
|
||||
|
||||
pub fn http_get(url: &str) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::get(url).unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn http_post(url: &str, hashmap: HashMap<&str, &str>) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::Client::new()
|
||||
.post(url)
|
||||
.json(&hashmap)
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn http_post_custom_body(url: &str, body: &str) -> ApiTestResponse {
|
||||
let response = reqwest::blocking::Client::new()
|
||||
.post(url)
|
||||
.body(body.to_string())
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
ApiTestResponse {
|
||||
status: response.status().as_u16(),
|
||||
json: serde_json::from_str(&response.text().unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BlockRequestBody<E: EthSpec> {
|
||||
bls_domain: String,
|
||||
data: BeaconBlock<E>,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_block_body(seed: u64) -> String {
|
||||
let block: BeaconBlock<E> = get_block(seed);
|
||||
let epoch = block.epoch();
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let block_request_body = BlockRequestBody {
|
||||
bls_domain: "beacon_proposer".to_string(),
|
||||
data: block,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&block_request_body).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AttestationRequestBody {
|
||||
bls_domain: String,
|
||||
data: AttestationData,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_attestation_body(seed: u64) -> String {
|
||||
let attestation = get_attestation::<E>(seed);
|
||||
let epoch = attestation.target.epoch;
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let attestation_request_body = AttestationRequestBody {
|
||||
bls_domain: "beacon_attester".to_string(),
|
||||
data: attestation,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&attestation_request_body).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct RandaoRequestBody {
|
||||
bls_domain: String,
|
||||
data: Epoch,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
}
|
||||
|
||||
pub fn get_test_randao_body(seed: u64) -> String {
|
||||
let epoch = Epoch::new(seed);
|
||||
|
||||
let fork = Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
};
|
||||
|
||||
let genesis_validators_root = Hash256::from_low_u64_be(seed);
|
||||
|
||||
let randao_request_body = RandaoRequestBody {
|
||||
bls_domain: "randao".to_string(),
|
||||
data: epoch,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
};
|
||||
|
||||
serde_json::to_string(&randao_request_body).unwrap()
|
||||
}
|
||||
|
||||
pub fn assert_sign_ok(resp: ApiTestResponse, expected_signature: &str) {
|
||||
assert_eq!(resp.status, 200);
|
||||
assert_eq!(
|
||||
serde_json::from_value::<SignatureApiResponse>(resp.json)
|
||||
.unwrap()
|
||||
.signature,
|
||||
expected_signature
|
||||
);
|
||||
}
|
||||
|
||||
pub fn assert_sign_error(resp: ApiTestResponse, http_status: u16, error_msg: &str) {
|
||||
assert_eq!(resp.status, http_status);
|
||||
assert_eq!(resp.json["error"].as_str().unwrap(), error_msg);
|
||||
}
|
||||
|
||||
103
testing/remote_signer_test/src/local_signer_test_data.rs
Normal file
103
testing/remote_signer_test/src/local_signer_test_data.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use crate::*;
|
||||
use hex::decode;
|
||||
use remote_signer_consumer::RemoteSignerObject;
|
||||
use std::mem;
|
||||
use types::{
|
||||
AttestationData, BeaconBlock, ChainSpec, Domain, Epoch, EthSpec, Fork, Hash256, SecretKey,
|
||||
SignedRoot,
|
||||
};
|
||||
|
||||
pub struct LocalSignerTestData<T: RemoteSignerObject> {
|
||||
secret_key: SecretKey,
|
||||
spec: ChainSpec,
|
||||
fork: Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
obj: T,
|
||||
}
|
||||
|
||||
impl<T: RemoteSignerObject> LocalSignerTestData<T> {
|
||||
pub fn new(obj: T) -> Self {
|
||||
let epoch = obj.get_epoch();
|
||||
|
||||
Self {
|
||||
secret_key: SecretKey::deserialize(&decode(SECRET_KEY_1).unwrap()).unwrap(),
|
||||
spec: E::default_spec(),
|
||||
fork: Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
},
|
||||
genesis_validators_root: Hash256::from_low_u64_be(0xc137),
|
||||
obj,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalSignerTestData<BeaconBlock<E>> {
|
||||
pub fn sign(&self) -> String {
|
||||
let signed_block = self.obj.clone().sign(
|
||||
&self.secret_key,
|
||||
&self.fork,
|
||||
self.genesis_validators_root,
|
||||
&self.spec,
|
||||
);
|
||||
|
||||
signed_block.signature.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalSignerTestData<AttestationData> {
|
||||
pub fn sign(&self) -> String {
|
||||
let domain = self.spec.get_domain(
|
||||
self.obj.target.epoch,
|
||||
Domain::BeaconAttester,
|
||||
&self.fork,
|
||||
self.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = self.obj.signing_root(domain);
|
||||
let signature = &self.secret_key.sign(message);
|
||||
|
||||
signature.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalSignerTestData<Epoch> {
|
||||
pub fn sign(&self) -> String {
|
||||
let domain = self.spec.get_domain(
|
||||
self.obj,
|
||||
Domain::Randao,
|
||||
&self.fork,
|
||||
self.genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = self.obj.signing_root(domain);
|
||||
let signature = &self.secret_key.sign(message);
|
||||
|
||||
signature.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_input_local_signer_block(seed: u64) -> LocalSignerTestData<BeaconBlock<E>> {
|
||||
let block: BeaconBlock<E>;
|
||||
|
||||
unsafe {
|
||||
block = mem::transmute(get_block::<E>(seed));
|
||||
}
|
||||
|
||||
LocalSignerTestData::new(block)
|
||||
}
|
||||
|
||||
pub fn get_input_local_signer_attestation(seed: u64) -> LocalSignerTestData<AttestationData> {
|
||||
let attestation: AttestationData;
|
||||
|
||||
unsafe {
|
||||
attestation = mem::transmute(get_attestation::<E>(seed));
|
||||
}
|
||||
|
||||
LocalSignerTestData::new(attestation)
|
||||
}
|
||||
|
||||
pub fn get_input_local_signer_randao(seed: u64) -> LocalSignerTestData<Epoch> {
|
||||
LocalSignerTestData::new(Epoch::new(seed))
|
||||
}
|
||||
20
testing/remote_signer_test/src/mock.rs
Normal file
20
testing/remote_signer_test/src/mock.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use crate::*;
|
||||
use httpmock::{Method::POST, MockServer};
|
||||
use tokio::time::Duration;
|
||||
|
||||
pub fn set_up_mock_server(status: u16, body: &str) -> MockServer {
|
||||
set_up_mock_server_with_timeout(status, body, 0)
|
||||
}
|
||||
|
||||
pub fn set_up_mock_server_with_timeout(status: u16, body: &str, delay: u64) -> MockServer {
|
||||
let server = MockServer::start();
|
||||
|
||||
server.mock(|when, then| {
|
||||
when.method(POST).path(format!("/sign/{}", PUBLIC_KEY_1));
|
||||
then.status(status)
|
||||
.delay(Duration::from_secs(delay))
|
||||
.body(body);
|
||||
});
|
||||
|
||||
server
|
||||
}
|
||||
69
testing/remote_signer_test/src/remote_signer_test_data.rs
Normal file
69
testing/remote_signer_test/src/remote_signer_test_data.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use crate::*;
|
||||
use remote_signer_consumer::RemoteSignerObject;
|
||||
use std::marker::PhantomData;
|
||||
use types::{AttestationData, BeaconBlock, Domain, Epoch, EthSpec, Fork, Hash256};
|
||||
|
||||
pub struct RemoteSignerTestData<E: EthSpec, T: RemoteSignerObject> {
|
||||
pub public_key: String,
|
||||
pub bls_domain: Domain,
|
||||
pub data: T,
|
||||
pub fork: Fork,
|
||||
pub genesis_validators_root: Hash256,
|
||||
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec, T: RemoteSignerObject> RemoteSignerTestData<E, T> {
|
||||
pub fn new(public_key: &str, data: T, bls_domain: Domain) -> Self {
|
||||
let epoch = data.get_epoch();
|
||||
|
||||
Self {
|
||||
public_key: public_key.to_string(),
|
||||
bls_domain,
|
||||
data,
|
||||
fork: Fork {
|
||||
previous_version: [1; 4],
|
||||
current_version: [2; 4],
|
||||
epoch,
|
||||
},
|
||||
genesis_validators_root: Hash256::from_low_u64_be(0xc137),
|
||||
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_input_data_block(seed: u64) -> RemoteSignerTestData<E, BeaconBlock<E>> {
|
||||
let block = get_block::<E>(seed);
|
||||
RemoteSignerTestData::new(PUBLIC_KEY_1, block, Domain::BeaconProposer)
|
||||
}
|
||||
|
||||
pub fn get_input_data_attestation(seed: u64) -> RemoteSignerTestData<E, AttestationData> {
|
||||
let attestation = get_attestation::<E>(seed);
|
||||
RemoteSignerTestData::new(PUBLIC_KEY_1, attestation, Domain::BeaconAttester)
|
||||
}
|
||||
|
||||
pub fn get_input_data_randao(seed: u64) -> RemoteSignerTestData<E, Epoch> {
|
||||
let epoch = Epoch::new(seed);
|
||||
RemoteSignerTestData::new(PUBLIC_KEY_1, epoch, Domain::Randao)
|
||||
}
|
||||
|
||||
pub fn get_input_data_and_set_domain<E: EthSpec, T: RemoteSignerObject>(
|
||||
f: fn(u64) -> RemoteSignerTestData<E, T>,
|
||||
bls_domain: Domain,
|
||||
) -> RemoteSignerTestData<E, T> {
|
||||
let mut test_input = f(0xc137);
|
||||
test_input.bls_domain = bls_domain;
|
||||
|
||||
test_input
|
||||
}
|
||||
|
||||
pub fn get_input_data_and_set_public_key<E: EthSpec, T: RemoteSignerObject>(
|
||||
f: fn(u64) -> RemoteSignerTestData<E, T>,
|
||||
p: &str,
|
||||
) -> RemoteSignerTestData<E, T> {
|
||||
let mut test_input = f(0xc137);
|
||||
test_input.public_key = p.to_string();
|
||||
|
||||
test_input
|
||||
}
|
||||
@@ -1,3 +1,17 @@
|
||||
use crate::*;
|
||||
pub use constants::*;
|
||||
pub use consumer::*;
|
||||
pub use local_signer_test_data::*;
|
||||
pub use mock::*;
|
||||
use remote_signer_client::Client;
|
||||
pub use remote_signer_test_data::*;
|
||||
use std::fs;
|
||||
use std::fs::{create_dir, File};
|
||||
use std::io::Write;
|
||||
use std::net::IpAddr::{V4, V6};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::Path;
|
||||
use tempdir::TempDir;
|
||||
use types::{
|
||||
AggregateSignature, Attestation, AttestationData, AttesterSlashing, BeaconBlock,
|
||||
BeaconBlockHeader, BitList, Checkpoint, Deposit, DepositData, Epoch, EthSpec, FixedVector,
|
||||
@@ -5,6 +19,71 @@ use types::{
|
||||
SignedBeaconBlockHeader, SignedVoluntaryExit, Slot, Unsigned, VariableList, VoluntaryExit,
|
||||
};
|
||||
|
||||
pub fn get_address(client: &Client) -> String {
|
||||
let listening_address = client.get_listening_address();
|
||||
let ip = match listening_address.ip() {
|
||||
V4(ip) => ip.to_string(),
|
||||
V6(ip) => ip.to_string(),
|
||||
};
|
||||
|
||||
format!("http://{}:{}", ip, listening_address.port())
|
||||
}
|
||||
|
||||
pub fn set_permissions(path: &Path, perm_octal: u32) {
|
||||
let metadata = fs::metadata(path).unwrap();
|
||||
let mut permissions = metadata.permissions();
|
||||
permissions.set_mode(perm_octal);
|
||||
fs::set_permissions(path, permissions).unwrap();
|
||||
}
|
||||
|
||||
pub fn add_key_files(tmp_dir: &TempDir) {
|
||||
let pairs = vec![
|
||||
(PUBLIC_KEY_1, SECRET_KEY_1),
|
||||
(PUBLIC_KEY_2, SECRET_KEY_2),
|
||||
(PUBLIC_KEY_3, SECRET_KEY_3),
|
||||
];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_mismatched_key_file(tmp_dir: &TempDir) {
|
||||
let pairs = vec![(MISMATCHED_PUBLIC_KEY, SECRET_KEY_1)];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_invalid_secret_key_file(tmp_dir: &TempDir) {
|
||||
let pairs = vec![(PUBLIC_KEY_FOR_INVALID_SECRET_KEY, INVALID_SECRET_KEY)];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
pub fn add_non_key_files(tmp_dir: &TempDir) {
|
||||
let pairs = vec![
|
||||
(SILLY_FILE_NAME_1, SILLY_CONTENT_1),
|
||||
(SILLY_FILE_NAME_2, SILLY_CONTENT_2),
|
||||
(SILLY_FILE_NAME_3, SILLY_CONTENT_3),
|
||||
];
|
||||
|
||||
add_files(tmp_dir, pairs);
|
||||
}
|
||||
|
||||
fn add_files(tmp_dir: &TempDir, pairs: Vec<(&str, &str)>) {
|
||||
for pair in pairs {
|
||||
let file_path = tmp_dir.path().join(pair.0);
|
||||
let mut tmp_file = File::create(file_path).unwrap();
|
||||
writeln!(tmp_file, "{}", pair.1).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_sub_dirs(tmp_dir: &TempDir) {
|
||||
let random_sub_dir_path = tmp_dir.path().join("random_sub_dir_name");
|
||||
create_dir(random_sub_dir_path).unwrap();
|
||||
|
||||
let another_sub_dir_path = tmp_dir.path().join(SUB_DIR_NAME);
|
||||
create_dir(another_sub_dir_path).unwrap();
|
||||
}
|
||||
|
||||
/// We spice up some of the values, based on a given `seed` parameter.
|
||||
pub fn get_block<E: EthSpec>(seed: u64) -> BeaconBlock<E> {
|
||||
let spec = &mut E::default_spec();
|
||||
Reference in New Issue
Block a user