From 163e411c9094c6f7f78b5eb2869829cf0ebf3122 Mon Sep 17 00:00:00 2001 From: Mat Date: Wed, 10 Jan 2024 13:46:20 -0700 Subject: [PATCH] Add fish_hash library and bindings --- Cargo.lock | 20 ++++++++++ ironfish-rust-nodejs/Cargo.toml | 3 +- ironfish-rust-nodejs/index.d.ts | 5 +++ ironfish-rust-nodejs/index.js | 3 +- ironfish-rust-nodejs/src/fish_hash.rs | 37 +++++++++++++++++++ ironfish-rust-nodejs/src/lib.rs | 1 + .../tests/fish_hash.test.slow.ts | 20 ++++++++++ 7 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 ironfish-rust-nodejs/src/fish_hash.rs create mode 100644 ironfish-rust-nodejs/tests/fish_hash.test.slow.ts diff --git a/Cargo.lock b/Cargo.lock index 46585ef016..5a46a74b88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1027,6 +1027,16 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93ace6ec7cc19c8ed33a32eaa9ea692d7faea05006b5356b9e2b668ec4bc3955" +[[package]] +name = "fish_hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9577244a17c8bd562cbfd4b86dead29d8b3f6cb779d1f7be4bc8a2c9b62028dc" +dependencies = [ + "blake3", + "tiny-keccak", +] + [[package]] name = "flume" version = "0.10.14" @@ -1564,6 +1574,7 @@ name = "ironfish-rust-nodejs" version = "0.1.0" dependencies = [ "base64 0.13.1", + "fish_hash", "ironfish", "ironfish_mpc", "napi", @@ -2820,6 +2831,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/ironfish-rust-nodejs/Cargo.toml b/ironfish-rust-nodejs/Cargo.toml index 169c090a9c..a3907ac565 100644 --- a/ironfish-rust-nodejs/Cargo.toml +++ b/ironfish-rust-nodejs/Cargo.toml @@ -27,10 +27,11 @@ crate-type = ["cdylib"] [dependencies] base64 = "0.13.0" +fish_hash = "0.1.0" ironfish = { path = "../ironfish-rust" } +ironfish_mpc = { path = "../ironfish-mpc" } napi = { version = "2.13.2", features = ["napi6"] } napi-derive = "2.13.0" -ironfish_mpc = { path = "../ironfish-mpc" } [build-dependencies] napi-build = "2.0.1" diff --git a/ironfish-rust-nodejs/index.d.ts b/ironfish-rust-nodejs/index.d.ts index ffb481a73b..c514d827d4 100644 --- a/ironfish-rust-nodejs/index.d.ts +++ b/ironfish-rust-nodejs/index.d.ts @@ -82,6 +82,11 @@ export function wordsToSpendingKey(words: string, languageCode: LanguageCode): s export function generateKeyFromPrivateKey(privateKey: string): Key export function initializeSapling(): void export function isValidPublicAddress(hexAddress: string): boolean +export class FishHashContext { + constructor(full: boolean) + prebuildDataset(threads: number): void + hash(header: Buffer): Buffer +} export class BoxKeyPair { constructor() static fromHex(secretHex: string): BoxKeyPair diff --git a/ironfish-rust-nodejs/index.js b/ironfish-rust-nodejs/index.js index 7e2c0651ac..5b2524eb0b 100644 --- a/ironfish-rust-nodejs/index.js +++ b/ironfish-rust-nodejs/index.js @@ -252,8 +252,9 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { contribute, verifyTransform, KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, initSignalHandler, triggerSegfault, ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, PROOF_LENGTH, TRANSACTION_SIGNATURE_LENGTH, TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH, TRANSACTION_EXPIRATION_LENGTH, TRANSACTION_FEE_LENGTH, LATEST_TRANSACTION_VERSION, TransactionPosted, Transaction, verifyTransactions, LanguageCode, generateKey, spendingKeyToWords, wordsToSpendingKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding +const { FishHashContext, contribute, verifyTransform, KEY_LENGTH, NONCE_LENGTH, BoxKeyPair, randomBytes, boxMessage, unboxMessage, RollingFilter, initSignalHandler, triggerSegfault, ASSET_ID_LENGTH, ASSET_METADATA_LENGTH, ASSET_NAME_LENGTH, ASSET_LENGTH, Asset, NOTE_ENCRYPTION_KEY_LENGTH, MAC_LENGTH, ENCRYPTED_NOTE_PLAINTEXT_LENGTH, ENCRYPTED_NOTE_LENGTH, NoteEncrypted, PUBLIC_ADDRESS_LENGTH, RANDOMNESS_LENGTH, MEMO_LENGTH, AMOUNT_VALUE_LENGTH, DECRYPTED_NOTE_LENGTH, Note, PROOF_LENGTH, TRANSACTION_SIGNATURE_LENGTH, TRANSACTION_PUBLIC_KEY_RANDOMNESS_LENGTH, TRANSACTION_EXPIRATION_LENGTH, TRANSACTION_FEE_LENGTH, LATEST_TRANSACTION_VERSION, TransactionPosted, Transaction, verifyTransactions, LanguageCode, generateKey, spendingKeyToWords, wordsToSpendingKey, generateKeyFromPrivateKey, initializeSapling, FoundBlockResult, ThreadPoolHandler, isValidPublicAddress } = nativeBinding +module.exports.FishHashContext = FishHashContext module.exports.contribute = contribute module.exports.verifyTransform = verifyTransform module.exports.KEY_LENGTH = KEY_LENGTH diff --git a/ironfish-rust-nodejs/src/fish_hash.rs b/ironfish-rust-nodejs/src/fish_hash.rs new file mode 100644 index 0000000000..bf6c882a6b --- /dev/null +++ b/ironfish-rust-nodejs/src/fish_hash.rs @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use fish_hash::Context; +use napi::{bindgen_prelude::Buffer, JsBuffer}; +use napi_derive::napi; + +#[napi] +pub struct FishHashContext { + inner: Context, +} + +#[napi] +impl FishHashContext { + #[napi(constructor)] + pub fn new(full: bool) -> Self { + Self { + inner: Context::new(full), + } + } + + #[napi] + pub fn prebuild_dataset(&mut self, threads: u32) { + self.inner.prebuild_dataset(threads as usize) + } + + #[napi] + pub fn hash(&mut self, header: JsBuffer) -> Buffer { + let bytes = header.into_value().unwrap(); + + let mut output = [0u8; 32]; + fish_hash::hash(&mut output, &mut self.inner, bytes.as_ref()); + + Buffer::from(output.to_vec()) + } +} diff --git a/ironfish-rust-nodejs/src/lib.rs b/ironfish-rust-nodejs/src/lib.rs index 7d9458a143..bfb186e9a3 100644 --- a/ironfish-rust-nodejs/src/lib.rs +++ b/ironfish-rust-nodejs/src/lib.rs @@ -13,6 +13,7 @@ use napi_derive::napi; use ironfish::mining; use ironfish::sapling_bls12; +pub mod fish_hash; pub mod mpc; pub mod nacl; pub mod rolling_filter; diff --git a/ironfish-rust-nodejs/tests/fish_hash.test.slow.ts b/ironfish-rust-nodejs/tests/fish_hash.test.slow.ts new file mode 100644 index 0000000000..905bfbc259 --- /dev/null +++ b/ironfish-rust-nodejs/tests/fish_hash.test.slow.ts @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import { FishHashContext } from '..' + +describe('FishHashContext', () => { + it('should be able to generate a new FishHash context', () => { + const context = new FishHashContext(false) + expect(context).toBeDefined() + }) + + it('should be able to hash a buffer', () => { + let data = Buffer.from('the quick brown fox jumps over the lazy dog') + const context = new FishHashContext(false) + + const hash = context.hash(data) + expect(hash.toString('hex')).toEqual('6f4429716dc009d5d3b9775a4d6a5d58bccd9f73386bf88da7d5afdf5deb50f1') + }) +})