Split DecodePSBT into Base64 and Raw versions
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.
This commit is contained in:
parent
162ffefd2f
commit
c734aaa15d
5 changed files with 25 additions and 8 deletions
|
@ -37,7 +37,11 @@ bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
|
||||||
*/
|
*/
|
||||||
bool ParseHashStr(const std::string& strHex, uint256& result);
|
bool ParseHashStr(const std::string& strHex, uint256& result);
|
||||||
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
|
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);
|
int ParseSighashString(const UniValue& sighash);
|
||||||
|
|
||||||
// core_write.cpp
|
// core_write.cpp
|
||||||
|
|
|
@ -176,10 +176,20 @@ bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
|
||||||
return true;
|
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());
|
bool invalid;
|
||||||
CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
|
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 {
|
try {
|
||||||
ss_data >> psbt;
|
ss_data >> psbt;
|
||||||
if (!ss_data.empty()) {
|
if (!ss_data.empty()) {
|
||||||
|
|
|
@ -1323,7 +1323,7 @@ UniValue decodepsbt(const JSONRPCRequest& request)
|
||||||
// Unserialize the transactions
|
// Unserialize the transactions
|
||||||
PartiallySignedTransaction psbtx;
|
PartiallySignedTransaction psbtx;
|
||||||
std::string error;
|
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));
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1524,7 +1524,7 @@ UniValue combinepsbt(const JSONRPCRequest& request)
|
||||||
for (unsigned int i = 0; i < txs.size(); ++i) {
|
for (unsigned int i = 0; i < txs.size(); ++i) {
|
||||||
PartiallySignedTransaction psbtx;
|
PartiallySignedTransaction psbtx;
|
||||||
std::string error;
|
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));
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
|
||||||
}
|
}
|
||||||
psbtxs.push_back(psbtx);
|
psbtxs.push_back(psbtx);
|
||||||
|
@ -1581,7 +1581,7 @@ UniValue finalizepsbt(const JSONRPCRequest& request)
|
||||||
// Unserialize the transactions
|
// Unserialize the transactions
|
||||||
PartiallySignedTransaction psbtx;
|
PartiallySignedTransaction psbtx;
|
||||||
std::string error;
|
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));
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4046,7 +4046,7 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request)
|
||||||
// Unserialize the transaction
|
// Unserialize the transaction
|
||||||
PartiallySignedTransaction psbtx;
|
PartiallySignedTransaction psbtx;
|
||||||
std::string error;
|
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));
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -293,5 +293,8 @@ class PSBTTest(BitcoinTestFramework):
|
||||||
psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True)
|
psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True)
|
||||||
self.nodes[0].decodepsbt(psbt['psbt'])
|
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__':
|
if __name__ == '__main__':
|
||||||
PSBTTest().main()
|
PSBTTest().main()
|
||||||
|
|
Loading…
Reference in a new issue