Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Draft implementation of BLS precompiles #11697

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
71 changes: 67 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,6 @@ members = [
"ethcore/wasm/run",
"evmbin",
]
exclude = [
"vendor",
]
1 change: 1 addition & 0 deletions ethcore/builtin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
179 changes: 179 additions & 0 deletions ethcore/builtin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions vendor/milagro_bls
Submodule milagro_bls added at 8c4647