diff --git a/Cargo.lock b/Cargo.lock index f0c36a567..ed71b73f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,16 +104,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "aurora-blake2" -version = "0.9.1" -source = "git+https://github.com/aurora-is-near/aurora-blake2.git#05a0b5f7a544c527c0118f8afe2f943b3de4bb03" -dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - [[package]] name = "aurora-bn" version = "0.1.0" @@ -159,7 +149,6 @@ dependencies = [ name = "aurora-engine-precompiles" version = "1.0.0" dependencies = [ - "aurora-blake2", "aurora-bn", "aurora-engine-sdk", "aurora-engine-types", diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml index b05e074b3..1965010b4 100644 --- a/engine-precompiles/Cargo.toml +++ b/engine-precompiles/Cargo.toml @@ -16,7 +16,6 @@ autobenches = false aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } -aurora-blake2 = { git = "https://github.com/aurora-is-near/aurora-blake2.git", version = "0.9.1", default-features = false } borsh = { version = "0.8.2", default-features = false } bn = { package = "aurora-bn", git = "https://github.com/aurora-is-near/aurora-bn.git", default-features = false } evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", rev = "37448b6cacd98b06282cff5a559684505c29bd2b", default-features = false } @@ -36,7 +35,7 @@ serde_json = "1" rand = "0.7.3" [features] -std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "borsh/std", "aurora-blake2/std", "bn/std", "evm/std", "evm-core/std", "libsecp256k1/std", "ripemd160/std", "sha2/std", "sha3/std", "ethabi/std"] +std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "borsh/std", "bn/std", "evm/std", "evm-core/std", "libsecp256k1/std", "ripemd160/std", "sha2/std", "sha3/std", "ethabi/std"] contract = [] log = [] error_refund = [] diff --git a/engine-precompiles/src/blake2.rs b/engine-precompiles/src/blake2.rs index 819039b47..d953bd374 100644 --- a/engine-precompiles/src/blake2.rs +++ b/engine-precompiles/src/blake2.rs @@ -3,6 +3,7 @@ use evm::{Context, ExitError}; use crate::prelude::types::EthGas; use crate::prelude::{mem, types::Address, Borrowed}; use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; +use aurora_engine_types::Vec; /// Blake2 costs. mod costs { @@ -15,6 +16,116 @@ mod costs { /// Blake2 constants. mod consts { pub(super) const INPUT_LENGTH: usize = 213; + + /// The precomputed SIGMA. + /// + /// See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693#section-2.7) specification for more details. + pub(super) const SIGMA: [[usize; 16]; 10] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], + ]; + + /// The initialization vector. + /// + /// See [RFC 7693](https://tools.ietf.org/html/rfc7693#section-2.6) specification for more details. + pub(super) const IV: [u64; 8] = [ + 0x6a09e667f3bcc908, + 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, + 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, + 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, + 0x5be0cd19137e2179, + ]; + + // G rotation constants. + + /// G rotation 1. + pub(super) const R1: u32 = 32; + + /// G rotation 2. + pub(super) const R2: u32 = 24; + + /// G rotation 3. + pub(super) const R3: u32 = 16; + + /// G rotation 4. + pub(super) const R4: u32 = 63; +} + +/// The G primitive function which mixes two input worlds, "x" and "y", into +/// four words indexed by "a", "b", "c", and "d" in the working vector v[0..15]. +/// +/// See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693#section-3.1) specification for more +/// details. +fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { + v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); + v[d] = (v[d] ^ v[a]).rotate_right(consts::R1); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(consts::R2); + v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); + v[d] = (v[d] ^ v[a]).rotate_right(consts::R3); + v[c] = v[c].wrapping_add(v[d]); + v[b] = (v[b] ^ v[c]).rotate_right(consts::R4); +} + +/// Takes as an argument the state vector `h`, message block vector `m` (the last block is padded +/// with zeros to full block size, if required), 2w-bit offset counter `t`, and final block +/// indicator flag `f`. Local vector v[0..15] is used in processing. F returns a new state vector. +/// The number of rounds, `r`, is 12 for BLAKE2b and 10 for BLAKE2s. Rounds are numbered from 0 to +/// r - 1. +/// +/// See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693#section-3.2) specification for more +/// details. +fn f(mut h: [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: u32) -> Vec { + // Initialize the work vector. + let mut v = [0u64; 16]; + v[0..8].copy_from_slice(&h); // First half from state. + v[8..16].copy_from_slice(&consts::IV); // Second half from IV. + + v[12] ^= t[0]; // Low word of the offset. + v[13] ^= t[1]; // High word. + + if f { + // last block flag? + v[14] = !v[14] // Invert all bits. + } + + for i in 0..rounds { + // Typically twelve rounds for blake2b. + // Message word selection permutation for this round. + let s = &consts::SIGMA[i as usize % 10]; + g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]); + g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]); + g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]); + g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]); + + g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]); + g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]); + g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]); + g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]); + } + + for i in 0..8 { + // XOR the two halves. + h[i] ^= v[i] ^ v[i + 8]; + } + + let mut result = Vec::with_capacity(64); + for value in h { + result.extend_from_slice(&value.to_le_bytes()); + } + + result } pub(super) struct Blake2F; @@ -94,7 +205,7 @@ impl Precompile for Blake2F { } let finished = input[212] != 0; - let output = aurora_blake2::blake2b_f(rounds, h, m, t, finished).to_vec(); + let output = f(h, m, t, finished, rounds); Ok(PrecompileOutput::without_logs(cost, output).into()) } }