Skip to content

Commit

Permalink
add receive_from_unbroadcasted_transfer_to_blinded test
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedberg committed Nov 24, 2024
1 parent 652630f commit ae69d03
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 8 deletions.
92 changes: 88 additions & 4 deletions tests/transfers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,13 +464,13 @@ fn same_transfer_twice() {
wlt_2.close_method(),
InvoiceType::Witness,
);
let _ = wlt_1.transfer(invoice.clone(), None, Some(500), None);
let _ = wlt_1.transfer(invoice.clone(), None, Some(500), true, None);

// retry with higher fees, TX hasn't been mined
let mid_height = get_height();
assert_eq!(initial_height, mid_height);

let _ = wlt_1.transfer(invoice, None, Some(1000), None);
let _ = wlt_1.transfer(invoice, None, Some(1000), true, None);

let final_height = get_height();
assert_eq!(initial_height, final_height);
Expand All @@ -495,7 +495,7 @@ fn accept_0conf() {
wlt_2.close_method(),
InvoiceType::Witness,
);
let (consignment, _) = wlt_1.transfer(invoice.clone(), None, None, None);
let (consignment, _) = wlt_1.transfer(invoice.clone(), None, None, true, None);

wlt_2.accept_transfer(consignment.clone(), None);

Expand Down Expand Up @@ -722,7 +722,7 @@ fn mainnet_wlt_receiving_test_asset() {
wlt_2.close_method(),
InvoiceType::Blinded(Some(utxo)),
);
let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), None);
let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), true, None);
wlt_1.mine_tx(&tx.txid(), false);
match consignment.validate(&wlt_2.get_resolver(), wlt_2.testnet()) {
Err((status, _invalid_consignment)) => {
Expand Down Expand Up @@ -896,3 +896,87 @@ fn collaborative_transfer() {
None,
);
}

#[test]
fn receive_from_unbroadcasted_transfer_to_blinded() {
initialize();

let mut wlt_1 = get_wallet(&DescriptorType::Wpkh);
let mut wlt_2 = get_wallet(&DescriptorType::Wpkh);
let mut wlt_3 = get_wallet(&DescriptorType::Wpkh);

let (contract_id, iface_type_name) = wlt_1.issue_nia(600, wlt_1.close_method(), None);

let utxo = wlt_2.get_utxo(None);
mine(false);
let invoice = wlt_2.invoice(
contract_id,
&iface_type_name,
100,
wlt_2.close_method(),
InvoiceType::Blinded(Some(utxo)),
);
// create transfer but do not broadcast its TX
let (consignment, tx) = wlt_1.transfer(invoice.clone(), None, Some(500), false, None);
let txid = tx.txid();

struct OffchainResolver<'a, 'cons, const TRANSFER: bool> {
witness_id: XWitnessId,
consignment: &'cons IndexedConsignment<'cons, TRANSFER>,
fallback: &'a AnyResolver,
}
impl<'a, 'cons, const TRANSFER: bool> ResolveWitness for OffchainResolver<'a, 'cons, TRANSFER> {
fn resolve_pub_witness(
&self,
witness_id: XWitnessId,
) -> Result<XWitnessTx, WitnessResolverError> {
self.consignment
.pub_witness(witness_id)
.and_then(|p| p.map_ref(|pw| pw.tx().cloned()).transpose())
.ok_or(WitnessResolverError::Unknown(witness_id))
.or_else(|_| self.fallback.resolve_pub_witness(witness_id))
}
fn resolve_pub_witness_ord(
&self,
witness_id: XWitnessId,
) -> Result<WitnessOrd, WitnessResolverError> {
if witness_id != self.witness_id {
return self.fallback.resolve_pub_witness_ord(witness_id);
}
Ok(WitnessOrd::Tentative)
}
}

let resolver = OffchainResolver {
witness_id: XChain::Bitcoin(txid),
consignment: &IndexedConsignment::new(&consignment),
fallback: &wlt_2.get_resolver(),
};

// wlt_2 use custom resolver to be able to send the assets even if transfer TX sending to
// blinded UTXO has not been broadcasted
wlt_2.accept_transfer_custom_resolver(consignment.clone(), None, &resolver);

let invoice = wlt_3.invoice(
contract_id,
&iface_type_name,
50,
wlt_2.close_method(),
InvoiceType::Witness,
);
let (consignment, tx) = wlt_2.transfer(invoice, Some(2000), None, true, None);
wlt_2.mine_tx(&tx.txid(), false);

// consignemnt validation fails because it notices an unbroadcasted TX in the history
let res = consignment.validate(&wlt_3.get_resolver(), wlt_3.testnet());
assert!(res.is_err());
let validation_status = match res {
Ok(validated_consignment) => validated_consignment.validation_status().clone(),
Err((status, _consignment)) => status,
};
assert_eq!(validation_status.failures.len(), 1);
assert!(matches!(
validation_status.failures[0],
Failure::SealNoPubWitness(_, _, _)
));
}
17 changes: 14 additions & 3 deletions tests/utils/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ impl TestWallet {
invoice: RgbInvoice,
sats: Option<u64>,
fee: Option<u64>,
broadcast: bool,
report: Option<&Report>,
) -> (Transfer, Tx) {
self.sync();
Expand Down Expand Up @@ -893,14 +894,24 @@ impl TestWallet {
writeln!(file, "\n---\n").unwrap();
serde_yaml::to_writer(&mut file, &psbt).unwrap();

self.broadcast_tx(&tx);
if broadcast {
self.broadcast_tx(&tx);
}

(consignment, tx)
}

pub fn accept_transfer(&mut self, consignment: Transfer, report: Option<&Report>) {
self.accept_transfer_custom_resolver(consignment, report, &self.get_resolver());
}

pub fn accept_transfer_custom_resolver(
&mut self,
consignment: Transfer,
report: Option<&Report>,
resolver: &impl ResolveWitness,
) {
self.sync();
let resolver = self.get_resolver();
let validate_start = Instant::now();
let validated_consignment = consignment
.validate(&resolver, self.testnet())
Expand Down Expand Up @@ -1100,7 +1111,7 @@ impl TestWallet {
fee: Option<u64>,
report: Option<&Report>,
) -> (Transfer, Tx) {
let (consignment, tx) = self.transfer(invoice, sats, fee, report);
let (consignment, tx) = self.transfer(invoice, sats, fee, true, report);
self.mine_tx(&tx.txid(), false);
recv_wlt.accept_transfer(consignment.clone(), report);
self.sync();
Expand Down
5 changes: 4 additions & 1 deletion tests/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ pub use rgb::{
RgbWallet, TapretKey, TransferParams, Transition, WalletProvider, XOutpoint, XWitnessId,
};
pub use rgbstd::{
containers::{BuilderSeal, ConsignmentExt, Fascia, FileContent, Kit, Transfer, ValidKit},
containers::{
BuilderSeal, ConsignmentExt, Fascia, FileContent, IndexedConsignment, Kit, Transfer,
ValidKit,
},
interface::{
ContractBuilder, ContractIface, DataAllocation, FilterExclude, FungibleAllocation, Iface,
IfaceClass, IfaceId, IfaceImpl, NamedField,
Expand Down

0 comments on commit ae69d03

Please sign in to comment.