Skip to content

Commit

Permalink
Add elip_liquidex module
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoComandini committed Jul 29, 2024
1 parent 2ca6c7b commit 7737c82
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
113 changes: 113 additions & 0 deletions src/pset/elip_liquidex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//!
//! An implementation of ELIP0XXX as defined in
//! <https://github.com/ElementsProject/ELIPs/blob/main/elip-0XXX.mediawiki>
//!
//! ELIP0XXX defines how to encode the extra data for LiquiDEX in a PSET.
//!

use crate::pset::{
confidential::AssetBlindingFactor,
encode,
raw::ProprietaryKey,
serialize::{Deserialize, Serialize},
Input, Output,
};

/// Input Asset Blinding Factor keytype as defined in ELIP0XXX
pub const PSBT_ELEMENTS_LIQUIDEX_IN_ABF: u8 = 0x00u8;

/// Output Asset Blinding Factor keytype as defined in ELIP0XXX
pub const PSBT_ELEMENTS_LIQUIDEX_OUT_ABF: u8 = 0x00u8;

/// Prefix for PSET LiquiDEX extension as defined in ELIP0XXX
pub const PSET_LIQUIDEX_PREFIX: &[u8] = b"pset_liquidex";

fn prop_key(keytype: u8) -> ProprietaryKey {
ProprietaryKey {
prefix: PSET_LIQUIDEX_PREFIX.to_vec(),
subtype: keytype,
key: vec![],
}
}

/// ELIP0XXX LiquiDEX extensions
impl Input {
/// Set Asset Blinding Factor
pub fn set_abf(&mut self, abf: AssetBlindingFactor) {
let key = prop_key(PSBT_ELEMENTS_LIQUIDEX_IN_ABF);
self.proprietary.insert(key, abf.serialize());
}

/// Get Asset Blinding Factor
pub fn get_abf(&self) -> Option<Result<AssetBlindingFactor, encode::Error>> {
let key = prop_key(PSBT_ELEMENTS_LIQUIDEX_IN_ABF);
self.proprietary
.get(&key)
.map(|data| AssetBlindingFactor::deserialize(data))
}
}

/// ELIP0XXX LiquiDEX extensions
impl Output {
/// Set Asset Blinding Factor
pub fn set_abf(&mut self, abf: AssetBlindingFactor) {
let key = prop_key(PSBT_ELEMENTS_LIQUIDEX_OUT_ABF);
self.proprietary.insert(key, abf.serialize());
}

/// Get Asset Blinding Factor
pub fn get_abf(&self) -> Option<Result<AssetBlindingFactor, encode::Error>> {
let key = prop_key(PSBT_ELEMENTS_LIQUIDEX_OUT_ABF);
self.proprietary
.get(&key)
.map(|data| AssetBlindingFactor::deserialize(data))
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::encode::{serialize_hex, Encodable};
use crate::hex::{FromHex, ToHex};

// b'\xfc\rpset_liquidex'
const ELIP0XXX_IDENTIFIER: &str = "fc0d707365745f6c69717569646578";

#[test]
fn prop_key_serialize() {
let key = prop_key(PSBT_ELEMENTS_LIQUIDEX_IN_ABF);
let mut vec = vec![];
key.consensus_encode(&mut vec).unwrap();

assert_eq!(
vec.to_hex(),
format!("0d{}00", PSET_LIQUIDEX_PREFIX.to_hex())
);

assert!(vec.to_hex().starts_with(&ELIP0XXX_IDENTIFIER[2..])); // cut proprietary prefix "fc"
}

#[test]
fn set_get_abf() {
// An ABF that's different if serialized in reverse or not
let abf_hex = "3311111111111111111111111111111111111111111111111111111111111111";
let abf_bytes = Vec::<u8>::from_hex(abf_hex).unwrap();
let abf = AssetBlindingFactor::from_slice(&abf_bytes).unwrap();

let mut input = Input::default();
assert!(input.get_abf().is_none());
input.set_abf(abf);
assert_eq!(input.get_abf().unwrap().unwrap(), abf);
let input_hex = serialize_hex(&input);
assert!(input_hex.contains(ELIP0XXX_IDENTIFIER));
assert!(input_hex.contains(abf_hex));

let mut output = Output::default();
assert!(output.get_abf().is_none());
output.set_abf(abf);
assert_eq!(output.get_abf().unwrap().unwrap(), abf);
let output_hex = serialize_hex(&output);
assert!(output_hex.contains(ELIP0XXX_IDENTIFIER));
assert!(output_hex.contains(abf_hex));
}
}
1 change: 1 addition & 0 deletions src/pset/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod map;
pub mod raw;
pub mod serialize;
pub mod elip100;
pub mod elip_liquidex;

#[cfg(feature = "base64")]
mod str;
Expand Down

0 comments on commit 7737c82

Please sign in to comment.