Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: extended BLS12-381 precompiles with NEAR host functions #999

Open
wants to merge 29 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e4e4c48
Added Prague hard fork
mrLSD Jan 15, 2025
464b80b
Fix tests gas
mrLSD Jan 15, 2025
7d61074
Update gas for tests
mrLSD Jan 15, 2025
3743e5d
Updated to: v0.47.0-aurora-rc.1
mrLSD Jan 22, 2025
b245d35
Merge branch 'develop' of github.com:aurora-is-near/aurora-engine int…
mrLSD Jan 30, 2025
092308b
Added basic BLS12-381 functions & G1_ADD precompile
mrLSD Jan 30, 2025
35960d5
Added precompiles: G1 MSM, G2 ADD, G2 MSM
mrLSD Jan 31, 2025
86196b0
Fixed gas for tests
mrLSD Jan 30, 2025
1ae42dc
Complete all BLS precompiles & tests gas cost refactoring
mrLSD Jan 31, 2025
a90cd4b
Added unit tests for BLS precompiles
mrLSD Feb 3, 2025
2270204
BLS12-381 test dev tools and json tests
mrLSD Feb 5, 2025
fbf479f
Silo tests fix
mrLSD Feb 5, 2025
11cca58
Fix silo clippy
mrLSD Feb 5, 2025
6a23603
BLS12-381 standalone test
mrLSD Feb 5, 2025
6bf9e41
Added documentation
mrLSD Feb 6, 2025
b860a2e
Extended BLS12-381 test cases for submit transactions
mrLSD Feb 6, 2025
ab884d2
Fix typo in comments
mrLSD Feb 7, 2025
d7e52b2
Added to engine-sdk BLS12-381 host functions
mrLSD Feb 11, 2025
c243252
Merge branch 'feat/sdk-bls' into feat/bls-precompiles
mrLSD Feb 11, 2025
85df760
Refactore BLS12-381 precompiles for NEP-488
mrLSD Feb 17, 2025
999d53a
Added execution funcs for BLS precompiles
mrLSD Feb 17, 2025
3fbbf3e
Added g1_mul and refactored general functions
mrLSD Feb 18, 2025
3d2a421
Fix BLS12-381 clippy
mrLSD Feb 19, 2025
49f4147
Refactored tests
mrLSD Feb 19, 2025
3bc45e0
Tests refactoring for BLS
mrLSD Feb 19, 2025
c7e788c
Fix clippy
mrLSD Feb 19, 2025
b650c40
Refactore BLS: g1_add, g1_msm
mrLSD Feb 20, 2025
2023788
Fix BLS NEAR-functions compatibility actions and logic
mrLSD Feb 20, 2025
a67b164
Cleanup
mrLSD Feb 20, 2025
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
17 changes: 9 additions & 8 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ bstr = "1"
byte-slice-cast = { version = "1", default-features = false }
criterion = "0.5"
ethabi = { version = "18", default-features = false }
evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.47.0-beta.1", default-features = false }
evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.47.0-beta.1", default-features = false, features = ["std"] }
evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.47.0-beta.1", default-features = false, features = ["std", "tracing"] }
evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.47.0-beta.1", default-features = false, features = ["std", "tracing"] }
evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "0.47.0-rc.1", default-features = false }
evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "0.47.0-rc.1", default-features = false, features = ["std"] }
evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "0.47.0-rc.1", default-features = false, features = ["std", "tracing"] }
evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "0.47.0-rc.1", default-features = false, features = ["std", "tracing"] }
fixed-hash = { version = "0.8", default-features = false }
function_name = "0.3"
git2 = "0.20"
Expand Down
1 change: 1 addition & 0 deletions engine-precompiles/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ num.workspace = true
ripemd.workspace = true
sha2.workspace = true
sha3.workspace = true
blst = "0.3.13"

[dev-dependencies]
aurora-engine-test-doubles.workspace = true
Expand Down
143 changes: 143 additions & 0 deletions engine-precompiles/src/bls12_381/g1_add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use super::G1_INPUT_ITEM_LENGTH;
use crate::prelude::types::{make_address, Address, EthGas};
use crate::prelude::Borrowed;
use crate::{EvmPrecompileResult, Precompile, PrecompileOutput, Vec};
use evm::{Context, ExitError};

/// Base gas fee for BLS12-381 `g1_add` operation.
const BASE_GAS_FEE: u64 = 375;

/// Input length of `g1_add` operation.
const INPUT_LENGTH: usize = 256;

/// BLS12-381 G1 Add
pub struct BlsG1Add;

