diff --git a/pdk-python/src/pdkpython/libpdk_ffi.dylib b/pdk-python/src/pdkpython/libpdk_ffi.dylib index e998025..272f862 100755 Binary files a/pdk-python/src/pdkpython/libpdk_ffi.dylib and b/pdk-python/src/pdkpython/libpdk_ffi.dylib differ diff --git a/pdk-python/src/pdkpython/pdk_ffi.py b/pdk-python/src/pdkpython/pdk_ffi.py index c48410a..6349141 100644 --- a/pdk-python/src/pdkpython/pdk_ffi.py +++ b/pdk-python/src/pdkpython/pdk_ffi.py @@ -3028,7 +3028,7 @@ def write(cls, cb, buf): # Declaration and FfiConverters for CanBroadcast Callback Interface class CanBroadcast: - def test_mempool_accept(self, tx_hex: "typing.List[str]"): + def test_mempool_accept(self, tx: "typing.List[int]"): raise NotImplementedError @@ -3037,7 +3037,7 @@ def py_foreignCallbackCallbackInterfaceCanBroadcast(handle, method, args_data, a def invoke_test_mempool_accept(python_callback, args_stream, buf_ptr): def makeCall():return python_callback.test_mempool_accept( - FfiConverterSequenceString.read(args_stream) + FfiConverterSequenceUInt8.read(args_stream) ) def makeCallAndHandleReturn(): @@ -3349,26 +3349,6 @@ def read(cls, buf): -class FfiConverterSequenceString(FfiConverterRustBuffer): - @classmethod - def write(cls, value, buf): - items = len(value) - buf.writeI32(items) - for item in value: - FfiConverterString.write(item, buf) - - @classmethod - def read(cls, buf): - count = buf.readI32() - if count < 0: - raise InternalError("Unexpected negative sequence length") - - return [ - FfiConverterString.read(buf) for i in range(count) - ] - - - class FfiConverterMapUInt64TypeOutPoint(FfiConverterRustBuffer): @classmethod def write(cls, items, buf): diff --git a/src/pdk_ffi.udl b/src/pdk_ffi.udl index 4ef9800..2372db5 100644 --- a/src/pdk_ffi.udl +++ b/src/pdk_ffi.udl @@ -132,7 +132,7 @@ interface Transaction{ callback interface CanBroadcast { [Throws=PayjoinError] - boolean test_mempool_accept(sequence tx_hex); + boolean test_mempool_accept( sequence tx ); }; interface UncheckedProposal{ diff --git a/src/receive.rs b/src/receive.rs index f7f82dd..384776a 100644 --- a/src/receive.rs +++ b/src/receive.rs @@ -1,20 +1,22 @@ -use crate::{ - transaction::{PartiallySignedTransaction, Transaction}, - Address, OutPoint, PayjoinError, ScriptBuf, TxOut, +use std::{ + collections::HashMap, + sync::{Arc, Mutex, MutexGuard}, }; + use payjoin::receive::{ MaybeInputsOwned as PdkMaybeInputsOwned, MaybeInputsSeen as PdkMaybeInputsSeen, MaybeMixedInputScripts as PdkMaybeMixedInputScripts, OutputsUnknown as PdkOutputsUnknown, PayjoinProposal as PdkPayjoinProposal, UncheckedProposal as PdkUncheckedProposal, }; use payjoin::Error as PdkError; -use std::{ - collections::HashMap, - sync::{Arc, Mutex, MutexGuard}, + +use crate::{ + transaction::{PartiallySignedTransaction, Transaction}, + Address, OutPoint, PayjoinError, ScriptBuf, TxOut, }; pub trait CanBroadcast: Send + Sync { - fn test_mempool_accept(&self, tx_hex: Vec) -> Result; + fn test_mempool_accept(&self, tx: Vec) -> Result; } #[derive(Clone)] @@ -37,6 +39,7 @@ impl payjoin::receive::Headers for Headers { self.0.get(key).map(|e| e.as_str()) } } + /// The sender’s original PSBT and optional parameters /// /// This type is used to proces the request. It is returned by UncheckedProposal::from_request(). @@ -51,6 +54,7 @@ impl From for UncheckedProposal { Self { internal: Mutex::new(Some(value)) } } } + impl UncheckedProposal { pub fn get_configuration( &self, @@ -96,9 +100,9 @@ impl UncheckedProposal { ) -> Result, PayjoinError> { let (proposal, _) = Self::get_configuration(self); let res = proposal.unwrap().check_can_broadcast(|tx| { - let raw_tx = hex::encode(payjoin::bitcoin::consensus::encode::serialize(&tx)); - let mempool_results = can_broadcast.test_mempool_accept(vec![raw_tx]); - match mempool_results { + match can_broadcast + .test_mempool_accept(payjoin::bitcoin::consensus::encode::serialize(&tx)) + { Ok(e) => Ok(e), Err(e) => Err(PdkError::Server(e.into())), } @@ -127,6 +131,7 @@ impl UncheckedProposal { pub struct MaybeInputsOwned { internal: Mutex>, } + impl From for MaybeInputsOwned { fn from(value: PdkMaybeInputsOwned) -> Self { MaybeInputsOwned { internal: Mutex::new(Some(value)) } @@ -136,6 +141,7 @@ impl From for MaybeInputsOwned { pub trait IsScriptOwned: Send + Sync { fn is_owned(&self, script: Arc) -> Result; } + impl MaybeInputsOwned { fn get_owned_inputs( &self, @@ -169,11 +175,13 @@ impl MaybeInputsOwned { pub struct MaybeMixedInputScripts { internal: Mutex>, } + impl From for MaybeMixedInputScripts { fn from(value: PdkMaybeMixedInputScripts) -> Self { MaybeMixedInputScripts { internal: Mutex::new(Some(value)) } } } + impl MaybeMixedInputScripts { fn get_input_scripts( &self, @@ -192,6 +200,7 @@ impl MaybeMixedInputScripts { } } } + pub trait IsOutputKnown { fn is_known(&self, outpoint: OutPoint) -> Result; } @@ -202,11 +211,13 @@ pub trait IsOutputKnown { pub struct MaybeInputsSeen { internal: Mutex>, } + impl From for MaybeInputsSeen { fn from(value: PdkMaybeInputsSeen) -> Self { MaybeInputsSeen { internal: Mutex::new(Some(value)) } } } + impl MaybeInputsSeen { fn get_inputs(&self) -> (Option, MutexGuard>) { let mut data_guard = self.internal.lock().unwrap(); @@ -229,6 +240,7 @@ impl MaybeInputsSeen { } } } + /// The receiver has not yet identified which outputs belong to the receiver. /// /// Only accept PSBTs that send us money. Identify those outputs with identify_receiver_outputs() to proceed @@ -236,6 +248,7 @@ impl MaybeInputsSeen { pub struct OutputsUnknown { internal: Mutex>, } + impl From for OutputsUnknown { fn from(value: PdkOutputsUnknown) -> Self { OutputsUnknown { internal: Mutex::new(Some(value)) } @@ -272,11 +285,13 @@ impl OutputsUnknown { pub struct PayjoinProposal { internal: Mutex>, } + impl From for PayjoinProposal { fn from(value: PdkPayjoinProposal) -> Self { PayjoinProposal { internal: Mutex::new(Some(value)) } } } + impl PayjoinProposal { fn get_proposal(&self) -> Option { let mut data_guard = self.internal.lock().unwrap(); @@ -392,13 +407,17 @@ mod test { let proposal = get_proposal_from_test_vector(); assert!(proposal.is_ok(), "OriginalPSBT should be a valid request"); } + struct MockScriptOwned {} + struct MockOutputOwned {} + impl IsOutputKnown for MockOutputOwned { fn is_known(&self, _: OutPoint) -> Result { Ok(false) } } + impl IsScriptOwned for MockScriptOwned { fn is_owned(&self, script: Arc) -> Result { { diff --git a/src/test/mod.rs b/src/test/mod.rs index f77966a..0cbead8 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -10,6 +10,7 @@ use log::{debug, log_enabled, Level}; use payjoin::bitcoin; use payjoin::bitcoin::base64; +use crate::bitcoin::consensus::encode::serialize_hex; use crate::receive::{Headers, IsOutputKnown, IsScriptOwned, UncheckedProposal}; use crate::send::{Configuration, Request}; use crate::transaction::PartiallySignedTransaction; @@ -42,14 +43,14 @@ fn integration_test() { ); assert_eq!( - payjoin::bitcoin::Amount::from_btc(50.0).unwrap(), + bitcoin::Amount::from_btc(50.0).unwrap(), sender.get_balances().unwrap().mine.trusted, "sender doesn't own bitcoin" ); // Receiver creates the payjoin URI let pj_receiver_address = receiver.get_new_address(None, None).unwrap().assume_checked(); - let amount = payjoin::bitcoin::Amount::from_btc(1.0).unwrap(); + let amount = bitcoin::Amount::from_btc(1.0).unwrap(); let pj_uri_string = format!( "{}?amount={}&pj=https://example.com", pj_receiver_address.to_qr_uri(), @@ -67,7 +68,7 @@ fn integration_test() { debug!("outputs: {:?}", outputs); let options = bitcoincore_rpc::json::WalletCreateFundedPsbtOptions { lock_unspent: Some(true), - fee_rate: Some(payjoin::bitcoin::Amount::from_sat(2000)), + fee_rate: Some(bitcoin::Amount::from_sat(2000)), ..Default::default() }; let psbt = sender @@ -206,8 +207,8 @@ fn handle_pj_request( struct TestBroadcast(Arc); impl crate::receive::CanBroadcast for TestBroadcast { - fn test_mempool_accept(&self, tx_hex: Vec) -> Result { - match self.0.test_mempool_accept(&tx_hex) { + fn test_mempool_accept(&self, tx: Vec) -> Result { + match self.0.test_mempool_accept(&[serialize_hex(&tx)]) { Ok(e) => Ok(match e.first() { Some(e) => e.allowed, None => panic!("No Mempool Result"),