Skip to content

Commit c27fe41

Browse files
committed
Create utility RPCs for PSBT
decodepsbt takes a PSBT and decodes it to JSON combinepsbt takes multiple PSBTs for the same tx and combines them. finalizepsbt takes a PSBT and finalizes the inputs. If all inputs are final, it extracts the network serialized transaction and returns that instead of a PSBT unless instructed otherwise. createpsbt is like createrawtransaction but for PSBTs instead of raw transactions. convertpsbt takes a network serialized transaction and converts it into a psbt. The resulting psbt will lose all signature data and an explicit flag must be set to allow transactions with signature data to be converted.
1 parent 8b5ef27 commit c27fe41

File tree

5 files changed

+606
-0
lines changed

5 files changed

+606
-0
lines changed

src/core_io.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class CBlock;
1414
class CScript;
1515
class CTransaction;
1616
struct CMutableTransaction;
17+
struct PartiallySignedTransaction;
1718
class uint256;
1819
class UniValue;
1920

@@ -24,12 +25,15 @@ bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no
2425
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
2526
uint256 ParseHashStr(const std::string&, const std::string& strName);
2627
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
28+
bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error);
2729

2830
// core_write.cpp
2931
UniValue ValueFromAmount(const CAmount& amount);
3032
std::string FormatScript(const CScript& script);
3133
std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
34+
std::string SighashToStr(unsigned char sighash_type);
3235
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
36+
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address);
3337
void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, bool include_hex = true, int serialize_flags = 0);
3438

3539
#endif // BITCOIN_CORE_IO_H

src/core_read.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <primitives/block.h>
88
#include <primitives/transaction.h>
99
#include <script/script.h>
10+
#include <script/sign.h>
1011
#include <serialize.h>
1112
#include <streams.h>
1213
#include <univalue.h>
@@ -160,6 +161,23 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
160161
return true;
161162
}
162163

164+
bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
165+
{
166+
std::vector<unsigned char> tx_data = DecodeBase64(base64_tx.c_str());
167+
CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
168+
try {
169+
ss_data >> psbt;
170+
if (!ss_data.empty()) {
171+
error = "extra data after PSBT";
172+
return false;
173+
}
174+
} catch (const std::exception& e) {
175+
error = e.what();
176+
return false;
177+
}
178+
return true;
179+
}
180+
163181
uint256 ParseHashStr(const std::string& strHex, const std::string& strName)
164182
{
165183
if (!IsHex(strHex)) // Note: IsHex("") is false

src/core_write.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ const std::map<unsigned char, std::string> mapSigHashTypes = {
7070
{static_cast<unsigned char>(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")},
7171
};
7272

73+
std::string SighashToStr(unsigned char sighash_type)
74+
{
75+
const auto& it = mapSigHashTypes.find(sighash_type);
76+
if (it == mapSigHashTypes.end()) return "";
77+
return it->second;
78+
}
79+
7380
/**
7481
* Create the assembly string representation of a CScript object.
7582
* @param[in] script CScript object to convert into the asm string representation.
@@ -128,6 +135,22 @@ std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags)
128135
return HexStr(ssTx.begin(), ssTx.end());
129136
}
130137

138+
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
139+
{
140+
out.pushKV("asm", ScriptToAsmStr(script));
141+
out.pushKV("hex", HexStr(script.begin(), script.end()));
142+
143+
std::vector<std::vector<unsigned char>> solns;
144+
txnouttype type;
145+
Solver(script, type, solns);
146+
out.pushKV("type", GetTxnOutputType(type));
147+
148+
CTxDestination address;
149+
if (include_address && ExtractDestination(script, address)) {
150+
out.pushKV("address", EncodeDestination(address));
151+
}
152+
}
153+
131154
void ScriptPubKeyToUniv(const CScript& scriptPubKey,
132155
UniValue& out, bool fIncludeHex)
133156
{

src/rpc/client.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ static const CRPCConvertParam vRPCConvertParams[] =
109109
{ "combinerawtransaction", 0, "txs" },
110110
{ "fundrawtransaction", 1, "options" },
111111
{ "fundrawtransaction", 2, "iswitness" },
112+
{ "createpsbt", 0, "inputs" },
113+
{ "createpsbt", 1, "outputs" },
114+
{ "createpsbt", 2, "locktime" },
115+
{ "createpsbt", 3, "replaceable" },
116+
{ "combinepsbt", 0, "txs"},
117+
{ "finalizepsbt", 1, "extract"},
118+
{ "converttopsbt", 1, "permitsigdata"},
119+
{ "converttopsbt", 2, "iswitness"},
112120
{ "gettxout", 1, "n" },
113121
{ "gettxout", 2, "include_mempool" },
114122
{ "gettxoutproof", 0, "txids" },

0 commit comments

Comments
 (0)