Skip to content

Commit

Permalink
Merge pull request #273 from Emurgo/ruslan/mint-fix
Browse files Browse the repository at this point in the history
Fixing minting API
  • Loading branch information
vsubhuman authored Jan 17, 2022
2 parents ffe663e + 3021134 commit 6a8c67a
Show file tree
Hide file tree
Showing 8 changed files with 509 additions and 122 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cardano-serialization-lib",
"version": "9.1.4",
"version": "10.0.0-beta.8",
"description": "(De)serialization functions for the Cardano blockchain along with related utility functions",
"scripts": {
"rust:build-nodejs": "(rimraf ./rust/pkg && cd rust; wasm-pack build --target=nodejs; wasm-pack pack) && npm run js:flowgen",
Expand Down
2 changes: 1 addition & 1 deletion rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cardano-serialization-lib"
version = "9.1.4"
version = "10.0.0-beta.8"
edition = "2018"
authors = ["EMURGO"]
license = "MIT"
Expand Down
40 changes: 27 additions & 13 deletions rust/pkg/cardano_serialization_lib.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -5197,31 +5197,45 @@ declare export class TransactionBuilder {
): void;

/**
* Set explicit Mint object to this builder
* it will replace any previously existing mint
* Set explicit Mint object and the required witnesses to this builder
* it will replace any previously existing mint and mint scripts
* NOTE! Error will be returned in case a mint policy does not have a matching script
* @param {Mint} mint
* @param {NativeScripts} mint_scripts
*/
set_mint(mint: Mint): void;
set_mint(mint: Mint, mint_scripts: NativeScripts): void;

/**
* Returns a copy of the current mint state in the builder
* @returns {Mint | void}
*/
get_mint(): Mint | void;

/**
* Returns a copy of the current mint witness scripts in the builder
* @returns {NativeScripts | void}
*/
get_mint_scripts(): NativeScripts | void;

/**
* Add a mint entry to this builder using a PolicyID and MintAssets object
* It will be securely added to existing or new Mint in this builder
* It will replace any existing mint assets with the same PolicyID
* @param {ScriptHash} policy_id
* @param {NativeScript} policy_script
* @param {MintAssets} mint_assets
*/
set_mint_asset(policy_id: ScriptHash, mint_assets: MintAssets): void;
set_mint_asset(policy_script: NativeScript, mint_assets: MintAssets): void;

/**
* Add a mint entry to this builder using a PolicyID, AssetName, and Int object for amount
* It will be securely added to existing or new Mint in this builder
* It will replace any previous existing amount same PolicyID and AssetName
* @param {ScriptHash} policy_id
* @param {NativeScript} policy_script
* @param {AssetName} asset_name
* @param {Int} amount
*/
add_mint_asset(
policy_id: ScriptHash,
policy_script: NativeScript,
asset_name: AssetName,
amount: Int
): void;
Expand All @@ -5231,14 +5245,14 @@ declare export class TransactionBuilder {
* Using a PolicyID, AssetName, Int for amount, Address, and Coin (BigNum) objects
* The asset will be securely added to existing or new Mint in this builder
* A new output will be added with the specified Address, the Coin value, and the minted asset
* @param {ScriptHash} policy_id
* @param {NativeScript} policy_script
* @param {AssetName} asset_name
* @param {Int} amount
* @param {Address} address
* @param {BigNum} output_coin
*/
add_mint_asset_and_output(
policy_id: ScriptHash,
policy_script: NativeScript,
asset_name: AssetName,
amount: Int,
address: Address,
Expand All @@ -5251,13 +5265,13 @@ declare export class TransactionBuilder {
* The asset will be securely added to existing or new Mint in this builder
* A new output will be added with the specified Address and the minted asset
* The output will be set to contain the minimum required amount of Coin
* @param {ScriptHash} policy_id
* @param {NativeScript} policy_script
* @param {AssetName} asset_name
* @param {Int} amount
* @param {Address} address
*/
add_mint_asset_and_output_min_required_coin(
policy_id: ScriptHash,
policy_script: NativeScript,
asset_name: AssetName,
amount: Int,
address: Address
Expand Down Expand Up @@ -5320,14 +5334,14 @@ declare export class TransactionBuilder {
/**
* Returns object the body of the new transaction
* Auxiliary data itself is not included
* You can use `get_auxiliary_date` or `build_tx`
* You can use `get_auxiliary_data` or `build_tx`
* @returns {TransactionBody}
*/
build(): TransactionBody;

/**
* Returns full Transaction object with the body and the auxiliary data
* NOTE: witness_set is set to just empty set
* NOTE: witness_set will contain all mint_scripts if any been added or set
* NOTE: is_valid set to true
* @returns {Transaction}
*/
Expand Down
125 changes: 125 additions & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use cbor_event::{
se::{Serialize, Serializer},
};

pub mod traits;
pub mod address;
pub mod chain_core;
pub mod chain_crypto;
Expand All @@ -58,6 +59,8 @@ use plutus::*;
use metadata::*;
use utils::*;
use std::cmp::Ordering;
use std::collections::BTreeSet;
use crate::traits::NoneOrEmpty;

type DeltaCoin = Int;

Expand Down Expand Up @@ -221,6 +224,7 @@ impl Certificates {
}

pub type RequiredSigners = Ed25519KeyHashes;
pub type RequiredSignersSet = BTreeSet<Ed25519KeyHash>;

#[wasm_bindgen]
#[derive(Clone)]
Expand Down Expand Up @@ -1744,6 +1748,21 @@ impl NativeScripts {
}
}

impl From<Vec<NativeScript>> for NativeScripts {
fn from(scripts: Vec<NativeScript>) -> Self {
scripts.iter().fold(NativeScripts::new(), |mut scripts, s| {
scripts.add(s);
scripts
})
}
}

impl NoneOrEmpty for NativeScripts {
fn is_none_or_empty(&self) -> bool {
self.0.is_empty()
}
}

#[wasm_bindgen]
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Update {
Expand Down Expand Up @@ -2782,6 +2801,39 @@ impl NetworkId {
}
}

impl From<&NativeScript> for RequiredSignersSet {
fn from(script: &NativeScript) -> Self {
match &script.0 {
NativeScriptEnum::ScriptPubkey(spk) => {
let mut set = BTreeSet::new();
set.insert(spk.addr_keyhash());
set
},
NativeScriptEnum::ScriptAll(all) => {
RequiredSignersSet::from(&all.native_scripts)
},
NativeScriptEnum::ScriptAny(any) => {
RequiredSignersSet::from(&any.native_scripts)
},
NativeScriptEnum::ScriptNOfK(ofk) => {
RequiredSignersSet::from(&ofk.native_scripts)
},
_ => BTreeSet::new(),
}
}
}

impl From<&NativeScripts> for RequiredSignersSet {
fn from(scripts: &NativeScripts) -> Self {
scripts.0.iter().fold(BTreeSet::new(), |mut set, s| {
RequiredSignersSet::from(s).iter().for_each(|pk| {
set.insert(pk.clone());
});
set
})
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -2963,4 +3015,77 @@ mod tests {
assert_eq!(p_ass.get(&name1).unwrap(), amount1);
assert_eq!(n_ass.get(&name1).unwrap(), amount1);
}

fn keyhash(x: u8) -> Ed25519KeyHash {
Ed25519KeyHash::from_bytes(vec![x, 180, 186, 93, 223, 42, 243, 7, 81, 98, 86, 125, 97, 69, 110, 52, 130, 243, 244, 98, 246, 13, 33, 212, 128, 168, 136, 40]).unwrap()
}

fn pkscript(pk: &Ed25519KeyHash) -> NativeScript {
NativeScript::new_script_pubkey(&ScriptPubkey::new(pk))
}

fn scripts_vec(scripts: Vec<&NativeScript>) -> NativeScripts {
NativeScripts(scripts.iter().map(|s| { (*s).clone() }).collect())
}

#[test]
fn native_scripts_get_pubkeys() {
let keyhash1 = keyhash(1);
let keyhash2 = keyhash(2);
let keyhash3 = keyhash(3);

let pks1 = RequiredSignersSet::from(&pkscript(&keyhash1));
assert_eq!(pks1.len(), 1);
assert!(pks1.contains(&keyhash1));

let pks2 = RequiredSignersSet::from(
&NativeScript::new_timelock_start(
&TimelockStart::new(123),
),
);
assert_eq!(pks2.len(), 0);

let pks3 = RequiredSignersSet::from(
&NativeScript::new_script_all(
&ScriptAll::new(&scripts_vec(vec![
&pkscript(&keyhash1),
&pkscript(&keyhash2),
]))
),
);
assert_eq!(pks3.len(), 2);
assert!(pks3.contains(&keyhash1));
assert!(pks3.contains(&keyhash2));

let pks4 = RequiredSignersSet::from(
&NativeScript::new_script_any(
&ScriptAny::new(&scripts_vec(vec![
&NativeScript::new_script_n_of_k(&ScriptNOfK::new(
1,
&scripts_vec(vec![
&NativeScript::new_timelock_start(&TimelockStart::new(132)),
&pkscript(&keyhash3),
]),
)),
&NativeScript::new_script_all(&ScriptAll::new(
&scripts_vec(vec![
&NativeScript::new_timelock_expiry(&TimelockExpiry::new(132)),
&pkscript(&keyhash1),
]),
)),
&NativeScript::new_script_any(&ScriptAny::new(
&scripts_vec(vec![
&pkscript(&keyhash1),
&pkscript(&keyhash2),
&pkscript(&keyhash3),
]),
)),
]))
),
);
assert_eq!(pks4.len(), 3);
assert!(pks4.contains(&keyhash1));
assert!(pks4.contains(&keyhash2));
assert!(pks4.contains(&keyhash3));
}
}
15 changes: 15 additions & 0 deletions rust/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pub trait NoneOrEmpty {
fn is_none_or_empty(&self) -> bool;
}

impl<T: NoneOrEmpty> NoneOrEmpty for &T {
fn is_none_or_empty(&self) -> bool {
(*self).is_none_or_empty()
}
}

impl<T: NoneOrEmpty> NoneOrEmpty for Option<T> {
fn is_none_or_empty(&self) -> bool {
self.is_none() || self.as_ref().unwrap().is_none_or_empty()
}
}
Loading

0 comments on commit 6a8c67a

Please sign in to comment.