From 8bbdb436d7fb36c1f1618635df24cbb6c6294097 Mon Sep 17 00:00:00 2001 From: fengjian <445077+fengjian@users.noreply.github.com> Date: Mon, 18 Mar 2024 16:03:19 +0800 Subject: [PATCH] implementing BLAKE3 opcode --- Cargo.lock | 5 +++-- Cargo.toml | 1 + src/isa/bytecode.rs | 3 +++ src/isa/exec.rs | 8 ++++++++ src/isa/instr.rs | 10 ++++++++++ src/isa/macros.rs | 3 +++ src/isa/opcodes.rs | 1 + 7 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f68034..be38cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,6 +9,7 @@ dependencies = [ "amplify", "ascii-armor", "baid58", + "blake3", "curve25519-dalek", "getrandom 0.2.12", "half", @@ -153,9 +154,9 @@ checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", "arrayvec", diff --git a/Cargo.toml b/Cargo.toml index d9009e8..6f75bee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ paste = "1" strict_encoding = { version = "2.7.0-beta.1", default-features = false, features = ["float", "derive"] } strict_types = { version = "2.7.0-beta.2", optional = true } sha2 = "0.10.8" +blake3 = "1.5.1" ripemd = "0.1.3" baid58 = "0.4.4" secp256k1 = { version = "0.28.2", optional = true, features = ["global-context"] } diff --git a/src/isa/bytecode.rs b/src/isa/bytecode.rs index 788d7b8..b800c93 100644 --- a/src/isa/bytecode.rs +++ b/src/isa/bytecode.rs @@ -1299,6 +1299,7 @@ impl Bytecode for DigestOp { DigestOp::Ripemd(_, _) => INSTR_RIPEMD, DigestOp::Sha256(_, _) => INSTR_SHA256, DigestOp::Sha512(_, _) => INSTR_SHA512, + DigestOp::Blake3(_, _) => INSTR_BLAKE3, } } @@ -1309,6 +1310,7 @@ impl Bytecode for DigestOp { match self { DigestOp::Ripemd(src, dst) | DigestOp::Sha256(src, dst) + | DigestOp::Blake3(src, dst) | DigestOp::Sha512(src, dst) => { writer.write_u4(src)?; writer.write_u4(dst)?; @@ -1328,6 +1330,7 @@ impl Bytecode for DigestOp { Ok(match instr { INSTR_RIPEMD => Self::Ripemd(src, dst), INSTR_SHA256 => Self::Sha256(src, dst), + INSTR_BLAKE3 => Self::Blake3(src, dst), INSTR_SHA512 => Self::Sha512(src, dst), x => unreachable!("instruction {:#010b} classified as digest operation", x), }) diff --git a/src/isa/exec.rs b/src/isa/exec.rs index 30aec21..114af11 100644 --- a/src/isa/exec.rs +++ b/src/isa/exec.rs @@ -1372,6 +1372,7 @@ impl InstructionSet for DigestOp { match self { DigestOp::Ripemd(src, _dst) | DigestOp::Sha256(src, _dst) + | DigestOp::Blake3(src, _dst) | DigestOp::Sha512(src, _dst) => bset![Reg::S(*src)], } } @@ -1380,6 +1381,7 @@ impl InstructionSet for DigestOp { match self { DigestOp::Ripemd(_src, dst) => bset![Reg::new(RegR::R160, *dst)], DigestOp::Sha256(_src, dst) => bset![Reg::new(RegR::R256, *dst)], + DigestOp::Blake3(_src, dst) => bset![Reg::new(RegR::R256, *dst)], DigestOp::Sha512(_src, dst) => bset![Reg::new(RegR::R512, *dst)], } } @@ -1407,6 +1409,12 @@ impl InstructionSet for DigestOp { let hash: Option<[u8; 32]> = s.map(|s| sha2::Sha256::digest(s.as_ref()).into()); regs.set_n(RegR::R256, dst, hash); } + DigestOp::Blake3(src, dst) => { + let s = regs.get_s(*src); + none = s.is_none(); + let hash: Option<[u8; 32]> = s.map(|s| blake3::hash(s.as_ref()).into()); + regs.set_n(RegR::R256, dst, hash); + } DigestOp::Sha512(src, dst) => { let s = regs.get_s(*src); none = s.is_none(); diff --git a/src/isa/instr.rs b/src/isa/instr.rs index 44c3408..b627803 100644 --- a/src/isa/instr.rs +++ b/src/isa/instr.rs @@ -883,6 +883,16 @@ pub enum DigestOp { /** Index of string register */ RegS, /** Index of `r512` register to save result to */ Reg16, ), + + /// Computes BLAKE3 hash value + /// + /// Sets `st0` to `false` and destination register to `None` if the source register does not + /// contain a value + #[display("Blake3 {0},r256{1}")] + Blake3( + /** Index of string register */ RegS, + /** Index of `r256` register to save result to */ Reg16, + ), } /// Operations on Secp256k1 elliptic curve diff --git a/src/isa/macros.rs b/src/isa/macros.rs index dd544f5..05d4b0c 100644 --- a/src/isa/macros.rs +++ b/src/isa/macros.rs @@ -842,6 +842,9 @@ macro_rules! instr { (sha2 s16[$idx1:literal],r256[$idx2:literal]) => { Instr::Digest(DigestOp::Sha256(RegS::from($idx1), $crate::_reg_idx16!($idx2))) }; + (blake3 s16[$idx1:literal],r256[$idx2:literal]) => { + Instr::Digest(DigestOp::Blake3(RegS::from($idx1), $crate::_reg_idx16!($idx2))) + }; (sha2 s16[$idx1:literal],r512[$idx2:literal]) => { Instr::Digest(DigestOp::Sha512(RegS::from($idx1), $crate::_reg_idx16!($idx2))) }; diff --git a/src/isa/opcodes.rs b/src/isa/opcodes.rs index 3f293a1..75385f8 100644 --- a/src/isa/opcodes.rs +++ b/src/isa/opcodes.rs @@ -117,6 +117,7 @@ pub const INSTR_RESV_TO: u8 = 0b01_111_111; pub const INSTR_RIPEMD: u8 = 0b10_000_000; pub const INSTR_SHA256: u8 = 0b10_000_001; pub const INSTR_SHA512: u8 = 0b10_000_010; +pub const INSTR_BLAKE3: u8 = 0b10_000_100; // ### Secp256k1 operations (SECP256K1)