Add whiteblock script, CLI options to support it

This commit is contained in:
Paul Hauner
2019-09-10 12:13:54 -04:00
parent 5de80f2799
commit 8c5a8034b6
16 changed files with 342 additions and 28 deletions

View File

@@ -10,10 +10,11 @@ edition = "2018"
lazy_static = "1.4"
num-bigint = "0.2"
eth2_hashing = "0.1"
hex = "0.3"
milagro_bls = { git = "https://github.com/michaelsproul/milagro_bls", branch = "little-endian-v0.10" }
serde_yaml = "0.8"
serde = "1.0"
serde_derive = "1.0"
[dev-dependencies]
base64 = "0.10"
serde = "1.0"
serde_derive = "1.0"
serde_yaml = "0.8"

View File

@@ -0,0 +1,20 @@
- {privkey: '0x25295f0d1d592a90b333e26e85149708208e9f8e8bc18f6c77bd62f8ad7a6866',
pubkey: '0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c'}
- {privkey: '0x51d0b65185db6989ab0b560d6deed19c7ead0e24b9b6372cbecb1f26bdfad000',
pubkey: '0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b'}
- {privkey: '0x315ed405fafe339603932eebe8dbfd650ce5dafa561f6928664c75db85f97857',
pubkey: '0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b'}
- {privkey: '0x25b1166a43c109cb330af8945d364722757c65ed2bfed5444b5a2f057f82d391',
pubkey: '0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e'}
- {privkey: '0x3f5615898238c4c4f906b507ee917e9ea1bb69b93f1dbd11a34d229c3b06784b',
pubkey: '0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e'}
- {privkey: '0x055794614bc85ed5436c1f5cab586aab6ca84835788621091f4f3b813761e7a8',
pubkey: '0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34'}
- {privkey: '0x1023c68852075965e0f7352dee3f76a84a83e7582c181c10179936c6d6348893',
pubkey: '0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373'}
- {privkey: '0x3a941600dc41e5d20e818473b817a28507c23cdfdb4b659c15461ee5c71e41f5',
pubkey: '0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac'}
- {privkey: '0x066e3bdc0415530e5c7fed6382d5c822c192b620203cf669903e1810a8c67d06',
pubkey: '0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7'}
- {privkey: '0x2b3b88a041168a1c4cd04bdd8de7964fd35238f95442dc678514f9dadb81ec34',
pubkey: '0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a'}

View File

@@ -22,8 +22,13 @@ extern crate lazy_static;
use eth2_hashing::hash;
use milagro_bls::{Keypair, PublicKey, SecretKey};
use num_bigint::BigUint;
use serde_derive::{Deserialize, Serialize};
use std::convert::TryInto;
use std::fs::File;
use std::path::PathBuf;
pub const PRIVATE_KEY_BYTES: usize = 48;
pub const PUBLIC_KEY_BYTES: usize = 48;
pub const HASH_BYTES: usize = 32;
lazy_static! {
@@ -63,3 +68,65 @@ pub fn keypair(validator_index: usize) -> Keypair {
sk,
}
}
#[derive(Serialize, Deserialize)]
struct YamlKeypair {
/// Big-endian.
privkey: String,
/// Big-endian.
pubkey: String,
}
impl TryInto<Keypair> for YamlKeypair {
type Error = String;
fn try_into(self) -> Result<Keypair, Self::Error> {
let privkey = string_to_bytes(&self.privkey)?;
let pubkey = string_to_bytes(&self.pubkey)?;
if (privkey.len() > PRIVATE_KEY_BYTES) || (pubkey.len() > PUBLIC_KEY_BYTES) {
return Err("Public or private key is too long".into());
}
let sk = {
let mut bytes = vec![0; PRIVATE_KEY_BYTES - privkey.len()];
bytes.extend_from_slice(&privkey);
SecretKey::from_bytes(&bytes)
.map_err(|e| format!("Failed to decode bytes into secret key: {:?}", e))?
};
let pk = {
let mut bytes = vec![0; PUBLIC_KEY_BYTES - pubkey.len()];
bytes.extend_from_slice(&pubkey);
PublicKey::from_bytes(&bytes)
.map_err(|e| format!("Failed to decode bytes into public key: {:?}", e))?
};
Ok(Keypair { pk, sk })
}
}
fn string_to_bytes(string: &str) -> Result<Vec<u8>, String> {
let string = if string.starts_with("0x") {
&string[2..]
} else {
string
};
hex::decode(string).map_err(|e| format!("Unable to decode public or private key: {}", e))
}
/// Loads keypairs from a YAML encoded file.
///
/// Uses this as reference:
/// https://github.com/ethereum/eth2.0-pm/blob/9a9dbcd95e2b8e10287797bd768014ab3d842e99/interop/mocked_start/keygen_10_validators.yaml
pub fn keypairs_from_yaml_file(path: PathBuf) -> Result<Vec<Keypair>, String> {
let file =
File::open(path.clone()).map_err(|e| format!("Unable to open YAML key file: {}", e))?;
serde_yaml::from_reader::<_, Vec<YamlKeypair>>(file)
.map_err(|e| format!("Could not parse YAML: {:?}", e))?
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, String>>()
}

View File

@@ -0,0 +1,23 @@
#![cfg(test)]
use eth2_interop_keypairs::{keypair as reference_keypair, keypairs_from_yaml_file};
use std::path::PathBuf;
fn yaml_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("specs")
.join("keygen_10_validators.yaml")
}
#[test]
fn load_from_yaml() {
let keypairs = keypairs_from_yaml_file(yaml_path()).expect("should read keypairs from file");
keypairs.into_iter().enumerate().for_each(|(i, keypair)| {
assert_eq!(
keypair,
reference_keypair(i),
"Decoded key {} does not match generated key",
i
)
});
}