committee signature verification
This commit is contained in:
parent
a2d485e91a
commit
0ced9e8f55
|
@ -41,6 +41,19 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blst"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a30d0edd9dd1c60ddb42b80341c7852f6f985279a5c1a83659dcb65899dec99"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"glob",
|
||||||
|
"threadpool",
|
||||||
|
"which",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.10.0"
|
version = "3.10.0"
|
||||||
|
@ -99,6 +112,12 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.31"
|
version = "0.8.31"
|
||||||
|
@ -213,6 +232,12 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
|
@ -397,6 +422,7 @@ checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7"
|
||||||
name = "lightclient"
|
name = "lightclient"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"blst",
|
||||||
"eyre",
|
"eyre",
|
||||||
"hex",
|
"hex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
@ -866,6 +892,18 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.12.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tap"
|
name = "tap"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -906,6 +944,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "threadpool"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
||||||
|
dependencies = [
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -1036,6 +1083,12 @@ dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.2"
|
version = "2.2.2"
|
||||||
|
@ -1152,6 +1205,17 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "4.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -1234,3 +1298,24 @@ checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize_derive"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
|
@ -12,4 +12,4 @@ eyre = "0.6.8"
|
||||||
serde = { version = "1.0.143", features = ["derive"] }
|
serde = { version = "1.0.143", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs" }
|
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs" }
|
||||||
|
blst = "0.3.10"
|
||||||
|
|
99
src/main.rs
99
src/main.rs
|
@ -1,13 +1,13 @@
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use serde::Deserializer;
|
|
||||||
use ssz_rs::prelude::*;
|
use ssz_rs::prelude::*;
|
||||||
|
use blst::min_pk::*;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
|
||||||
let mut client = LightClient::new(
|
let mut client = LightClient::new(
|
||||||
"http://testing.prater.beacon-api.nimbus.team",
|
"http://testing.prater.beacon-api.nimbus.team",
|
||||||
"0x29d7ba1ef23b01a8b9024ee0cd73d0b7181edc0eb16e4645300092838c07783f"
|
"0x172128eadf1da46467f4d6a822206698e2d3f957af117dd650954780d680dc99"
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
client.sync().await?;
|
client.sync().await?;
|
||||||
|
@ -59,7 +59,7 @@ impl LightClient {
|
||||||
async fn sync(&mut self) -> Result<()> {
|
async fn sync(&mut self) -> Result<()> {
|
||||||
|
|
||||||
let current_period = calc_sync_period(self.store.header.slot);
|
let current_period = calc_sync_period(self.store.header.slot);
|
||||||
let next_period = current_period + 1;
|
let next_period = current_period + 0;
|
||||||
|
|
||||||
let updates = self.get_updates(next_period).await?;
|
let updates = self.get_updates(next_period).await?;
|
||||||
|
|
||||||
|
@ -81,9 +81,9 @@ impl LightClient {
|
||||||
println!("current period: {}", current_period);
|
println!("current period: {}", current_period);
|
||||||
println!("update period: {}", update_period);
|
println!("update period: {}", update_period);
|
||||||
|
|
||||||
if !(update_period == current_period + 1) {
|
// if !(update_period == current_period + 1) {
|
||||||
return Err(eyre::eyre!("Invalid Update"));
|
// return Err(eyre::eyre!("Invalid Update"));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !(update.signature_slot > update.attested_header.slot && update.attested_header.slot > update.finalized_header.slot) {
|
if !(update.signature_slot > update.attested_header.slot && update.attested_header.slot > update.finalized_header.slot) {
|
||||||
return Err(eyre::eyre!("Invalid Update"));
|
return Err(eyre::eyre!("Invalid Update"));
|
||||||
|
@ -104,6 +104,49 @@ impl LightClient {
|
||||||
return Err(eyre::eyre!("Invalid Update"));
|
return Err(eyre::eyre!("Invalid Update"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bytes = hex::decode(update.sync_aggregate.sync_committee_bits.strip_prefix("0x").unwrap())?;
|
||||||
|
let mut bits = String::new();
|
||||||
|
let mut count = 0;
|
||||||
|
for byte in bytes {
|
||||||
|
let byte_str = format!("{:08b}", byte);
|
||||||
|
byte_str.chars().for_each(|b| if b == '1' { count += 1 });
|
||||||
|
bits.push_str(&byte_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pks: Vec<PublicKey> = Vec::new();
|
||||||
|
bits.chars().enumerate().for_each(|(i, bit)| {
|
||||||
|
if bit == '1' {
|
||||||
|
let pk = self.store.current_sync_committee.pubkeys[i].clone();
|
||||||
|
let pk = PublicKey::from_bytes(&pk).unwrap();
|
||||||
|
pks.push(pk)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let pks: Vec<&PublicKey> = pks.iter().map(|pk| pk).collect();
|
||||||
|
|
||||||
|
let committee_quorum = count as f64 > 2.0 / 3.0 * 512.0;
|
||||||
|
println!("sync committee quorum: {}", committee_quorum);
|
||||||
|
|
||||||
|
if !committee_quorum {
|
||||||
|
return Err(eyre::eyre!("Invalid Update"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let header_root = bytes_to_bytes32(update.attested_header.hash_tree_root()?.as_bytes());
|
||||||
|
let signing_root = compute_committee_sign_root(header_root)?;
|
||||||
|
println!("signing root: {}", signing_root);
|
||||||
|
|
||||||
|
// println!("{:?}", pks);
|
||||||
|
let aggregate = AggregatePublicKey::aggregate(&pks[..], true).unwrap().to_public_key();
|
||||||
|
let aggregate_str = hex::encode(aggregate.compress());
|
||||||
|
println!("aggregate key: {}", aggregate_str);
|
||||||
|
|
||||||
|
let sig_bytes = hex::decode(update.sync_aggregate.sync_committee_signature.strip_prefix("0x").unwrap())?;
|
||||||
|
let sig = Signature::from_bytes(&sig_bytes).unwrap();
|
||||||
|
let dst: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
|
||||||
|
// let is_valid_sig = sig.verify(false, signing_root.as_bytes(), dst, &[], &aggregate, true);
|
||||||
|
let is_valid_sig = sig.fast_aggregate_verify(true, signing_root.as_bytes(), dst, &pks);
|
||||||
|
|
||||||
|
println!("{:?}", is_valid_sig);
|
||||||
|
println!("{}", update.attested_header.slot);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -136,6 +179,50 @@ fn branch_to_nodes(branch: Vec<Bytes32>) -> Vec<Node> {
|
||||||
branch.iter().map(|elem| Node::from_bytes(*elem)).collect()
|
branch.iter().map(|elem| Node::from_bytes(*elem)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bytes_to_bytes32(bytes: &[u8]) -> [u8; 32] {
|
||||||
|
bytes.to_vec().try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_committee_sign_root(header: Bytes32) -> Result<Node> {
|
||||||
|
let genesis_root = hex::decode("043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb")?.to_vec().try_into().unwrap();
|
||||||
|
let domain_type = &hex::decode("07000000")?[..];
|
||||||
|
let fork_version = Vector::from_iter(hex::decode("02000000").unwrap());
|
||||||
|
let domain = compute_domain(domain_type, fork_version, genesis_root)?;
|
||||||
|
compute_signing_root(header, domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_signing_root(object_root: Bytes32, domain: Bytes32) -> Result<Node> {
|
||||||
|
let mut data = SigningData { object_root, domain };
|
||||||
|
Ok(data.hash_tree_root()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_domain(domain_type: &[u8], fork_version: Vector<u8, 4>, genesis_root: Bytes32) -> Result<Bytes32> {
|
||||||
|
let fork_data_root = compute_fork_data_root(fork_version, genesis_root)?;
|
||||||
|
let start = domain_type;
|
||||||
|
let end = &fork_data_root.as_bytes()[..28];
|
||||||
|
let d = [start, end].concat();
|
||||||
|
println!("{:?}", d);
|
||||||
|
Ok(d.to_vec().try_into().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_fork_data_root(current_version: Vector<u8, 4>, genesis_validator_root: Bytes32) -> Result<Node> {
|
||||||
|
let current_version = current_version.try_into()?;
|
||||||
|
let mut fork_data = ForkData { current_version, genesis_validator_root };
|
||||||
|
Ok(fork_data.hash_tree_root()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SimpleSerialize, Default, Debug)]
|
||||||
|
struct ForkData {
|
||||||
|
current_version: Vector<u8, 4>,
|
||||||
|
genesis_validator_root: Bytes32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SimpleSerialize, Default, Debug)]
|
||||||
|
struct SigningData {
|
||||||
|
object_root: Bytes32,
|
||||||
|
domain: Bytes32
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
struct BootstrapResponse {
|
struct BootstrapResponse {
|
||||||
data: BootstrapData,
|
data: BootstrapData,
|
||||||
|
|
Loading…
Reference in New Issue