mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
Add mina library with poseidon
This commit is contained in:
parent
e5eb32acee
commit
37b5a40ab8
5 changed files with 1353 additions and 0 deletions
1182
mina/Cargo.lock
generated
Normal file
1182
mina/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
17
mina/Cargo.toml
Normal file
17
mina/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "mina"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
mina-hasher = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
mina-signer = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
o1-utils = { git = "https://github.com/o1-labs/proof-systems", tag = "0.1.0", version = "0.1.0" }
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.24.3"
|
||||
35
mina/build.rs
Normal file
35
mina/build.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
extern crate cbindgen;
|
||||
|
||||
use cbindgen::Config;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
let package_name = env::var("CARGO_PKG_NAME").unwrap();
|
||||
let output_file = target_dir()
|
||||
.join(format!("{}.h", package_name))
|
||||
.display()
|
||||
.to_string();
|
||||
|
||||
let config = Config {
|
||||
language: cbindgen::Language::C,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
cbindgen::generate_with_config(&crate_dir, config)
|
||||
.unwrap()
|
||||
.write_to_file(&output_file);
|
||||
}
|
||||
|
||||
/// Find the location of the `target/` directory. Note that this may be
|
||||
/// overridden by `cmake`, so we also need to check the `CARGO_TARGET_DIR`
|
||||
/// variable.
|
||||
fn target_dir() -> PathBuf {
|
||||
if let Ok(target) = env::var("CARGO_TARGET_DIR") {
|
||||
PathBuf::from(target)
|
||||
} else {
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("target")
|
||||
}
|
||||
}
|
||||
56
mina/src/lib.rs
Normal file
56
mina/src/lib.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
mod mina;
|
||||
|
||||
use std::array::TryFromSliceError;
|
||||
|
||||
use mina::{Message, NetworkId};
|
||||
use mina_signer::{BaseField, CurvePoint, PubKey, Signature, ScalarField};
|
||||
use o1_utils::FieldHelpers;
|
||||
|
||||
pub const FIELD_SIZE: usize = 32;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn poseidon_hash(
|
||||
network_id: u8,
|
||||
field_ptr: *const u8,
|
||||
field_len: usize,
|
||||
output_ptr: *mut u8, // 32 bytes
|
||||
) -> bool {
|
||||
let network_id = match network_id {
|
||||
0x00 => NetworkId::TESTNET,
|
||||
0x01 => NetworkId::MAINNET,
|
||||
0xff => NetworkId::NULLNET,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let fields = unsafe { std::slice::from_raw_parts(field_ptr, field_len * FIELD_SIZE) };
|
||||
|
||||
let fields = match fields
|
||||
.chunks(FIELD_SIZE)
|
||||
.map(|chunk| chunk[..32].try_into())
|
||||
.collect::<Result<Vec<[u8; 32]>, TryFromSliceError>>()
|
||||
{
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let msg = match Message::from_bytes_slice(&fields) {
|
||||
Ok(msg) => msg,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
let hash = mina::poseidon(&msg, network_id);
|
||||
|
||||
let output = unsafe { std::slice::from_raw_parts_mut(output_ptr, FIELD_SIZE) };
|
||||
|
||||
output.copy_from_slice(&hash.to_bytes());
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {}
|
||||
}
|
||||
63
mina/src/mina.rs
Normal file
63
mina/src/mina.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use mina_hasher::{DomainParameter, Hashable, Hasher, ROInput};
|
||||
use mina_signer::{BaseField, PubKey, Signer, Signature};
|
||||
use o1_utils::{field_helpers::FieldHelpersError, FieldHelpers};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum NetworkId {
|
||||
TESTNET = 0x00,
|
||||
MAINNET = 0x01,
|
||||
NULLNET = 0xff,
|
||||
}
|
||||
|
||||
impl From<NetworkId> for u8 {
|
||||
fn from(id: NetworkId) -> u8 {
|
||||
id as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl DomainParameter for NetworkId {
|
||||
fn into_bytes(self) -> Vec<u8> {
|
||||
vec![self as u8]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Message {
|
||||
fields: Vec<BaseField>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn from_bytes_slice(fields_bytes: &[[u8; 32]]) -> Result<Self, FieldHelpersError> {
|
||||
Ok(Self {
|
||||
fields: fields_bytes
|
||||
.iter()
|
||||
.map(|bytes| BaseField::from_bytes(bytes))
|
||||
.collect::<Result<Vec<BaseField>, FieldHelpersError>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Hashable for Message {
|
||||
type D = NetworkId;
|
||||
|
||||
fn to_roinput(&self) -> ROInput {
|
||||
self.fields
|
||||
.iter()
|
||||
.fold(ROInput::new(), |roi, field| roi.append_field(*field))
|
||||
}
|
||||
|
||||
fn domain_string(network_id: NetworkId) -> Option<String> {
|
||||
match network_id {
|
||||
NetworkId::MAINNET => "MinaSignatureMainnet".to_string().into(),
|
||||
NetworkId::TESTNET => "CodaSignature".to_string().into(),
|
||||
NetworkId::NULLNET => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poseidon(msg: &Message, network_id: NetworkId) -> BaseField {
|
||||
let mut hasher = mina_hasher::create_kimchi::<Message>(network_id);
|
||||
|
||||
hasher.hash(msg)
|
||||
}
|
||||
Loading…
Reference in a new issue