| 1852 | } |
| 1853 | |
| 1854 | static RPCMethod joinpsbts() |
| 1855 | { |
| 1856 | return RPCMethod{ |
| 1857 | "joinpsbts", |
| 1858 | "Joins multiple distinct version 0 PSBTs with different inputs and outputs into one version 0 PSBT with inputs and outputs from all of the PSBTs\n" |
| 1859 | "No input in any of the PSBTs can be in more than one of the PSBTs.\n", |
| 1860 | { |
| 1861 | {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The base64 strings of partially signed transactions", |
| 1862 | { |
| 1863 | {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} |
| 1864 | }} |
| 1865 | }, |
| 1866 | RPCResult { |
| 1867 | RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" |
| 1868 | }, |
| 1869 | RPCExamples { |
| 1870 | HelpExampleCli("joinpsbts", "\"psbt\"") |
| 1871 | }, |
| 1872 | [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue |
| 1873 | { |
| 1874 | // Unserialize the transactions |
| 1875 | std::vector<PartiallySignedTransaction> psbtxs; |
| 1876 | UniValue txs = request.params[0].get_array(); |
| 1877 | |
| 1878 | if (txs.size() <= 1) { |
| 1879 | throw JSONRPCError(RPC_INVALID_PARAMETER, "At least two PSBTs are required to join PSBTs."); |
| 1880 | } |
| 1881 | |
| 1882 | uint32_t best_version = 1; |
| 1883 | uint32_t best_locktime = 0xffffffff; |
| 1884 | for (unsigned int i = 0; i < txs.size(); ++i) { |
| 1885 | util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(txs[i].get_str()); |
| 1886 | if (!psbt_res) { |
| 1887 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original)); |
| 1888 | } |
| 1889 | psbtxs.push_back(*psbt_res); |
| 1890 | const PartiallySignedTransaction& psbtx = psbtxs.back(); |
| 1891 | if (psbtx.GetVersion() != 0) { |
| 1892 | throw JSONRPCError(RPC_INVALID_PARAMETER, "joinpsbts only operates on version 0 PSBTs"); |
| 1893 | } |
| 1894 | // Choose the highest version number |
| 1895 | if (psbtx.tx_version > best_version) { |
| 1896 | best_version = psbtx.tx_version; |
| 1897 | } |
| 1898 | // Choose the lowest lock time |
| 1899 | uint32_t psbt_locktime = psbtx.fallback_locktime.value_or(0); |
| 1900 | if (psbt_locktime < best_locktime) { |
| 1901 | best_locktime = psbt_locktime; |
| 1902 | } |
| 1903 | } |
| 1904 | |
| 1905 | // Create a blank psbt where everything will be added |
| 1906 | CMutableTransaction tx; |
| 1907 | tx.version = best_version; |
| 1908 | tx.nLockTime = best_locktime; |
| 1909 | PartiallySignedTransaction merged_psbt(tx, psbtxs.at(0).GetVersion()); |
| 1910 | |
| 1911 | // Merge |
nothing calls this directly
no test coverage detected