From 56c75c0d1100cedf85f99448830cd0fd3e90d6c6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 11 May 2020 10:53:51 +0200 Subject: [PATCH] Implement everything except pairing and FP maps --- .gitmodules | 3 + Cargo.lock | 71 ++++++++++++++- Cargo.toml | 3 + ethcore/builtin/Cargo.toml | 1 + ethcore/builtin/src/lib.rs | 179 +++++++++++++++++++++++++++++++++++++ vendor/milagro_bls | 1 + 6 files changed, 254 insertions(+), 4 deletions(-) create mode 160000 vendor/milagro_bls diff --git a/.gitmodules b/.gitmodules index 7abf7f59263..4ffc9e2d886 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "ethcore/res/wasm-tests"] path = ethcore/res/wasm-tests url = https://github.com/openethereum/wasm-tests +[submodule "vendor/milagro_bls"] + path = vendor/milagro_bls + url = https://github.com/sorpaas/milagro_bls diff --git a/Cargo.lock b/Cargo.lock index 54a015535b4..c7027c8005d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,6 +103,13 @@ dependencies = [ "memchr", ] +[[package]] +name = "amcl" +version = "0.1.0" +dependencies = [ + "zeroize 0.9.3", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -994,7 +1001,7 @@ dependencies = [ "rlp", "secp256k1", "tiny-keccak 2.0.2", - "zeroize", + "zeroize 1.1.0", ] [[package]] @@ -1263,6 +1270,7 @@ dependencies = [ "keccak-hash", "log", "maplit", + "milagro_bls", "num", "parity-bytes", "parity-crypto", @@ -1808,7 +1816,7 @@ dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", "syn 1.0.17", - "synstructure", + "synstructure 0.12.3", ] [[package]] @@ -2832,6 +2840,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "milagro_bls" +version = "0.11.0" +dependencies = [ + "amcl", + "hex", + "lazy_static", + "rand 0.7.3", + "ring", + "yaml-rust", + "zeroize 1.1.0", +] + [[package]] name = "mime" version = "0.3.16" @@ -3254,7 +3275,7 @@ dependencies = [ "sha2", "subtle 2.2.2", "tiny-keccak 2.0.2", - "zeroize", + "zeroize 1.1.0", ] [[package]] @@ -3557,7 +3578,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2 1.0.9", "syn 1.0.17", - "synstructure", + "synstructure 0.12.3", ] [[package]] @@ -4822,6 +4843,18 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "synstructure" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", + "unicode-xid 0.1.0", +] + [[package]] name = "synstructure" version = "0.12.3" @@ -5798,8 +5831,38 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "zeroize" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" +dependencies = [ + "zeroize_derive", +] + [[package]] name = "zeroize" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" + +[[package]] +name = "zeroize_derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", + "synstructure 0.10.2", +] diff --git a/Cargo.toml b/Cargo.toml index fe140117de1..986550bc56a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -131,3 +131,6 @@ members = [ "ethcore/wasm/run", "evmbin", ] +exclude = [ + "vendor", +] diff --git a/ethcore/builtin/Cargo.toml b/ethcore/builtin/Cargo.toml index 16780253706..8b4a4491917 100644 --- a/ethcore/builtin/Cargo.toml +++ b/ethcore/builtin/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4" num = { version = "0.1", default-features = false, features = ["bigint"] } parity-bytes = "0.1" parity-crypto = { version = "0.6.1", features = ["publickey"] } +milagro_bls = { path = "../../vendor/milagro_bls" } [dev-dependencies] hex-literal = "0.2.1" diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 8f9dde5fc3e..b9a7e274286 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -37,6 +37,7 @@ use num::{BigUint, Zero, One}; use parity_bytes::BytesRef; use parity_crypto::digest; use eip_152::compress; +use milagro_bls as bls; /// Native implementation of a built-in contract. pub trait Implementation: Send + Sync { @@ -394,6 +395,42 @@ pub struct Bn128Pairing; /// The Blake2F builtin pub struct Blake2F; +#[derive(Debug)] +/// The Bls12G1Add builtin. +pub struct Bls12G1Add; + +#[derive(Debug)] +/// The Bls12G1Mul builtin. +pub struct Bls12G1Mul; + +#[derive(Debug)] +/// The Bls12G1MultiExp builtin. +pub struct Bls12G1MultiExp; + +#[derive(Debug)] +/// The Bls12G2Add builtin. +pub struct Bls12G2Add; + +#[derive(Debug)] +/// The Bls12G2Mul builtin. +pub struct Bls12G2Mul; + +#[derive(Debug)] +/// The Bls12G2MultiExp builtin. +pub struct Bls12G2MultiExp; + +#[derive(Debug)] +/// The Bls12Pairing builtin. +pub struct Bls12Pairing; + +#[derive(Debug)] +/// The Bls12MapFpToG1 builtin. +pub struct Bls12MapFpToG1; + +#[derive(Debug)] +/// The Bls12MapFp2ToG2 builtin. +pub struct Bls12MapFp2ToG2; + impl Implementation for Identity { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { output.write(0, input); @@ -756,6 +793,148 @@ impl Bn128Pairing { } } +impl Implementation for Bls12G1Add { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() != 256 { + return Err("Invalid input length") + } + + let mut g1a = bls::G1Point::from_bytes(&input[0..128]).map_err(|_| "Invalid g1a")?; + let g1b = bls::G1Point::from_bytes(&input[128..256]).map_err(|_| "Invalid g1b")?; + + g1a.add(&g1b); + + output.write(0, &g1a.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12G1Mul { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() != 160 { + return Err("Invalid input length") + } + + let mut g1a = bls::G1Point::from_bytes(&input[0..128]).map_err(|_| "Invalid g1a")?; + let num = bls::BigNum::frombytes(&input[128..160]); + + g1a.mul(&num); + + output.write(0, &g1a.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12G1MultiExp { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() % 160 != 0 { + return Err("Invalid input length") + } + + let mut start = 0; + let mut ret = bls::G1Point::new(); + while start < input.len() { + let mut g1a = bls::G1Point::from_bytes(&input[start..(start + 128)]) + .map_err(|_| "Invalid g1a")?; + let num = bls::BigNum::frombytes(&input[(start + 128)..(start + 160)]); + + g1a.mul(&num); + ret.add(&g1a); + + start += 160; + } + + output.write(0, &ret.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12G2Add { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() != 512 { + return Err("Invalid input length") + } + + let mut g1a = bls::G2Point::from_bytes(&input[0..256]).map_err(|_| "Invalid g1a")?; + let g1b = bls::G2Point::from_bytes(&input[256..512]).map_err(|_| "Invalid g1b")?; + + g1a.add(&g1b); + + output.write(0, &g1a.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12G2Mul { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() != 288 { + return Err("Invalid input length") + } + + let mut g1a = bls::G2Point::from_bytes(&input[0..256]).map_err(|_| "Invalid g1a")?; + let num = bls::BigNum::frombytes(&input[256..288]); + + g1a.mul(&num); + + output.write(0, &g1a.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12G2MultiExp { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() % 288 != 0 { + return Err("Invalid input length") + } + + let mut start = 0; + let mut ret = bls::G2Point::new(); + while start < input.len() { + let mut g1a = bls::G2Point::from_bytes(&input[start..(start + 256)]) + .map_err(|_| "Invalid g1a")?; + let num = bls::BigNum::frombytes(&input[(start + 256)..(start + 288)]); + + g1a.mul(&num); + ret.add(&g1a); + + start += 288; + } + + output.write(0, &ret.as_bytes()[..]); + Ok(()) + } +} + +impl Implementation for Bls12Pairing { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() % 384 != 0 { + return Err("Invalid input length") + } + + unimplemented!() + } +} + +impl Implementation for Bls12MapFpToG1 { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() % 64 != 0 { + return Err("Invalid input length") + } + + unimplemented!() + } +} + +impl Implementation for Bls12MapFp2ToG2 { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { + if input.len() % 128 != 0 { + return Err("Invalid input length") + } + + unimplemented!() + } +} + #[cfg(test)] mod tests { use std::convert::TryFrom; diff --git a/vendor/milagro_bls b/vendor/milagro_bls new file mode 160000 index 00000000000..8c46476e488 --- /dev/null +++ b/vendor/milagro_bls @@ -0,0 +1 @@ +Subproject commit 8c46476e4881a47551e13f8ef4902d118e01bedc