aboutsummaryrefslogtreecommitdiff
path: root/src/rpcrawtransaction.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2012-09-07 21:05:20 -0400
committerGavin Andresen <gavinandresen@gmail.com>2012-10-29 13:34:35 -0400
commit03346a61b175420681bec120656ac1d5db169547 (patch)
tree68b4b53393031bb6964b94572d1820ee04eb7c0b /src/rpcrawtransaction.cpp
parent2d43f88e1fbccf5b03db12a40567c5ef40029173 (diff)
Add redeemScript to listunspent output and signrawtransaction input
signrawtransaction was unable to sign pay-to-script-hash inputs when given the list of private keys to use. With this commit you can provide the p2sh redemption script in the list of inputs.
Diffstat (limited to 'src/rpcrawtransaction.cpp')
-rw-r--r--src/rpcrawtransaction.cpp69
1 files changed, 46 insertions, 23 deletions
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 54b463111f..e82f4ad91d 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -226,6 +226,17 @@ Value listunspent(const Array& params, bool fHelp)
entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
entry.push_back(Pair("vout", out.i));
entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
+ if (pk.IsPayToScriptHash())
+ {
+ CTxDestination address;
+ if (ExtractDestination(pk, address))
+ {
+ const CScriptID& hash = boost::get<const CScriptID&>(address);
+ CScript redeemScript;
+ if (pwalletMain->GetCScript(hash, redeemScript))
+ entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end())));
+ }
+ }
entry.push_back(Pair("amount",ValueFromAmount(nValue)));
entry.push_back(Pair("confirmations",out.nDepth));
results.push_back(entry);
@@ -321,7 +332,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 4)
throw runtime_error(
- "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
+ "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex,\"redeemScript\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
"Sign inputs for raw transaction (serialized, hex-encoded).\n"
"Second optional argument (may be null) is an array of previous transaction outputs that\n"
"this transaction depends on but may not yet be in the block chain.\n"
@@ -377,6 +388,28 @@ Value signrawtransaction(const Array& params, bool fHelp)
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
}
+ bool fGivenKeys = false;
+ CBasicKeyStore tempKeystore;
+ if (params.size() > 2 && params[2].type() != null_type)
+ {
+ fGivenKeys = true;
+ Array keys = params[2].get_array();
+ BOOST_FOREACH(Value k, keys)
+ {
+ CBitcoinSecret vchSecret;
+ bool fGood = vchSecret.SetString(k.get_str());
+ if (!fGood)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
+ CKey key;
+ bool fCompressed;
+ CSecret secret = vchSecret.GetSecret(fCompressed);
+ key.SetSecret(secret, fCompressed);
+ tempKeystore.AddKey(key);
+ }
+ }
+ else
+ EnsureWalletIsUnlocked();
+
// Add previous txouts given in the RPC call:
if (params.size() > 1 && params[1].type() != null_type)
{
@@ -388,7 +421,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
Object prevOut = p.get_obj();
- RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
+ RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type)("redeemScript",str_type));
uint256 txid = ParseHashO(prevOut, "txid");
@@ -409,33 +442,23 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
// what todo if txid is known, but the actual output isn't?
}
+ if ((unsigned int)nOut >= coins.vout.size())
+ coins.vout.resize(nOut+1);
coins.vout[nOut].scriptPubKey = scriptPubKey;
coins.vout[nOut].nValue = 0; // we don't know the actual output value
view.SetCoins(txid, coins);
- }
- }
- bool fGivenKeys = false;
- CBasicKeyStore tempKeystore;
- if (params.size() > 2 && params[2].type() != null_type)
- {
- fGivenKeys = true;
- Array keys = params[2].get_array();
- BOOST_FOREACH(Value k, keys)
- {
- CBitcoinSecret vchSecret;
- bool fGood = vchSecret.SetString(k.get_str());
- if (!fGood)
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key");
- CKey key;
- bool fCompressed;
- CSecret secret = vchSecret.GetSecret(fCompressed);
- key.SetSecret(secret, fCompressed);
- tempKeystore.AddKey(key);
+ // if redeemScript given and not using the local wallet (private keys
+ // given), add redeemScript to the tempKeystore so it can be signed:
+ Value v = find_value(prevOut, "redeemScript");
+ if (fGivenKeys && scriptPubKey.IsPayToScriptHash() && !(v == Value::null))
+ {
+ vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
+ CScript redeemScript(rsData.begin(), rsData.end());
+ tempKeystore.AddCScript(redeemScript);
+ }
}
}
- else
- EnsureWalletIsUnlocked();
const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);