annotate src/rpcrawtransaction.cpp @ 3330:71d199d19f59 draft

Allow signrawtransaction '...' null null 'hashtype' Allows the user to pass null as the second or third parameter to signrawtransaction, in case you need to (for example) fetch private keys from the wallet but want to specify the hash type.
author Gavin Andresen <gavinandresen@gmail.com>
date Mon, 20 Aug 2012 16:18:17 -0400 (2012-08-20)
parents 71eb723dde0e
children 060485871634
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
1 // Copyright (c) 2010 Satoshi Nakamoto
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
2 // Copyright (c) 2009-2012 The Bitcoin developers
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
3 // Distributed under the MIT/X11 software license, see the accompanying
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
5
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
6 #include <boost/assign/list_of.hpp>
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
7
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
8 #include "base58.h"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
9 #include "bitcoinrpc.h"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
10 #include "db.h"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
11 #include "init.h"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
12 #include "main.h"
3197
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
13 #include "net.h"
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
14 #include "wallet.h"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
15
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
16 using namespace std;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
17 using namespace boost;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
18 using namespace boost::assign;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
19 using namespace json_spirit;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
20
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
21 // These are all in bitcoinrpc.cpp:
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
22 extern Object JSONRPCError(int code, const string& message);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
23 extern int64 AmountFromValue(const Value& value);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
24 extern Value ValueFromAmount(int64 amount);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
25 extern std::string HelpRequiringPassphrase();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
26 extern void EnsureWalletIsUnlocked();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
27
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
28 void
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
29 ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
30 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
31 txnouttype type;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
32 vector<CTxDestination> addresses;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
33 int nRequired;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
34
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
35 out.push_back(Pair("asm", scriptPubKey.ToString()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
36 out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
37
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
38 if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
39 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
40 out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
41 return;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
42 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
43
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
44 out.push_back(Pair("reqSigs", nRequired));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
45 out.push_back(Pair("type", GetTxnOutputType(type)));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
46
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
47 Array a;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
48 BOOST_FOREACH(const CTxDestination& addr, addresses)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
49 a.push_back(CBitcoinAddress(addr).ToString());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
50 out.push_back(Pair("addresses", a));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
51 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
52
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
53 void
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
54 TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
55 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
56 entry.push_back(Pair("txid", tx.GetHash().GetHex()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
57 entry.push_back(Pair("version", tx.nVersion));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
58 entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
59 Array vin;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
60 BOOST_FOREACH(const CTxIn& txin, tx.vin)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
61 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
62 Object in;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
63 if (tx.IsCoinBase())
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
64 in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
65 else
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
66 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
67 in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
68 in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
69 Object o;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
70 o.push_back(Pair("asm", txin.scriptSig.ToString()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
71 o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
72 in.push_back(Pair("scriptSig", o));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
73 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
74 in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
75 vin.push_back(in);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
76 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
77 entry.push_back(Pair("vin", vin));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
78 Array vout;
3156
505666711e5b Use unsigned ints to fix signed/unsigned warnings
Gavin Andresen <gavinandresen@gmail.com>
parents: 3154
diff changeset
79 for (unsigned int i = 0; i < tx.vout.size(); i++)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
80 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
81 const CTxOut& txout = tx.vout[i];
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
82 Object out;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
83 out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
3156
505666711e5b Use unsigned ints to fix signed/unsigned warnings
Gavin Andresen <gavinandresen@gmail.com>
parents: 3154
diff changeset
84 out.push_back(Pair("n", (boost::int64_t)i));
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
85 Object o;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
86 ScriptPubKeyToJSON(txout.scriptPubKey, o);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
87 out.push_back(Pair("scriptPubKey", o));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
88 vout.push_back(out);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
89 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
90 entry.push_back(Pair("vout", vout));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
91
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
92 if (hashBlock != 0)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
93 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
94 entry.push_back(Pair("blockhash", hashBlock.GetHex()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
95 map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
96 if (mi != mapBlockIndex.end() && (*mi).second)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
97 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
98 CBlockIndex* pindex = (*mi).second;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
99 if (pindex->IsInMainChain())
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
100 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
101 entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
102 entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
103 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
104 else
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
105 entry.push_back(Pair("confirmations", 0));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
106 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
107 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
108 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
109
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
110 Value getrawtransaction(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
111 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
112 if (fHelp || params.size() < 1 || params.size() > 2)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
113 throw runtime_error(
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
114 "getrawtransaction <txid> [verbose=0]\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
115 "If verbose=0, returns a string that is\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
116 "serialized, hex-encoded data for <txid>.\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
117 "If verbose is non-zero, returns an Object\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
118 "with information about <txid>.");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
119
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
120 uint256 hash;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
121 hash.SetHex(params[0].get_str());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
122
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
123 bool fVerbose = false;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
124 if (params.size() > 1)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
125 fVerbose = (params[1].get_int() != 0);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
126
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
127 CTransaction tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
128 uint256 hashBlock = 0;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
129 if (!GetTransaction(hash, tx, hashBlock))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
130 throw JSONRPCError(-5, "No information available about transaction");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
131
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
132 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
133 ssTx << tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
134 string strHex = HexStr(ssTx.begin(), ssTx.end());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
135
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
136 if (!fVerbose)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
137 return strHex;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
138
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
139 Object result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
140 result.push_back(Pair("hex", strHex));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
141 TxToJSON(tx, hashBlock, result);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
142 return result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
143 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
144
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
145 Value listunspent(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
146 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
147 if (fHelp || params.size() > 2)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
148 throw runtime_error(
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
149 "listunspent [minconf=1] [maxconf=999999]\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
150 "Returns array of unspent transaction outputs\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
151 "with between minconf and maxconf (inclusive) confirmations.\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
152 "Results are an array of Objects, each of which has:\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
153 "{txid, vout, scriptPubKey, amount, confirmations}");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
155 RPCTypeCheck(params, list_of(int_type)(int_type));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
156
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
157 int nMinDepth = 1;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
158 if (params.size() > 0)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
159 nMinDepth = params[0].get_int();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
160
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
161 int nMaxDepth = 999999;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
162 if (params.size() > 1)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
163 nMaxDepth = params[1].get_int();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
164
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
165 Array results;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
166 vector<COutput> vecOutputs;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
167 pwalletMain->AvailableCoins(vecOutputs, false);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
168 BOOST_FOREACH(const COutput& out, vecOutputs)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
169 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
170 if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
171 continue;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
172
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
173 int64 nValue = out.tx->vout[out.i].nValue;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
174 const CScript& pk = out.tx->vout[out.i].scriptPubKey;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
175 Object entry;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
176 entry.push_back(Pair("txid", out.tx->GetHash().GetHex()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
177 entry.push_back(Pair("vout", out.i));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
178 entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end())));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
179 entry.push_back(Pair("amount",ValueFromAmount(nValue)));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
180 entry.push_back(Pair("confirmations",out.nDepth));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
181 results.push_back(entry);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
182 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
183
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
184 return results;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
185 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
186
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
187 Value createrawtransaction(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
188 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
189 if (fHelp || params.size() != 2)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
190 throw runtime_error(
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
191 "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
192 "Create a transaction spending given inputs\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
193 "(array of objects containing transaction id and output number),\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
194 "sending to given address(es).\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
195 "Returns hex-encoded raw transaction.\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
196 "Note that the transaction's inputs are not signed, and\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
197 "it is not stored in the wallet or transmitted to the network.");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
198
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
199 RPCTypeCheck(params, list_of(array_type)(obj_type));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
200
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
201 Array inputs = params[0].get_array();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
202 Object sendTo = params[1].get_obj();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
203
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
204 CTransaction rawTx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
205
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
206 BOOST_FOREACH(Value& input, inputs)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
207 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
208 const Object& o = input.get_obj();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
209
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
210 const Value& txid_v = find_value(o, "txid");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
211 if (txid_v.type() != str_type)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
212 throw JSONRPCError(-8, "Invalid parameter, missing txid key");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
213 string txid = txid_v.get_str();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
214 if (!IsHex(txid))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
215 throw JSONRPCError(-8, "Invalid parameter, expected hex txid");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
216
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
217 const Value& vout_v = find_value(o, "vout");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
218 if (vout_v.type() != int_type)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
219 throw JSONRPCError(-8, "Invalid parameter, missing vout key");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
220 int nOutput = vout_v.get_int();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
221 if (nOutput < 0)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
222 throw JSONRPCError(-8, "Invalid parameter, vout must be positive");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
223
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
224 CTxIn in(COutPoint(uint256(txid), nOutput));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
225 rawTx.vin.push_back(in);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
226 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
227
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
228 set<CBitcoinAddress> setAddress;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
229 BOOST_FOREACH(const Pair& s, sendTo)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
230 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
231 CBitcoinAddress address(s.name_);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
232 if (!address.IsValid())
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
233 throw JSONRPCError(-5, string("Invalid Bitcoin address:")+s.name_);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
234
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
235 if (setAddress.count(address))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
236 throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
237 setAddress.insert(address);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
238
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
239 CScript scriptPubKey;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
240 scriptPubKey.SetDestination(address.Get());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
241 int64 nAmount = AmountFromValue(s.value_);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
242
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
243 CTxOut out(nAmount, scriptPubKey);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
244 rawTx.vout.push_back(out);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
245 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
246
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
247 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
248 ss << rawTx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
249 return HexStr(ss.begin(), ss.end());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
250 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
251
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
252 Value decoderawtransaction(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
253 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
254 if (fHelp || params.size() != 1)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
255 throw runtime_error(
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
256 "decoderawtransaction <hex string>\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
257 "Return a JSON object representing the serialized, hex-encoded transaction.");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
258
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
259 RPCTypeCheck(params, list_of(str_type));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
260
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
261 vector<unsigned char> txData(ParseHex(params[0].get_str()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
262 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
263 CTransaction tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
264 try {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
265 ssData >> tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
266 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
267 catch (std::exception &e) {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
268 throw JSONRPCError(-22, "TX decode failed");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
269 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
270
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
271 Object result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
272 TxToJSON(tx, 0, result);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
273
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
274 return result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
275 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
276
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
277 Value signrawtransaction(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
278 {
3225
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
279 if (fHelp || params.size() < 1 || params.size() > 4)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
280 throw runtime_error(
3225
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
281 "signrawtransaction <hex string> [{\"txid\":txid,\"vout\":n,\"scriptPubKey\":hex},...] [<privatekey1>,...] [sighashtype=\"ALL\"]\n"
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
282 "Sign inputs for raw transaction (serialized, hex-encoded).\n"
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
283 "Second optional argument (may be null) is an array of previous transaction outputs that\n"
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
284 "this transaction depends on but may not yet be in the blockchain.\n"
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
285 "Third optional argument (may be null) is an array of base58-encoded private\n"
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
286 "keys that, if given, will be the only keys used to sign the transaction.\n"
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
287 "Fourth optional argument is a string that is one of six values; ALL, NONE, SINGLE or\n"
3225
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
288 "ALL|ANYONECANPAY, NONE|ANYONECANPAY, SINGLE|ANYONECANPAY.\n"
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
289 "Returns json object with keys:\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
290 " hex : raw transaction with signature(s) (hex-encoded string)\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
291 " complete : 1 if transaction has a complete set of signature (0 if not)"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
292 + HelpRequiringPassphrase());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
293
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
294 RPCTypeCheck(params, list_of(str_type)(array_type)(array_type)(str_type), true);
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
295
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
296 vector<unsigned char> txData(ParseHex(params[0].get_str()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
297 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
298 vector<CTransaction> txVariants;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
299 while (!ssData.empty())
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
300 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
301 try {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
302 CTransaction tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
303 ssData >> tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
304 txVariants.push_back(tx);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
305 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
306 catch (std::exception &e) {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
307 throw JSONRPCError(-22, "TX decode failed");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
308 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
309 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
310
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
311 if (txVariants.empty())
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
312 throw JSONRPCError(-22, "Missing transaction");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
313
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
314 // mergedTx will end up with all the signatures; it
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
315 // starts as a clone of the rawtx:
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
316 CTransaction mergedTx(txVariants[0]);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
317 bool fComplete = true;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
318
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
319 // Fetch previous transactions (inputs):
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
320 map<COutPoint, CScript> mapPrevOut;
3289
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
321 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
322 {
3289
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
323 CTransaction tempTx;
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
324 MapPrevTx mapPrevTx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
325 CTxDB txdb("r");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
326 map<uint256, CTxIndex> unused;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
327 bool fInvalid;
3289
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
328
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
329 // FetchInputs aborts on failure, so we go one at a time.
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
330 tempTx.vin.push_back(mergedTx.vin[i]);
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
331 tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
332
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
333 // Copy results into mapPrevOut:
3289
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
334 BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
335 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
336 const uint256& prevHash = txin.prevout.hash;
3289
0addd08564e8 Correctly handle missing inputs in signrawtransaction. Fixes #1654.
Gregory Maxwell <greg@xiph.org>
parents: 3225
diff changeset
337 if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
338 mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
339 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
340 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
341
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
342 // Add previous txouts given in the RPC call:
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
343 if (params.size() > 1 && params[1].type() != null_type)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
344 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
345 Array prevTxs = params[1].get_array();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
346 BOOST_FOREACH(Value& p, prevTxs)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
347 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
348 if (p.type() != obj_type)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
349 throw JSONRPCError(-22, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
350
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
351 Object prevOut = p.get_obj();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
352
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
353 RPCTypeCheck(prevOut, map_list_of("txid", str_type)("vout", int_type)("scriptPubKey", str_type));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
354
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
355 string txidHex = find_value(prevOut, "txid").get_str();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
356 if (!IsHex(txidHex))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
357 throw JSONRPCError(-22, "txid must be hexadecimal");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
358 uint256 txid;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
359 txid.SetHex(txidHex);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
360
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
361 int nOut = find_value(prevOut, "vout").get_int();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
362 if (nOut < 0)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
363 throw JSONRPCError(-22, "vout must be positive");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
364
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
365 string pkHex = find_value(prevOut, "scriptPubKey").get_str();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
366 if (!IsHex(pkHex))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
367 throw JSONRPCError(-22, "scriptPubKey must be hexadecimal");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
368 vector<unsigned char> pkData(ParseHex(pkHex));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
369 CScript scriptPubKey(pkData.begin(), pkData.end());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
370
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
371 COutPoint outpoint(txid, nOut);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
372 if (mapPrevOut.count(outpoint))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
373 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
374 // Complain if scriptPubKey doesn't match
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
375 if (mapPrevOut[outpoint] != scriptPubKey)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
376 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
377 string err("Previous output scriptPubKey mismatch:\n");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
378 err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
379 scriptPubKey.ToString();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
380 throw JSONRPCError(-22, err);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
381 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
382 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
383 else
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
384 mapPrevOut[outpoint] = scriptPubKey;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
385 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
386 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
387
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
388 bool fGivenKeys = false;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
389 CBasicKeyStore tempKeystore;
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
390 if (params.size() > 2 && params[2].type() != null_type)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
391 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
392 fGivenKeys = true;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
393 Array keys = params[2].get_array();
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
394 BOOST_FOREACH(Value k, keys)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
395 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
396 CBitcoinSecret vchSecret;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
397 bool fGood = vchSecret.SetString(k.get_str());
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
398 if (!fGood)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
399 throw JSONRPCError(-5,"Invalid private key");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
400 CKey key;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
401 bool fCompressed;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
402 CSecret secret = vchSecret.GetSecret(fCompressed);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
403 key.SetSecret(secret, fCompressed);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
404 tempKeystore.AddKey(key);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
405 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
406 }
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
407 else
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
408 EnsureWalletIsUnlocked();
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
409
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
410 const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
411
3225
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
412 int nHashType = SIGHASH_ALL;
3330
71d199d19f59 Allow signrawtransaction '...' null null 'hashtype'
Gavin Andresen <gavinandresen@gmail.com>
parents: 3327
diff changeset
413 if (params.size() > 3 && params[3].type() != null_type)
3225
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
414 {
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
415 static map<string, int> mapSigHashValues =
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
416 boost::assign::map_list_of
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
417 (string("ALL"), int(SIGHASH_ALL))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
418 (string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
419 (string("NONE"), int(SIGHASH_NONE))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
420 (string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
421 (string("SINGLE"), int(SIGHASH_SINGLE))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
422 (string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
423 ;
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
424 string strHashType = params[3].get_str();
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
425 if (mapSigHashValues.count(strHashType))
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
426 nHashType = mapSigHashValues[strHashType];
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
427 else
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
428 throw JSONRPCError(-8, "Invalid sighash param");
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
429 }
13158535565e New feature for signrawtransaction: specify signature hash (ALL/NONE/etc)
Gavin Andresen <gavinandresen@gmail.com>
parents: 3197
diff changeset
430
3327
71eb723dde0e When using SIGHASH_SINGLE, do not sign inputs that have no corresponding outputs.
Gavin Andresen <gavinandresen@gmail.com>
parents: 3289
diff changeset
431 bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
71eb723dde0e When using SIGHASH_SINGLE, do not sign inputs that have no corresponding outputs.
Gavin Andresen <gavinandresen@gmail.com>
parents: 3289
diff changeset
432
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
433 // Sign what we can:
3156
505666711e5b Use unsigned ints to fix signed/unsigned warnings
Gavin Andresen <gavinandresen@gmail.com>
parents: 3154
diff changeset
434 for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
435 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
436 CTxIn& txin = mergedTx.vin[i];
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
437 if (mapPrevOut.count(txin.prevout) == 0)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
438 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
439 fComplete = false;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
440 continue;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
441 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
442 const CScript& prevPubKey = mapPrevOut[txin.prevout];
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
443
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
444 txin.scriptSig.clear();
3327
71eb723dde0e When using SIGHASH_SINGLE, do not sign inputs that have no corresponding outputs.
Gavin Andresen <gavinandresen@gmail.com>
parents: 3289
diff changeset
445 // Only sign SIGHASH_SINGLE if there's a corresponding output:
71eb723dde0e When using SIGHASH_SINGLE, do not sign inputs that have no corresponding outputs.
Gavin Andresen <gavinandresen@gmail.com>
parents: 3289
diff changeset
446 if (!fHashSingle || (i < mergedTx.vout.size()))
71eb723dde0e When using SIGHASH_SINGLE, do not sign inputs that have no corresponding outputs.
Gavin Andresen <gavinandresen@gmail.com>
parents: 3289
diff changeset
447 SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
448
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
449 // ... and merge in other signatures:
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
450 BOOST_FOREACH(const CTransaction& txv, txVariants)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
451 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
452 txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
453 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
454 if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, true, 0))
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
455 fComplete = false;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
456 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
457
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
458 Object result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
459 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
460 ssTx << mergedTx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
461 result.push_back(Pair("hex", HexStr(ssTx.begin(), ssTx.end())));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
462 result.push_back(Pair("complete", fComplete));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
463
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
464 return result;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
465 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
466
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
467 Value sendrawtransaction(const Array& params, bool fHelp)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
468 {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
469 if (fHelp || params.size() < 1 || params.size() > 1)
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
470 throw runtime_error(
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
471 "sendrawtransaction <hex string>\n"
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
472 "Submits raw transaction (serialized, hex-encoded) to local node and network.");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
473
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
474 RPCTypeCheck(params, list_of(str_type));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
475
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
476 // parse hex string from parameter
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
477 vector<unsigned char> txData(ParseHex(params[0].get_str()));
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
478 CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
479 CTransaction tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
480
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
481 // deserialize binary data stream
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
482 try {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
483 ssData >> tx;
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
484 }
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
485 catch (std::exception &e) {
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
486 throw JSONRPCError(-22, "TX decode failed");
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
487 }
3197
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
488 uint256 hashTx = tx.GetHash();
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
489
3197
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
490 // See if the transaction is already in a block
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
491 // or in the memory pool:
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
492 CTransaction existingTx;
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
493 uint256 hashBlock = 0;
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
494 if (GetTransaction(hashTx, existingTx, hashBlock))
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
495 {
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
496 if (hashBlock != 0)
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
497 throw JSONRPCError(-5, string("transaction already in block ")+hashBlock.GetHex());
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
498 // Not in block, but already in the memory pool; will drop
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
499 // through to re-relay it.
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
500 }
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
501 else
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
502 {
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
503 // push to local node
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
504 CTxDB txdb("r");
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
505 if (!tx.AcceptToMemoryPool(txdb))
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
506 throw JSONRPCError(-22, "TX rejected");
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
507
3197
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
508 SyncWithWallets(tx, NULL, true);
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
509 }
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
510 RelayMessage(CInv(MSG_TX, hashTx), tx);
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
511
3197
b63a5263d11a Bug fix: sendrawtransaction was not relaying properly
Gavin Andresen <gavinandresen@gmail.com>
parents: 3156
diff changeset
512 return hashTx.GetHex();
3154
6c1eeeb7e4c2 Implement raw transaction RPC calls
Gavin Andresen <gavinandresen@gmail.com>
parents:
diff changeset
513 }