Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ multiple_crate_versions = "allow"
[workspace.dependencies]
ring = "0.17.14"
hex = "0.4.3"
smplx-std = "0.0.4"
simplex = { git = "https://github.com/BlockstreamResearch/smplx.git", rev = "6a6bef4d8b14aa7bdfdfb35ef2174cc6a370ad45", package = "smplx-std" }
sha2 = { version = "0.10.9", features = ["compress"] }
serde = { version = "1.0.228", features = ["derive"]}
thiserror = { version = "2.0.18" }
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ workspace = true
thiserror = { workspace = true }
hex = { workspace = true }
serde = { workspace = true }
smplx-std = { workspace = true }
simplex = { workspace = true }

anyhow = "1"
dotenvy = "0.15"
Expand Down
22 changes: 11 additions & 11 deletions crates/cli/src/commands/utility/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ impl Utility {

let mut ft = FinalTransaction::new();

let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(first_utxo.clone()),
IssuanceInput::new(asset_amount, asset_entropy),
IssuanceInput::new_issuance(asset_amount, 0, asset_entropy),
RequiredSignature::NativeEcdsa,
);

Expand All @@ -100,12 +100,12 @@ impl Utility {
ft.add_output(PartialOutput::new(
signer_script_pubkey.clone(),
asset_amount,
asset_id,
issuance_details.asset_id,
));

println!(
"Issuing new asset with id - {} and amount - {}",
asset_id.to_hex(),
issuance_details.asset_id.to_hex(),
asset_amount,
);

Expand Down Expand Up @@ -133,23 +133,23 @@ impl Utility {
let total_asset_amount = PREPARATION_UTXO_ASSET_AMOUNT * UTILITY_NFTS_COUNT as u64;
let asset_entropy = get_random_seed();

let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(issuance_utxo.clone()),
IssuanceInput::new(total_asset_amount, asset_entropy),
IssuanceInput::new_issuance(total_asset_amount, 0, asset_entropy),
RequiredSignature::NativeEcdsa,
);

for _ in 0..UTILITY_NFTS_COUNT {
ft.add_output(PartialOutput::new(
signer_script_pubkey.clone(),
PREPARATION_UTXO_ASSET_AMOUNT,
asset_id,
issuance_details.asset_id,
));
}

println!(
"Issuing preparation UTXOs with the {} asset id...",
asset_id.to_hex()
issuance_details.asset_id.to_hex()
);

let (tx, _) = context.signer.finalize(&ft)?;
Expand Down Expand Up @@ -193,12 +193,12 @@ impl Utility {
let issuance_asset_entropy = get_random_seed();

for (index, utxo) in issuance_utxos.iter().enumerate() {
let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(utxo.clone()),
IssuanceInput::new(utility_nfts_amounts[index], issuance_asset_entropy),
IssuanceInput::new_issuance(utility_nfts_amounts[index], 0, issuance_asset_entropy),
RequiredSignature::NativeEcdsa,
);
asset_ids.push(asset_id);
asset_ids.push(issuance_details.asset_id);
}

for (index, asset_id) in asset_ids.into_iter().enumerate() {
Expand Down
2 changes: 1 addition & 1 deletion crates/contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ hex = { workspace = true }
thiserror = { workspace = true }
modular-bitfield = { workspace = true }

smplx-std = { workspace = true }
simplex = { workspace = true }

[dev-dependencies]
anyhow = "1"
Expand Down
32 changes: 21 additions & 11 deletions crates/contracts/simf/issuance_factory.simf
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ fn check_flags_eq(flag_1: bool, flag_2: bool) {
assert!(jet::eq_1(<bool>::into(flag_1), <bool>::into(flag_2)));
}

fn ensure_non_zero_amount(amount: u64) {
assert!(jet::some_64(amount));
}

fn ensure_asset_with_amount(index: u32, is_input_index: bool, expected_asset_bits: u256, expected_amount: u64) {
let (asset_bits, amount): (u256, u64) = get_asset_and_amount(index, is_input_index);

Expand Down Expand Up @@ -69,6 +73,14 @@ fn ensure_output_is_op_return(index: u32) {

fn ensure_zero_bit(bit: bool) { assert!(jet::eq_1(<bool>::into(bit), 0)); }

// Math helpers

fn safe_add_32(first: u32, second: u32) -> u32 {
let (carry, result): (bool, u32) = jet::add_32(first, second);

result
}

// Main paths logic

fn get_reissuance_flag(index: u8) -> bool {
Expand All @@ -83,15 +95,16 @@ fn verify_issuance(input_index: u32, output_index: u32, reissuance_flag: bool) {
let outpoint: Outpoint = unwrap(jet::input_prev_outpoint(input_index));
let issuance_entropy: u256 = jet::calculate_issuance_entropy(outpoint, contract_hash);

let has_reissuance: bool = unwrap(unwrap(jet::issuance(input_index)));

assert!(jet::eq_1(<bool>::into(has_reissuance), <bool>::into(reissuance_flag)));
let explicit_reissuance_tokens_amount: u64 = unwrap_right::<(u1, u256)>(unwrap(unwrap(jet::issuance_token_amount(input_index))));

match has_reissuance {
match reissuance_flag {
// TODO: Add confidential reissuance tokens verification
true => {
let conf_token: ExplicitAsset = jet::calculate_confidential_token(issuance_entropy);
ensure_non_zero_amount(explicit_reissuance_tokens_amount);
},
false => {
check_asset_amounts_eq(explicit_reissuance_tokens_amount, 0);
},
false => {},
};

let issuance_amount: Amount1 = unwrap(unwrap(jet::issuance_asset_amount(input_index)));
Expand All @@ -108,11 +121,8 @@ fn verify_issuance_step(acc: (), start_output_index: u32, i: u8) -> Either<(), (
false => {
let step_index: u32 = <(u16, u16)>::into((0, <(u8, u8)>::into((0, i))));

let (carry, input_index): (bool, u32) = jet::add_32(jet::current_index(), step_index);
ensure_zero_bit(carry);

let (carry, output_index): (bool, u32) = jet::add_32(start_output_index, step_index);
ensure_zero_bit(carry);
let input_index: u32 = safe_add_32(jet::current_index(), step_index);
let output_index: u32 = safe_add_32(start_output_index, step_index);

verify_issuance(input_index, output_index, get_reissuance_flag(i));

Expand Down
12 changes: 8 additions & 4 deletions crates/contracts/src/programs/issuance_factory/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use simplex::provider::ProviderTrait;
use simplex::simplicityhl::elements::{AssetId, Script, Transaction};
use simplex::simplicityhl::elements::{hex::ToHex, schnorr::XOnlyPublicKey};
use simplex::transaction::partial_input::IssuanceInput;
use simplex::transaction::{FinalTransaction, PartialOutput, RequiredSignature, UTXO};
use simplex::transaction::{
FinalTransaction, IssuanceDetails, PartialOutput, RequiredSignature, UTXO,
};
use simplex::{program::Program, provider::SimplicityNetwork};

use crate::artifacts::issuance_factory::IssuanceFactoryProgram;
Expand All @@ -16,7 +18,7 @@ pub struct IssuanceFactory {
parameters: IssuanceFactoryParameters,
}

// TODO: encode constants to the factory asset amount
// TODO: encode constants to the factory asset amount or creation OP_RETURN
pub const PRE_LOCK_ISSUING_UTXOS_COUNT: u8 = 2;
pub const PRE_LOCK_REISSUANCE_FLAGS: u64 = 0;
pub const ISSUANCE_FACTORY_CREATION_OP_RETURN_DATA_LENGTH: usize = 32;
Expand Down Expand Up @@ -113,7 +115,7 @@ impl IssuanceFactory {
ft: &mut FinalTransaction,
program_utxo: UTXO,
program_issuance_input: IssuanceInput,
) {
) -> IssuanceDetails {
let issuance_factory_amount = program_utxo.explicit_amount();
let issuance_factory_asset = program_utxo.explicit_asset();

Expand All @@ -123,7 +125,7 @@ impl IssuanceFactory {
output_index: issuance_factory_output_index,
};

self.add_program_issuance_input_with_signature(
let issuance_details = self.add_program_issuance_input_with_signature(
ft,
program_utxo,
program_issuance_input,
Expand All @@ -132,6 +134,8 @@ impl IssuanceFactory {
);

self.add_program_output(ft, issuance_factory_asset, issuance_factory_amount);

issuance_details
}

pub fn attach_factory_removing(&self, ft: &mut FinalTransaction, program_utxo: UTXO) {
Expand Down
11 changes: 5 additions & 6 deletions crates/contracts/src/programs/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use simplex::program::{Program, WitnessTrait};
use simplex::provider::SimplicityNetwork;
use simplex::transaction::partial_input::IssuanceInput;
use simplex::transaction::{
FinalTransaction, PartialInput, PartialOutput, ProgramInput, RequiredSignature, UTXO,
FinalTransaction, IssuanceDetails, PartialInput, PartialOutput, ProgramInput,
RequiredSignature, UTXO,
};

use simplex::simplicityhl::elements::{AssetId, Script};
Expand Down Expand Up @@ -61,15 +62,13 @@ pub trait SimplexProgram {
issuance_input: IssuanceInput,
witness: Box<dyn WitnessTrait>,
required_signature: RequiredSignature,
) -> AssetId {
let (asset_id, _) = ft.add_program_issuance_input(
) -> IssuanceDetails {
ft.add_program_issuance_input(
PartialInput::new(program_utxo),
ProgramInput::new(Box::new(self.get_program().clone()), witness),
issuance_input,
required_signature,
);

asset_id
)
}

fn add_program_output<'a>(
Expand Down
5 changes: 2 additions & 3 deletions crates/contracts/tests/asset_auth/unlock_failure_flows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,9 @@ fn fails_to_unlock_when_auth_input_amount_is_invalid(
auth_utxo.explicit_asset(),
));

// TODO: Update Simplex to write more fail test cases
// let result = signer.finalize(&ft);
let result = signer.finalize(&ft);

// assert!(result.is_err(), "Must fail but it does not");
assert!(result.is_err(), "Must fail but it does not");

Ok(())
}
22 changes: 11 additions & 11 deletions crates/contracts/tests/common/issuance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ pub fn issue_asset(

let asset_entropy = get_random_seed();

let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(first_utxo.clone()),
IssuanceInput::new(asset_amount, asset_entropy),
IssuanceInput::new_issuance(asset_amount, 0, asset_entropy),
RequiredSignature::NativeEcdsa,
);

Expand All @@ -34,7 +34,7 @@ pub fn issue_asset(
ft.add_output(PartialOutput::new(
signer_script_pubkey.clone(),
asset_amount,
asset_id,
issuance_details.asset_id,
));

ft.add_output(PartialOutput::new(
Expand All @@ -45,7 +45,7 @@ pub fn issue_asset(

let txid = finalize_and_broadcast(context, &ft)?;

Ok((txid, asset_id))
Ok((txid, issuance_details.asset_id))
}

pub fn issue_preparation_utxos_tx(
Expand All @@ -60,17 +60,17 @@ pub fn issue_preparation_utxos_tx(
let total_asset_amount = PREPARATION_UTXO_ASSET_AMOUNT * UTILITY_NFTS_COUNT as u64;
let asset_entropy = get_random_seed();

let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(first_utxo.clone()),
IssuanceInput::new(total_asset_amount, asset_entropy),
IssuanceInput::new_issuance(total_asset_amount, 0, asset_entropy),
RequiredSignature::NativeEcdsa,
);

for _ in 0..UTILITY_NFTS_COUNT {
ft.add_output(PartialOutput::new(
signer.get_address().script_pubkey(),
PREPARATION_UTXO_ASSET_AMOUNT,
asset_id,
issuance_details.asset_id,
));
}

Expand All @@ -84,7 +84,7 @@ pub fn issue_preparation_utxos_tx(

let txid = finalize_and_broadcast(context, &ft)?;

Ok((txid, asset_id))
Ok((txid, issuance_details.asset_id))
}

pub fn issue_utility_nfts_tx(
Expand Down Expand Up @@ -115,12 +115,12 @@ pub fn issue_utility_nfts_tx(
let issuance_asset_entropy = get_random_seed();

for (index, utxo) in issuance_utxos.iter().enumerate() {
let (asset_id, _) = ft.add_issuance_input(
let issuance_details = ft.add_issuance_input(
PartialInput::new(utxo.clone()),
IssuanceInput::new(utility_nfts_amounts[index], issuance_asset_entropy),
IssuanceInput::new_issuance(utility_nfts_amounts[index], 0, issuance_asset_entropy),
RequiredSignature::NativeEcdsa,
);
asset_ids.push(asset_id);
asset_ids.push(issuance_details.asset_id);
}

for (index, asset_id) in asset_ids.into_iter().enumerate() {
Expand Down
2 changes: 2 additions & 0 deletions crates/contracts/tests/issuance_factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[path = "issuance_factory/mod.rs"]
mod issuance_factory_tests;
Loading
Loading