From faaed3b928b57202670f17028784d9d284e81b74 Mon Sep 17 00:00:00 2001 From: tp Date: Fri, 22 Jul 2022 13:25:03 +0200 Subject: [PATCH 1/2] cip14 fingerprint --- Cargo.lock | 8 ++- Cargo.toml | 2 +- src/mapper/map.rs | 1 + src/model.rs | 1 + src/utils/bech32.rs | 23 +++++++++ src/utils/cip14.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++ src/utils/mod.rs | 1 + 7 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 src/utils/cip14.rs diff --git a/Cargo.lock b/Cargo.lock index 78399703..142ced4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -702,6 +702,11 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "129eabb7b0b78644a3a7e7cf220714aba47463bb281f69fa7a71ca5d12564cca" +[[package]] +name = "cryptoxide" +version = "0.4.2" +source = "git+https://github.com/typed-io/cryptoxide.git?branch=master#f50c82e623e5a791e0f193fe68c92f526b37d290" + [[package]] name = "ct-logs" version = "0.8.0" @@ -1597,6 +1602,7 @@ dependencies = [ "cloud-pubsub", "config", "crossterm", + "cryptoxide 0.4.2 (git+https://github.com/typed-io/cryptoxide.git?branch=master)", "elasticsearch", "env_logger", "file-rotate", @@ -1662,7 +1668,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6845888ac675c4cbef6fb9d8c2b33bb05e6a3e7a7cf8e9f8e8faed1422119d" dependencies = [ - "cryptoxide", + "cryptoxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex", "pallas-codec", "rand_core", diff --git a/Cargo.toml b/Cargo.toml index acded594..19addf31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ serde_json = { version = "1.0.81", features = ["arbitrary_precision"] } strum = "0.24" strum_macros = "0.24" prometheus_exporter = { version = "0.8.4", default-features = false } - +cryptoxide = { git = "https://github.com/typed-io/cryptoxide.git", branch="master", features = ["blake2"]} # feature logs file-rotate = { version = "0.6.0", optional = true } diff --git a/src/mapper/map.rs b/src/mapper/map.rs index 25ca0f52..9309226d 100644 --- a/src/mapper/map.rs +++ b/src/mapper/map.rs @@ -210,6 +210,7 @@ impl EventWriter { asset: asset.to_hex(), asset_ascii: String::from_utf8(asset.to_vec()).ok(), amount, + fingerprint: crate::utils::cip14::cip14_fingerprint(&policy, &asset), } } diff --git a/src/model.rs b/src/model.rs index 0daeffe8..280a57e0 100644 --- a/src/model.rs +++ b/src/model.rs @@ -111,6 +111,7 @@ pub struct OutputAssetRecord { pub asset: String, pub asset_ascii: Option, pub amount: u64, + pub fingerprint : Option, } impl From for EventData { diff --git a/src/utils/bech32.rs b/src/utils/bech32.rs index 30e1bdff..6fc36466 100644 --- a/src/utils/bech32.rs +++ b/src/utils/bech32.rs @@ -20,6 +20,12 @@ impl Bech32Config { address_hrp: info.address_hrp.to_owned(), } } + + pub(crate) fn for_cip14() -> Self { + Self { + address_hrp: "asset".to_string(), + } + } } impl Default for Bech32Config { @@ -47,6 +53,22 @@ impl Bech32Provider { Ok(enc) } + + pub fn encode_cip14(&self, data: &[u8]) -> Option { + match bech32::encode( + &self.0.address_hrp, + data.to_base32(), + bech32::Variant::Bech32, + ){ + Ok(ok) => { + Some(ok) + }, + Err(e) => { + log::error!("Could not encode cip14 assetname: '{}'",e.to_string()); + None + } + } + } } #[cfg(test)] @@ -65,4 +87,5 @@ mod tests { assert_eq!(bech32, "addr1q8kx44w6a607h03sp3skpgmdfkhsc5nx4ch7sfzuhdvp8yrznq2ds9jl64rmdulk74vy9f0sg27tzylgapnz00q8rumsuhj834"); } + } diff --git a/src/utils/cip14.rs b/src/utils/cip14.rs new file mode 100644 index 00000000..8c55a8e3 --- /dev/null +++ b/src/utils/cip14.rs @@ -0,0 +1,119 @@ +//! An utility to build fingerprints for Cardano assets +use cryptoxide::{digest::Digest, blake2b::Blake2b}; +use crate::utils::bech32::{Bech32Config,Bech32Provider}; + + +pub fn blake2b160(data: &[u8]) -> [u8;20] {//Vec:: { + let mut out = [0u8; 20]; + let mut context = Blake2b::new(20); + context.input(data); + context.result(&mut out); + Blake2b::blake2b(&mut out, data, &[]); + out +} + +pub fn cip14_fingerprint(p: &Vec::, a: &Vec::) -> Option { + let data = [&p[..],&a[..]].concat(); + let hash = blake2b160(&data); + let bech32_provider = Bech32Provider::new(Bech32Config::for_cip14()); + let fingerprint = bech32_provider.encode_cip14(hash.as_slice()); + log::debug!("CIP14 Fingerprint: {:?}",fingerprint); + fingerprint +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cip14_ok_1() { + let policy = hex::decode("bb3ce45d5272654e58ad076f114d8f683ae4553e3c9455b18facfea1").unwrap(); + let assetname =hex::decode("4261627943726f63202332323237").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1et8j5whwuqrxvdyxfh4grmmrx4exeg4juzx88z"); + } + + #[test] + fn cip14_ok_2() { + let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); + let assetname =hex::decode("").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1rjklcrnsdzqp65wjgrg55sy9723kw09mlgvlc3"); + } + + #[test] + fn cip14_ok_3() { + let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc37e").unwrap(); + let assetname =hex::decode("").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1nl0puwxmhas8fawxp8nx4e2q3wekg969n2auw3"); + } + + #[test] + fn cip14_ok_4() { + let policy = hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(); + let assetname =hex::decode("").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1uyuxku60yqe57nusqzjx38aan3f2wq6s93f6ea"); + } + + #[test] + fn cip14_ok_5() { + let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); + let assetname =hex::decode("504154415445").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset13n25uv0yaf5kus35fm2k86cqy60z58d9xmde92"); + } + + #[test] + fn cip14_ok_6() { + let policy = hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(); + let assetname =hex::decode("504154415445").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1hv4p5tv2a837mzqrst04d0dcptdjmluqvdx9k3"); + } + + #[test] + fn cip14_ok_7() { + let policy = hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(); + let assetname =hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1aqrdypg669jgazruv5ah07nuyqe0wxjhe2el6f"); + } + + #[test] + fn cip14_ok_8() { + let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); + let assetname =hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset17jd78wukhtrnmjh3fngzasxm8rck0l2r4hhyyt"); + } + + #[test] + fn cip14_ok_9() { + let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); + let assetname =hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + + let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); + println!("{}",bech32); + assert_eq!(bech32, "asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w"); + + } + +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index f33b37da..fcb53427 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -28,6 +28,7 @@ pub mod throttle; pub(crate) mod bech32; pub(crate) mod retry; pub(crate) mod time; +pub(crate) mod cip14; mod facade; From ddccf212add693bf024f3d91ccba032d636ce43d Mon Sep 17 00:00:00 2001 From: tp Date: Fri, 22 Jul 2022 13:36:24 +0200 Subject: [PATCH 2/2] cleanup --- src/utils/bech32.rs | 1 - src/utils/cip14.rs | 27 ++++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/utils/bech32.rs b/src/utils/bech32.rs index 6fc36466..261fdc42 100644 --- a/src/utils/bech32.rs +++ b/src/utils/bech32.rs @@ -87,5 +87,4 @@ mod tests { assert_eq!(bech32, "addr1q8kx44w6a607h03sp3skpgmdfkhsc5nx4ch7sfzuhdvp8yrznq2ds9jl64rmdulk74vy9f0sg27tzylgapnz00q8rumsuhj834"); } - } diff --git a/src/utils/cip14.rs b/src/utils/cip14.rs index 8c55a8e3..c67004b1 100644 --- a/src/utils/cip14.rs +++ b/src/utils/cip14.rs @@ -1,9 +1,10 @@ -//! An utility to build fingerprints for Cardano assets +//! An utility to build fingerprints for Cardano assets CIP14 +//! https://cips.cardano.org/cips/cip14/ +//! use cryptoxide::{digest::Digest, blake2b::Blake2b}; use crate::utils::bech32::{Bech32Config,Bech32Provider}; - -pub fn blake2b160(data: &[u8]) -> [u8;20] {//Vec:: { +pub fn blake2b160(data: &[u8]) -> [u8;20] { let mut out = [0u8; 20]; let mut context = Blake2b::new(20); context.input(data); @@ -31,7 +32,7 @@ mod tests { let assetname =hex::decode("4261627943726f63202332323237").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1et8j5whwuqrxvdyxfh4grmmrx4exeg4juzx88z"); } @@ -41,7 +42,7 @@ mod tests { let assetname =hex::decode("").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1rjklcrnsdzqp65wjgrg55sy9723kw09mlgvlc3"); } @@ -51,7 +52,7 @@ mod tests { let assetname =hex::decode("").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1nl0puwxmhas8fawxp8nx4e2q3wekg969n2auw3"); } @@ -61,7 +62,7 @@ mod tests { let assetname =hex::decode("").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1uyuxku60yqe57nusqzjx38aan3f2wq6s93f6ea"); } @@ -71,7 +72,7 @@ mod tests { let assetname =hex::decode("504154415445").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset13n25uv0yaf5kus35fm2k86cqy60z58d9xmde92"); } @@ -81,7 +82,7 @@ mod tests { let assetname =hex::decode("504154415445").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1hv4p5tv2a837mzqrst04d0dcptdjmluqvdx9k3"); } @@ -91,7 +92,7 @@ mod tests { let assetname =hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1aqrdypg669jgazruv5ah07nuyqe0wxjhe2el6f"); } @@ -101,17 +102,17 @@ mod tests { let assetname =hex::decode("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset17jd78wukhtrnmjh3fngzasxm8rck0l2r4hhyyt"); } - + #[test] fn cip14_ok_9() { let policy = hex::decode("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373").unwrap(); let assetname =hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); let bech32 = cip14_fingerprint(&policy,&assetname).unwrap(); - println!("{}",bech32); + log::debug!("{}",bech32); assert_eq!(bech32, "asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w"); }