impl BlsG1Add {
pub const ADDRESS: Address = make_address(0, 0xB);

#[cfg(not(feature = "contract"))]
fn execute(input: &[u8]) -> Result<Vec<u8>, ExitError> {
use super::standalone::g1;
use blst::{
blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine,
blst_p1_to_affine,
};

// NB: There is no subgroup check for the G1 addition precompile.
//
// We set the subgroup checks here to `false`
let a_aff = &g1::extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?;
let b_aff = &g1::extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?;

let mut b = blst_p1::default();
// SAFETY: b and b_aff are blst values.
unsafe { blst_p1_from_affine(&mut b, b_aff) };

let mut p = blst_p1::default();
// SAFETY: p, b and a_aff are blst values.
unsafe { blst_p1_add_or_double_affine(&mut p, &b, a_aff) };

let mut p_aff = blst_p1_affine::default();
// SAFETY: p_aff and p are blst values.
unsafe { blst_p1_to_affine(&mut p_aff, &p) };

Ok(g1::encode_g1_point(&p_aff))
}

#[cfg(feature = "contract")]
#[allow(clippy::range_plus_one)]
fn execute(input: &[u8]) -> Result<Vec<u8>, ExitError> {
use super::{extract_g1, padding_g1_result, FP_LENGTH};

let (p0_x, p0_y) = extract_g1(&input[..G1_INPUT_ITEM_LENGTH])?;
let (p1_x, p1_y) = extract_g1(&input[G1_INPUT_ITEM_LENGTH..])?;

let mut g1_input = [0u8; 4 * FP_LENGTH + 2];

if input[..G1_INPUT_ITEM_LENGTH] == [0; G1_INPUT_ITEM_LENGTH] {
g1_input[1] |= 0x40;
} else {
g1_input[1..1 + FP_LENGTH].copy_from_slice(p0_x);
g1_input[1 + FP_LENGTH..1 + 2 * FP_LENGTH].copy_from_slice(p0_y);
}

if input[G1_INPUT_ITEM_LENGTH..] == [0; G1_INPUT_ITEM_LENGTH] {
g1_input[2 + 2 * FP_LENGTH] |= 0x40;
} else {
g1_input[2 + 2 * FP_LENGTH..2 + 3 * FP_LENGTH].copy_from_slice(p1_x);
g1_input[2 + 3 * FP_LENGTH..2 + 4 * FP_LENGTH].copy_from_slice(p1_y);
}

let output = aurora_engine_sdk::bls12381_p1_sum(&g1_input[..]);
Ok(padding_g1_result(&output))
}
}

impl Precompile for BlsG1Add {
fn required_gas(_input: &[u8]) -> Result<EthGas, ExitError>
where
Self: Sized,
{
Ok(EthGas::new(BASE_GAS_FEE))
}

/// G1 addition call expects `256` bytes as an input that is interpreted as byte
/// concatenation of two G1 points (`128` bytes each).
/// Output is an encoding of addition operation result - single G1 point (`128`
/// bytes).
/// See also: <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition>
fn run(
&self,
input: &[u8],
target_gas: Option<EthGas>,
_context: &Context,
_is_static: bool,
) -> EvmPrecompileResult {
if input.len() != INPUT_LENGTH {
return Err(ExitError::Other(Borrowed("ERR_BLS_G1ADD_INPUT_LEN")));
}

let cost = Self::required_gas(input)?;
if let Some(target_gas) = target_gas {
if cost > target_gas {
return Err(ExitError::OutOfGas);
}
}

let output = Self::execute(input)?;
Ok(PrecompileOutput::without_logs(cost, output))
}
}

#[cfg(test)]
mod tests {
use super::*;
use aurora_engine_types::H160;

#[test]
fn bls12_381_g1_add() {
let precompile = BlsG1Add;
let ctx = Context {
address: H160::zero(),
caller: H160::zero(),
apparent_value: 0.into(),
};
let input = hex::decode("\
00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb\
0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed2\
000000000000000000000000000000000441e7f7f96198e4c23bd5eb16f1a7f045dbc8c53219ab2bcea91d3a027e2dfe659feac64905f8b9add7e4bfc91bec2b\
0000000000000000000000000000000005fc51bb1b40c87cd4292d4b66f8ca5ce4ef9abd2b69d4464b4879064203bda7c9fc3f896a3844ebc713f7bb20951d95")
.expect("hex decoding failed");

let res = precompile
.run(&input, None, &ctx, false)
.expect("precompile run should not fail");
let expected = hex::decode("\
0000000000000000000000000000000016b8ab56b45a9294466809b8e858c1ad15ad0d52cfcb62f8f5753dc94cee1de6efaaebce10701e3ec2ecaa9551024ea\
600000000000000000000000000000000124571eec37c0b1361023188d66ec17c1ec230d31b515e0e81e599ec19e40c8a7c8cdea9735bc3d8b4e37ca7e5dd71f6")
.expect("hex decoding failed");

assert_eq!(res.output, expected);
}
}
Loading
Loading