From 1f007db650effd79d383a8a9226a517110b431e9 Mon Sep 17 00:00:00 2001 From: willowens14 Date: Thu, 15 Jun 2023 13:56:31 -0600 Subject: [PATCH 1/4] Add preliminary send payjoin support Remove Cargo.lock fixed handlers formatting payjoin 0.8.2 regenerated cargo.lock - pin tokio+tempfile to build with MSRV 1.57.0 Updated pin 8/28 added psbt::input crate --- .github/workflows/cont_integration.yml | 6 +- .gitignore | 1 + Cargo.lock | 225 +++++++++++-------------- Cargo.toml | 8 +- README.md | 7 + src/commands.rs | 9 +- src/handlers.rs | 139 ++++++++++++++- 7 files changed, 264 insertions(+), 131 deletions(-) diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index a8912c29..2695e3bf 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -59,8 +59,12 @@ jobs: cargo update -p cc --precise 1.0.81 cargo update -p tokio --precise 1.29.1 cargo update -p flate2 --precise 1.0.26 + cargo update -p reqwest --precise "0.11.18" + cargo update -p h2 --precise "0.3.20" + cargo update -p rustls --precise "0.20.8" + - name: Build - run: cargo build --no-default-features --features repl,${{ matrix.features }} --locked + run: cargo build --no-default-features --features repl,${{ matrix.features }} - name: Clippy run: cargo clippy -- -D warnings - name: Test diff --git a/.gitignore b/.gitignore index 6dfb84d0..5fd1beab 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.swp .idea +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index ddf5635e..1faf30dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,9 +42,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "57e6e951cfbb2db8de1828d49073a113a29fd7117b1596caa781a258c7e38d72" dependencies = [ "cfg-if", "once_cell", @@ -53,19 +53,13 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.4" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - [[package]] name = "async-trait" version = "0.1.73" @@ -190,8 +184,10 @@ dependencies = [ "getrandom", "js-sys", "log", + "payjoin", "rand 0.6.5", "regex", + "reqwest", "rustyline", "secp256k1 0.22.2", "serde", @@ -232,6 +228,16 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bip21" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1998475af29ccfb7c761bb624a16e501fc321510366012bc9cce267bc134aedc" +dependencies = [ + "bitcoin", + "percent-encoding-rfc3986", +] + [[package]] name = "bip39" version = "1.2.0" @@ -381,9 +387,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", "libc", @@ -598,19 +604,19 @@ dependencies = [ "byteorder", "libc", "log", - "rustls 0.20.8", + "rustls", "serde", "serde_json", "webpki", - "webpki-roots 0.22.6", + "webpki-roots", "winapi", ] [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -904,9 +910,9 @@ checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -929,21 +935,20 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", - "allocator-api2", + "ahash 0.8.0", ] [[package]] name = "hashlink" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.13.2", ] [[package]] @@ -1481,6 +1486,19 @@ dependencies = [ "proc-macro-hack", ] +[[package]] +name = "payjoin" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d925dff9512850cf8c220ed6268afb5a5ec098aa0c897482e88deb57791cb8c" +dependencies = [ + "base64 0.13.1", + "bip21", + "bitcoin", + "log", + "url", +] + [[package]] name = "pbkdf2" version = "0.11.0" @@ -1499,6 +1517,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "percent-encoding-rfc3986" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3637c05577168127568a64e9dc5a6887da720efef07b3d9472d45f63ab191166" + [[package]] name = "pin-project-lite" version = "0.2.12" @@ -1812,21 +1836,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.6" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", @@ -1835,15 +1847,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "20b9b67e2ca7dd9e9f9285b759de30ff538aab981abaaf7bc9bd90b84a0126c3" dependencies = [ "base64 0.21.2", "bytes", @@ -1937,38 +1949,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "rustls" -version = "0.21.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.3", - "sct", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustyline" version = "9.0.0" @@ -2065,9 +2045,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2088,18 +2068,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.183" +version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" dependencies = [ "proc-macro2", "quote", @@ -2153,9 +2133,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg 1.1.0", ] @@ -2281,9 +2261,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", @@ -2494,21 +2474,21 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.7.1" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" +checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" dependencies = [ - "base64 0.21.2", + "base64 0.13.1", "flate2", "log", "once_cell", - "rustls 0.21.6", - "rustls-webpki 0.100.1", + "rustls", "serde", "serde_json", "socks", "url", - "webpki-roots 0.23.1", + "webpki", + "webpki-roots", ] [[package]] @@ -2663,15 +2643,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "webpki-roots" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" -dependencies = [ - "rustls-webpki 0.100.1", -] - [[package]] name = "which" version = "4.4.0" @@ -2738,24 +2709,24 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f51fb4c64f8b770a823c043c7fad036323e1c48f55287b7bbb7987b2fcdf3b" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.48.3", - "windows_i686_gnu 0.48.3", - "windows_i686_msvc 0.48.3", - "windows_x86_64_gnu 0.48.3", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.48.3", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde1bb55ae4ce76a597a8566d82c57432bc69c039449d61572a7a353da28f68c" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -2765,9 +2736,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2" [[package]] name = "windows_aarch64_msvc" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1513e8d48365a78adad7322fd6b5e4c4e99d92a69db8df2d435b25b1f1f286d4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -2777,9 +2748,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a" [[package]] name = "windows_i686_gnu" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60587c0265d2b842298f5858e1a5d79d146f9ee0c37be5782e92a6eb5e1d7a83" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -2789,9 +2760,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64" [[package]] name = "windows_i686_msvc" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224fe0e0ffff5d2ea6a29f82026c8f43870038a0ffc247aa95a52b47df381ac4" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -2801,15 +2772,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954" [[package]] name = "windows_x86_64_gnu" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fc52a0f50a088de499712cbc012df7ebd94e2d6eb948435449d76a6287e7ad" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2093925509d91ea3d69bcd20238f4c2ecdb1a29d3c281d026a09705d0dd35f3d" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -2819,17 +2790,18 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f" [[package]] name = "windows_x86_64_msvc" -version = "0.48.3" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] @@ -2888,11 +2860,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" dependencies = [ "cc", "libc", - "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 48a8603d..1d15bb30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["bitcoin", "wallet", "descriptor", "psbt", "taproot"] readme = "README.md" license = "MIT" -[dependencies] +[dependencies] bdk = { version = "0.27.1", default-features = false, features = ["all-keys"] } bdk-macros = "0.6" clap = { version = "3.2.22", features = ["derive"] } @@ -21,6 +21,12 @@ zeroize = "<1.4.0" dirs-next = "2.0" env_logger = "0.7" base64 = "^0.13" +# payjoin dependencies +payjoin = { version = "=0.8.2", features = ["send"] } +# reqwest +reqwest = { version = "0.10.10", features = ["blocking"] } + + # Optional dependencies rustyline = { version = "~9.0", optional = true } diff --git a/README.md b/README.md index fe95bd51..03495048 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,13 @@ cargo update -p cc --precise 1.0.81 cargo update -p tokio --precise 1.29.1 # flate2 1.0.27 has MSRV 1.63.0+ cargo update -p flate2 --precise 1.0.26 +# reqwest 0.11.19 has MSRV 1.63.0+ +cargo update -p reqwest --precise "0.11.18" +# h2 0.3.21 has MSRV 1.63.0+ +cargo update -p h2 --precise "0.3.20" +# rustls 0.20.9 has MSRV 1.60.0+ +cargo update -p rustls --precise "0.20.8" + ``` ## Resources diff --git a/src/commands.rs b/src/commands.rs index 12d8fe93..e391b121 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -527,6 +527,13 @@ pub enum OnlineWalletSubCommand { #[clap(name = "CONFIRMATIONS", long = "confirmations", default_value = "6")] confirmations: u32, }, + #[cfg(not(feature = "async-interface"))] + /// Sends a Payjoin Transaction. Takes a valid payjoin bip21 uri. + SendPayjoin { + /// Sets the bip21 uri to send to. + #[clap(name = "URI", long = "uri")] + uri: String, + }, } /// Subcommands for Key operations. @@ -622,7 +629,7 @@ mod test { feature = "compact_filters", feature = "rpc" ))] - use super::OnlineWalletSubCommand::{Broadcast, Sync}; + use super::OnlineWalletSubCommand::{Broadcast, SendPayjoin, Sync}; use super::WalletSubCommand::OfflineWalletSubCommand; #[cfg(any( feature = "electrum", diff --git a/src/handlers.rs b/src/handlers.rs index c21afc0c..2582366f 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -87,8 +87,9 @@ use rustyline::error::ReadlineError; use rustyline::Editor; use serde_json::json; use std::str::FromStr; +// Import some modules for payjoin functionality -/// Execute an offline wallet sub-command +// Execute an offline wallet sub-command /// /// Offline wallet sub-commands are described in [`OfflineWalletSubCommand`]. pub fn handle_offline_wallet_subcommand( @@ -321,7 +322,11 @@ where B: Blockchain, D: BatchDatabase, { + use crate::bitcoin::psbt::Input; use bdk::SyncOptions; + use payjoin::PjUriExt; + use payjoin::UriExt; + use std::convert::TryFrom; match online_subcommand { Sync => { @@ -393,6 +398,138 @@ where maybe_await!(wallet.verify_proof(&psbt, &msg, max_confirmation_height))?; Ok(json!({ "spendable": spendable })) } + + #[cfg(not(feature = "async-interface"))] + // Payjoin Logic goes here + SendPayjoin { uri } => { + // convert the bip21 uri into a payjoin uri, and handle error if necessary + let uri = payjoin::Uri::try_from(uri).map_err(|e| { + Error::Generic(format!("Unable to convert BIP21 into Payjoin URI: {}", e)) + })?; + + // ensure uri is payjoin capable + let uri = uri + .check_pj_supported() + .map_err(|e| Error::Generic(format!("Payjoin not supported: {}", e.to_string())))?; + + // ensure amount of satoshis is specified in uri, handle error if not + let sats = match uri.amount { + Some(amount) => Ok(amount.to_sat()), + None => Err(Error::Generic("URI was empty".to_string())), + }?; + + // call wallet build tx to create psbt + let mut tx_builder = wallet.build_tx(); + + // assuming uri address is of type address + let scrm = uri.address.script_pubkey(); + + // create tx with payjoin uri + tx_builder + .add_recipient(scrm.clone(), sats) + .fee_rate(FeeRate::from_sat_per_vb(1.0)) + .enable_rbf(); + + // create original psbt + let (mut original_psbt, _tx_details) = tx_builder + .finish() + .map_err(|e| Error::Generic(format!("Unable to build transaction: {}", e)))?; + + // check + sign psbt + let finalized = wallet.sign(&mut original_psbt, SignOptions::default())?; + + // handle error if the psbt is not finalized + if !finalized { + return Err(Error::Generic("PSBT not finalized".to_string())); + } + + // set payjoin params + // TODO use fee_rate + let pj_params = payjoin::send::Configuration::with_fee_contribution( + payjoin::bitcoin::Amount::from_sat(100), + None, + ); + + // save a clone for after processing the response + let mut ocean_psbt = original_psbt.clone(); + + // Construct the request with the PSBT and parameters + let (req, ctx) = uri + .create_pj_request(original_psbt, pj_params) // not clone here + .map_err(|e| Error::Generic(format!("Error building payjoin request: {}", e)))?; + + // reqwest client + let client = reqwest::blocking::Client::builder() + .danger_accept_invalid_certs(true) + .build() + .map_err(|e| Error::Generic(format!("Error building payjoin client: {}", e)))?; + + // send the request, and receive response + let response = client + .post(req.url) + .body(req.body) + .header("Content-Type", "text/plain") + .send() + .map_err(|e| Error::Generic(format!("Error with HTTP request: {}", e)))?; + + // process the response + let mut payjoin_psbt = ctx + .process_response(response) + .map_err(|e| Error::Generic(format!("Error processing payjoin response: {}", e)))?; + + // need to reintroduce utxo from original psbt + fn input_pairs( + psbt: &mut PartiallySignedTransaction, + ) -> Box + '_> { + Box::new(psbt.unsigned_tx.input.iter().zip(&mut psbt.inputs)) + } + + // get original inputs from original psbt clone (ocean_psbt) + let mut original_inputs = input_pairs(&mut ocean_psbt).peekable(); + + for (proposed_txin, proposed_psbtin) in input_pairs(&mut payjoin_psbt) { + if let Some((original_txin, original_psbtin)) = original_inputs.peek() { + if proposed_txin.previous_output == original_txin.previous_output { + proposed_psbtin.witness_utxo = original_psbtin.witness_utxo.clone(); + proposed_psbtin.non_witness_utxo = original_psbtin.non_witness_utxo.clone(); + } + original_inputs.next(); + } + } + + // basic flow for broadcasting: sign, extract tx, and then broadcast + + // sign + wallet.sign(&mut payjoin_psbt, SignOptions::default())?; + + // finalize + let finalized = wallet.finalize_psbt(&mut payjoin_psbt, SignOptions::default())?; + + match finalized { + true => { + + // Signing was successful + } + false => { + // signing failed + return Err(Error::Generic( + "Signing the payjoin transaction failed.".to_string(), + )); + } + } + + // Extract the finalized transaction + let finalized_tx = payjoin_psbt.extract_tx(); + dbg!("Finalized Transaction:"); + dbg!(finalized_tx.clone()); + + // Broadcast the transaction + blockchain.broadcast(&finalized_tx)?; + + Ok(serde_json::Value::String( + "Successfully sent payjoin transaction".to_string(), + )) + } } } From 9ea62be83eff05687dbbc3b5d2593391e9fdbde4 Mon Sep 17 00:00:00 2001 From: willowens14 Date: Thu, 21 Sep 2023 13:59:50 -0500 Subject: [PATCH 2/4] fixing dependencies for MSRV 1.57.0 Signed-off-by: willowens14 --- .github/workflows/cont_integration.yml | 7 ++++--- Cargo.toml | 2 +- README.md | 15 ++++++++------- src/commands.rs | 6 ++++-- src/handlers.rs | 7 +++---- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index 2695e3bf..c1a48b9a 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -57,10 +57,11 @@ jobs: cargo update -p tempfile --precise 3.6.0 cargo update -p base64ct --precise 1.5.3 cargo update -p cc --precise 1.0.81 - cargo update -p tokio --precise 1.29.1 cargo update -p flate2 --precise 1.0.26 - cargo update -p reqwest --precise "0.11.18" - cargo update -p h2 --precise "0.3.20" + cargo update -p h2:0.3.21 --precise "0.3.20" + cargo update -p reqwest:0.11.20 --precise "0.11.18" + cargo update -p tokio:1.32.0 --precise 1.29.1 + cargo update -p tokio-util:0.7.9 --precise 0.7.8 cargo update -p rustls --precise "0.20.8" - name: Build diff --git a/Cargo.toml b/Cargo.toml index 1d15bb30..5ddd2db3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ dirs-next = "2.0" env_logger = "0.7" base64 = "^0.13" # payjoin dependencies -payjoin = { version = "=0.8.2", features = ["send"] } +payjoin = { version = "=0.8.2", features = ["send"] } # reqwest reqwest = { version = "0.10.10", features = ["blocking"] } diff --git a/README.md b/README.md index 03495048..7348efa4 100644 --- a/README.md +++ b/README.md @@ -135,16 +135,17 @@ cargo update -p tempfile --precise 3.6.0 cargo update -p base64ct --precise 1.5.3 # cc 1.0.82 is throwing error with rust 1.57.0, "error[E0599]: no method named `retain_mut`..." cargo update -p cc --precise 1.0.81 -# tokio 0.30.0 has MSRV 1.63.0 -cargo update -p tokio --precise 1.29.1 + +cargo update -p rustls --precise "0.20.8" # flate2 1.0.27 has MSRV 1.63.0+ cargo update -p flate2 --precise 1.0.26 + +cargo update -p h2:0.3.21 --precise "0.3.20" # reqwest 0.11.19 has MSRV 1.63.0+ -cargo update -p reqwest --precise "0.11.18" -# h2 0.3.21 has MSRV 1.63.0+ -cargo update -p h2 --precise "0.3.20" -# rustls 0.20.9 has MSRV 1.60.0+ -cargo update -p rustls --precise "0.20.8" +cargo update -p reqwest:0.11.20 --precise "0.11.18" +# tokio 0.32.0 has MSRV 1.63.0 +cargo update -p tokio:1.32.0 --precise 1.29.1 +cargo update -p tokio-util:0.7.9 --precise 0.7.8 ``` diff --git a/src/commands.rs b/src/commands.rs index e391b121..3e74e13e 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -527,7 +527,7 @@ pub enum OnlineWalletSubCommand { #[clap(name = "CONFIRMATIONS", long = "confirmations", default_value = "6")] confirmations: u32, }, - #[cfg(not(feature = "async-interface"))] + #[cfg(any(feature = "electrum", feature = "esplora-ureq",))] /// Sends a Payjoin Transaction. Takes a valid payjoin bip21 uri. SendPayjoin { /// Sets the bip21 uri to send to. @@ -623,13 +623,15 @@ mod test { use std::str::{self, FromStr}; use super::OfflineWalletSubCommand::{BumpFee, CreateTx, GetNewAddress}; + #[cfg(any(feature = "electrum", feature = "esplora-ureq",))] + use super::OnlineWalletSubCommand::SendPayjoin; #[cfg(any( feature = "electrum", feature = "esplora", feature = "compact_filters", feature = "rpc" ))] - use super::OnlineWalletSubCommand::{Broadcast, SendPayjoin, Sync}; + use super::OnlineWalletSubCommand::{Broadcast, Sync}; use super::WalletSubCommand::OfflineWalletSubCommand; #[cfg(any( feature = "electrum", diff --git a/src/handlers.rs b/src/handlers.rs index 2582366f..61ea8f26 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -322,10 +322,9 @@ where B: Blockchain, D: BatchDatabase, { - use crate::bitcoin::psbt::Input; use bdk::SyncOptions; - use payjoin::PjUriExt; - use payjoin::UriExt; + #[cfg(any(feature = "electrum", feature = "esplora-ureq",))] + use payjoin::{bitcoin::psbt::Input, PjUriExt, UriExt}; use std::convert::TryFrom; match online_subcommand { @@ -399,7 +398,7 @@ where Ok(json!({ "spendable": spendable })) } - #[cfg(not(feature = "async-interface"))] + #[cfg(any(feature = "electrum", feature = "esplora-ureq",))] // Payjoin Logic goes here SendPayjoin { uri } => { // convert the bip21 uri into a payjoin uri, and handle error if necessary From 2de946d59de6377faf8191e1c47e5f433c58f6b5 Mon Sep 17 00:00:00 2001 From: willowens14 Date: Mon, 11 Dec 2023 20:46:12 -0600 Subject: [PATCH 3/4] fix MSRV issues --- .github/workflows/cont_integration.yml | 15 ++++++++++----- src/handlers.rs | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index c1a48b9a..ddb91e6f 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -56,13 +56,18 @@ jobs: cargo update -p hashlink --precise 0.8.0 cargo update -p tempfile --precise 3.6.0 cargo update -p base64ct --precise 1.5.3 - cargo update -p cc --precise 1.0.81 cargo update -p flate2 --precise 1.0.26 - cargo update -p h2:0.3.21 --precise "0.3.20" - cargo update -p reqwest:0.11.20 --precise "0.11.18" - cargo update -p tokio:1.32.0 --precise 1.29.1 + cargo update -p h2:0.3.21 --precise 0.3.20 + cargo update -p reqwest:0.11.22 --precise 0.11.18 + cargo update -p tokio:1.33.0 --precise 1.29.1 cargo update -p tokio-util:0.7.9 --precise 0.7.8 - cargo update -p rustls --precise "0.20.8" + cargo update -p rustls --precise 0.20.8 + cargo update -p byteorder --precise "1.4.3" + cargo update -p webpki --precise 0.22.2 + cargo update -p cc --precise 1.0.81 + cargo update -p os_str_bytes --precise 6.5.1 + cargo update -p jobserver --precise 0.1.26 + - name: Build run: cargo build --no-default-features --features repl,${{ matrix.features }} diff --git a/src/handlers.rs b/src/handlers.rs index 61ea8f26..1f0b596e 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -491,8 +491,9 @@ where if proposed_txin.previous_output == original_txin.previous_output { proposed_psbtin.witness_utxo = original_psbtin.witness_utxo.clone(); proposed_psbtin.non_witness_utxo = original_psbtin.non_witness_utxo.clone(); - } + original_inputs.next(); + } } } From e93f225cc31bdaf4bf945f3adf9927bf85e4bc6d Mon Sep 17 00:00:00 2001 From: DanGould Date: Wed, 13 Dec 2023 20:24:25 -0500 Subject: [PATCH 4/4] Format original_inputs.next() --- src/handlers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers.rs b/src/handlers.rs index 1f0b596e..effdd239 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -491,8 +491,8 @@ where if proposed_txin.previous_output == original_txin.previous_output { proposed_psbtin.witness_utxo = original_psbtin.witness_utxo.clone(); proposed_psbtin.non_witness_utxo = original_psbtin.non_witness_utxo.clone(); - - original_inputs.next(); + + original_inputs.next(); } } }