diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2012-09-07 21:05:20 -0400 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2012-10-29 13:34:35 -0400 |
commit | 03346a61b175420681bec120656ac1d5db169547 (patch) | |
tree | 68b4b53393031bb6964b94572d1820ee04eb7c0b /src/rpcrawtransaction.cpp | |
parent | 2d43f88e1fbccf5b03db12a40567c5ef40029173 (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.cpp | 69 |
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); |