Skip to content

Commit

Permalink
Split DecodePSBT into Base64 and Raw versions
Browse files Browse the repository at this point in the history
Split up DecodePSBT, which both decodes base64 and then deserializes a
PartiallySignedTransaction, into two functions: DecodeBase64PSBT, which retains
the old behavior, and DecodeRawPSBT, which only performs the deserialization.

Add a test for base64 decoding failure.
  • Loading branch information
gwillen committed Feb 11, 2019
1 parent 162ffef commit c734aaa
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/core_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
*/
bool ParseHashStr(const std::string& strHex, uint256& result);
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
NODISCARD bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error);

//! Decode a base64ed PSBT into a PartiallySignedTransaction
NODISCARD bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
//! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
NODISCARD bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error);
int ParseSighashString(const UniValue& sighash);

// core_write.cpp
Expand Down
16 changes: 13 additions & 3 deletions src/core_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,20 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
return true;
}

bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
{
std::vector<unsigned char> tx_data = DecodeBase64(base64_tx.c_str());
CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
bool invalid;
std::string tx_data = DecodeBase64(base64_tx, &invalid);
if (invalid) {
error = "invalid base64";
return false;
}
return DecodeRawPSBT(psbt, tx_data, error);
}

bool DecodeRawPSBT(PartiallySignedTransaction& psbt, const std::string& tx_data, std::string& error)
{
CDataStream ss_data(tx_data.data(), tx_data.data() + tx_data.size(), SER_NETWORK, PROTOCOL_VERSION);
try {
ss_data >> psbt;
if (!ss_data.empty()) {
Expand Down
6 changes: 3 additions & 3 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,7 @@ UniValue decodepsbt(const JSONRPCRequest& request)
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}

Expand Down Expand Up @@ -1524,7 +1524,7 @@ UniValue combinepsbt(const JSONRPCRequest& request)
for (unsigned int i = 0; i < txs.size(); ++i) {
PartiallySignedTransaction psbtx;
std::string error;
if (!DecodePSBT(psbtx, txs[i].get_str(), error)) {
if (!DecodeBase64PSBT(psbtx, txs[i].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}
psbtxs.push_back(psbtx);
Expand Down Expand Up @@ -1581,7 +1581,7 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
// Unserialize the transactions
PartiallySignedTransaction psbtx;
std::string error;
if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}

Expand Down
2 changes: 1 addition & 1 deletion src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4046,7 +4046,7 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
// Unserialize the transaction
PartiallySignedTransaction psbtx;
std::string error;
if (!DecodePSBT(psbtx, request.params[0].get_str(), error)) {
if (!DecodeBase64PSBT(psbtx, request.params[0].get_str(), error)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
}

Expand Down
3 changes: 3 additions & 0 deletions test/functional/rpc_psbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,8 @@ def run_test(self):
psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True)
self.nodes[0].decodepsbt(psbt['psbt'])

# Test decoding error: invalid base64
assert_raises_rpc_error(-22, "TX decode failed invalid base64", self.nodes[0].decodepsbt, ";definitely not base64;")

if __name__ == '__main__':
PSBTTest().main()

0 comments on commit c734aaa

Please sign in to comment.