Skip to content

Commit 9d9a91c

Browse files
committed
rpc: bugfix, incorrect segwit redeem script size used in signrawtransactionwithkey
The process currently fails to sign redeem scripts that are longer than 520 bytes. Even when it shouldn't. The 520 bytes redeem scripts limit is a legacy p2sh rule, and not a segwit limitation. Segwit redeem scripts are not restricted by the script item size limit. The reason why this occurs, is the usage of the same keystore used by the legacy spkm. Which contains blockage for any redeem scripts longer than the script item size limit.
1 parent 0c9fedf commit 9d9a91c

File tree

3 files changed

+11
-7
lines changed

3 files changed

+11
-7
lines changed

src/rpc/rawtransaction.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -785,15 +785,19 @@ static RPCHelpMan signrawtransactionwithkey()
785785
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
786786
}
787787

788-
FillableSigningProvider keystore;
788+
FlatSigningProvider keystore;
789789
const UniValue& keys = request.params[1].get_array();
790790
for (unsigned int idx = 0; idx < keys.size(); ++idx) {
791791
UniValue k = keys[idx];
792792
CKey key = DecodeSecret(k.get_str());
793793
if (!key.IsValid()) {
794794
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
795795
}
796-
keystore.AddKey(key);
796+
797+
CPubKey pubkey = key.GetPubKey();
798+
CKeyID key_id = pubkey.GetID();
799+
keystore.pubkeys.emplace(key_id, pubkey);
800+
keystore.keys.emplace(key_id, key);
797801
}
798802

799803
// Fetch previous transactions (inputs):

src/rpc/rawtransaction_util.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
181181
vErrorsRet.push_back(entry);
182182
}
183183

184-
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins)
184+
void ParsePrevouts(const UniValue& prevTxsUnival, FlatSigningProvider* keystore, std::map<COutPoint, Coin>& coins)
185185
{
186186
if (!prevTxsUnival.isNull()) {
187187
const UniValue& prevTxs = prevTxsUnival.get_array();
@@ -247,11 +247,11 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
247247
// work from witnessScript when possible
248248
std::vector<unsigned char> scriptData(!ws.isNull() ? ParseHexV(ws, "witnessScript") : ParseHexV(rs, "redeemScript"));
249249
CScript script(scriptData.begin(), scriptData.end());
250-
keystore->AddCScript(script);
250+
keystore->scripts.emplace(CScriptID(script), script);
251251
// Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
252252
// This is done for redeemScript only for compatibility, it is encouraged to use the explicit witnessScript field instead.
253253
CScript witness_output_script{GetScriptForDestination(WitnessV0ScriptHash(script))};
254-
keystore->AddCScript(witness_output_script);
254+
keystore->scripts.emplace(CScriptID(witness_output_script), witness_output_script);
255255

256256
if (!ws.isNull() && !rs.isNull()) {
257257
// if both witnessScript and redeemScript are provided,

src/rpc/rawtransaction_util.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <optional>
1313

1414
struct bilingual_str;
15-
class FillableSigningProvider;
15+
struct FlatSigningProvider;
1616
class UniValue;
1717
struct CMutableTransaction;
1818
class Coin;
@@ -38,7 +38,7 @@ void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const
3838
* @param keystore A pointer to the temporary keystore if there is one
3939
* @param coins Map of unspent outputs - coins in mempool and current chain UTXO set, may be extended by previous txns outputs after call
4040
*/
41-
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
41+
void ParsePrevouts(const UniValue& prevTxsUnival, FlatSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
4242

4343
/** Normalize univalue-represented inputs and add them to the transaction */
4444
void AddInputs(CMutableTransaction& rawTx, const UniValue& inputs_in, bool rbf);

0 commit comments

Comments
 (0)