@@ -44,6 +44,8 @@ static CCriticalSection cs_nWalletUnlockTime;
44
44
extern Value dumpprivkey (const Array& params, bool fHelp );
45
45
extern Value importprivkey (const Array& params, bool fHelp );
46
46
47
+ const Object emptyobj;
48
+
47
49
Object JSONRPCError (int code, const string& message)
48
50
{
49
51
Object error;
@@ -111,6 +113,33 @@ HexBits(unsigned int nBits)
111
113
return HexStr (BEGIN (uBits.cBits ), END (uBits.cBits ));
112
114
}
113
115
116
+ enum DecomposeMode {
117
+ DM_NONE = 0 ,
118
+ DM_HASH,
119
+ DM_HEX,
120
+ DM_ASM,
121
+ DM_OBJ,
122
+ };
123
+
124
+ enum DecomposeMode
125
+ FindDecompose (const Object& decompositions, const char * pcType, const char * pcDefault)
126
+ {
127
+ Value val = find_value (decompositions, pcType);
128
+ std::string strDecompose = (val.type () == null_type) ? pcDefault : val.get_str ();
129
+
130
+ if (strDecompose == " no" )
131
+ return DM_NONE;
132
+ if (strDecompose == " hash" )
133
+ return DM_HASH;
134
+ if (strDecompose == " hex" )
135
+ return DM_HEX;
136
+ if (strDecompose == " asm" )
137
+ return DM_ASM;
138
+ if (strDecompose == " obj" )
139
+ return DM_OBJ;
140
+ throw JSONRPCError (-18 , " Invalid decomposition" );
141
+ }
142
+
114
143
void WalletTxToJSON (const CWalletTx& wtx, Object& entry)
115
144
{
116
145
int confirms = wtx.GetDepthInMainChain ();
@@ -126,11 +155,74 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
126
155
entry.push_back (Pair (item.first , item.second ));
127
156
}
128
157
129
- void TxToJSON (const CTransaction &tx, Object& entry)
158
+ void
159
+ ScriptSigToJSON (const CTxIn& txin, Object& out)
160
+ {
161
+ out.push_back (Pair (" asm" , txin.scriptSig .ToString ()));
162
+ out.push_back (Pair (" hex" , HexStr (txin.scriptSig .begin (), txin.scriptSig .end ())));
163
+
164
+ CTransaction txprev;
165
+ uint256 hashTxprevBlock;
166
+ if (!GetTransaction (txin.prevout .hash , txprev, hashTxprevBlock))
167
+ return ;
168
+
169
+ txnouttype type;
170
+ vector<CBitcoinAddress> addresses;
171
+ int nRequired;
172
+
173
+ if (!ExtractAddresses (txprev.vout [txin.prevout .n ].scriptPubKey , type,
174
+ addresses, nRequired))
175
+ {
176
+ out.push_back (Pair (" type" , GetTxnOutputType (TX_NONSTANDARD)));
177
+ return ;
178
+ }
179
+
180
+ out.push_back (Pair (" type" , GetTxnOutputType (type)));
181
+ if (type == TX_MULTISIG)
182
+ {
183
+ // TODO: Need to handle this specially since not all input addresses are required...
184
+ return ;
185
+ }
186
+
187
+ Array a;
188
+ BOOST_FOREACH (const CBitcoinAddress& addr, addresses)
189
+ a.push_back (addr.ToString ());
190
+ out.push_back (Pair (" addresses" , a));
191
+ }
192
+
193
+ void
194
+ ScriptPubKeyToJSON (const CScript& scriptPubKey, Object& out)
195
+ {
196
+ txnouttype type;
197
+ vector<CBitcoinAddress> addresses;
198
+ int nRequired;
199
+
200
+ out.push_back (Pair (" asm" , scriptPubKey.ToString ()));
201
+ out.push_back (Pair (" hex" , HexStr (scriptPubKey.begin (), scriptPubKey.end ())));
202
+
203
+ if (!ExtractAddresses (scriptPubKey, type, addresses, nRequired))
204
+ {
205
+ out.push_back (Pair (" type" , GetTxnOutputType (TX_NONSTANDARD)));
206
+ return ;
207
+ }
208
+
209
+ out.push_back (Pair (" reqSigs" , nRequired));
210
+ out.push_back (Pair (" type" , GetTxnOutputType (type)));
211
+
212
+ Array a;
213
+ BOOST_FOREACH (const CBitcoinAddress& addr, addresses)
214
+ a.push_back (addr.ToString ());
215
+ out.push_back (Pair (" addresses" , a));
216
+ }
217
+
218
+ void TxToJSON (const CTransaction &tx, Object& entry, const Object& decompositions)
130
219
{
131
220
entry.push_back (Pair (" version" , tx.nVersion ));
132
221
entry.push_back (Pair (" locktime" , (boost::int64_t )tx.nLockTime ));
133
222
entry.push_back (Pair (" size" , (boost::int64_t )::GetSerializeSize (tx, SER_NETWORK, PROTOCOL_VERSION)));
223
+
224
+ enum DecomposeMode decomposeScript = FindDecompose (decompositions, " script" , " asm" );
225
+
134
226
Array vin;
135
227
BOOST_FOREACH (const CTxIn& txin, tx.vin )
136
228
{
@@ -143,7 +235,25 @@ void TxToJSON(const CTransaction &tx, Object& entry)
143
235
prevout.push_back (Pair (" hash" , txin.prevout .hash .GetHex ()));
144
236
prevout.push_back (Pair (" n" , (boost::int64_t )txin.prevout .n ));
145
237
in.push_back (Pair (" prevout" , prevout));
146
- in.push_back (Pair (" scriptSig" , txin.scriptSig .ToString ()));
238
+ switch (decomposeScript) {
239
+ case DM_NONE:
240
+ break ;
241
+ case DM_HEX:
242
+ in.push_back (Pair (" scriptSig" , HexStr (txin.scriptSig .begin (), txin.scriptSig .end ())));
243
+ break ;
244
+ case DM_ASM:
245
+ in.push_back (Pair (" scriptSig" , txin.scriptSig .ToString ()));
246
+ break ;
247
+ case DM_OBJ:
248
+ {
249
+ Object o;
250
+ ScriptSigToJSON (txin, o);
251
+ in.push_back (Pair (" scriptSig" , o));
252
+ break ;
253
+ }
254
+ default :
255
+ throw JSONRPCError (-18 , " Invalid script decomposition" );
256
+ }
147
257
}
148
258
in.push_back (Pair (" sequence" , (boost::int64_t )txin.nSequence ));
149
259
vin.push_back (in);
@@ -154,12 +264,32 @@ void TxToJSON(const CTransaction &tx, Object& entry)
154
264
{
155
265
Object out;
156
266
out.push_back (Pair (" value" , ValueFromAmount (txout.nValue )));
157
- out.push_back (Pair (" scriptPubKey" , txout.scriptPubKey .ToString ()));
267
+ switch (decomposeScript) {
268
+ case DM_NONE:
269
+ break ;
270
+ case DM_HEX:
271
+ out.push_back (Pair (" scriptPubKey" , HexStr (txout.scriptPubKey .begin (), txout.scriptPubKey .end ())));
272
+ break ;
273
+ case DM_ASM:
274
+ out.push_back (Pair (" scriptPubKey" , txout.scriptPubKey .ToString ()));
275
+ break ;
276
+ case DM_OBJ:
277
+ {
278
+ Object o;
279
+ ScriptPubKeyToJSON (txout.scriptPubKey , o);
280
+ out.push_back (Pair (" scriptPubKey" , o));
281
+ break ;
282
+ }
283
+ default :
284
+ throw JSONRPCError (-18 , " Invalid script decomposition" );
285
+ }
158
286
vout.push_back (out);
159
287
}
160
288
entry.push_back (Pair (" vout" , vout));
161
289
}
162
290
291
+ void AnyTxToJSON (const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions);
292
+
163
293
string AccountFromValue (const Value& value)
164
294
{
165
295
string strAccount = value.get_str ();
@@ -168,10 +298,13 @@ string AccountFromValue(const Value& value)
168
298
return strAccount;
169
299
}
170
300
171
- Object blockToJSON (const CBlock& block, const CBlockIndex* blockindex)
301
+ Object blockToJSON (const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions )
172
302
{
173
303
Object result;
174
304
result.push_back (Pair (" hash" , block.GetHash ().GetHex ()));
305
+ CMerkleTx txGen (block.vtx [0 ]);
306
+ txGen.SetMerkleBranch (&block);
307
+ result.push_back (Pair (" confirmations" , (int )txGen.GetDepthInMainChain ()));
175
308
result.push_back (Pair (" size" , (int )::GetSerializeSize (block, SER_NETWORK, PROTOCOL_VERSION)));
176
309
result.push_back (Pair (" height" , blockindex->nHeight ));
177
310
result.push_back (Pair (" version" , block.nVersion ));
@@ -180,10 +313,38 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
180
313
result.push_back (Pair (" nonce" , (boost::uint64_t )block.nNonce ));
181
314
result.push_back (Pair (" bits" , HexBits (block.nBits )));
182
315
result.push_back (Pair (" difficulty" , GetDifficulty (blockindex)));
183
- Array txhashes;
184
- BOOST_FOREACH (const CTransaction&tx, block.vtx )
185
- txhashes.push_back (tx.GetHash ().GetHex ());
186
- result.push_back (Pair (" tx" , txhashes));
316
+
317
+ enum DecomposeMode decomposeTxn = FindDecompose (decompositions, " tx" , " hash" );
318
+ if (decomposeTxn)
319
+ {
320
+ Array txs;
321
+ switch (decomposeTxn) {
322
+ case DM_OBJ:
323
+ BOOST_FOREACH (const CTransaction&tx, block.vtx )
324
+ {
325
+ Object entry;
326
+ AnyTxToJSON (tx.GetHash (), &tx, entry, decompositions);
327
+ txs.push_back (entry);
328
+ }
329
+ break ;
330
+ case DM_HEX:
331
+ BOOST_FOREACH (const CTransaction&tx, block.vtx )
332
+ {
333
+ CDataStream ssTx (SER_NETWORK, PROTOCOL_VERSION);
334
+ ssTx << tx;
335
+
336
+ txs.push_back (HexStr (ssTx.begin (), ssTx.end ()));
337
+ }
338
+ break ;
339
+ case DM_HASH:
340
+ BOOST_FOREACH (const CTransaction&tx, block.vtx )
341
+ txs.push_back (tx.GetHash ().GetHex ());
342
+ break ;
343
+ default :
344
+ throw JSONRPCError (-18 , " Invalid transaction decomposition" );
345
+ }
346
+ result.push_back (Pair (" tx" , txs));
347
+ }
187
348
188
349
if (blockindex->pprev )
189
350
result.push_back (Pair (" previousblockhash" , blockindex->pprev ->GetBlockHash ().GetHex ()));
@@ -194,6 +355,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
194
355
195
356
196
357
358
+
197
359
// /
198
360
// / Note: This interface may still be subject to change.
199
361
// /
@@ -1498,23 +1660,14 @@ Value listsinceblock(const Array& params, bool fHelp)
1498
1660
return ret;
1499
1661
}
1500
1662
1501
- Value gettransaction (const Array& params, bool fHelp )
1663
+ void
1664
+ AnyTxToJSON (const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions)
1502
1665
{
1503
- if (fHelp || params.size () != 1 )
1504
- throw runtime_error (
1505
- " gettransaction <txid>\n "
1506
- " Get detailed information about <txid>" );
1507
-
1508
- uint256 hash;
1509
- hash.SetHex (params[0 ].get_str ());
1510
-
1511
- Object entry;
1512
-
1513
1666
if (pwalletMain->mapWallet .count (hash))
1514
1667
{
1515
1668
const CWalletTx& wtx = pwalletMain->mapWallet [hash];
1516
1669
1517
- TxToJSON (wtx, entry);
1670
+ TxToJSON (wtx, entry, decompositions );
1518
1671
1519
1672
int64 nCredit = wtx.GetCredit ();
1520
1673
int64 nDebit = wtx.GetDebit ();
@@ -1535,10 +1688,12 @@ Value gettransaction(const Array& params, bool fHelp)
1535
1688
{
1536
1689
CTransaction tx;
1537
1690
uint256 hashBlock = 0 ;
1538
- if (GetTransaction (hash, tx, hashBlock))
1691
+ if ((!ptx) && GetTransaction (hash, tx, hashBlock))
1692
+ ptx = &tx;
1693
+ if (ptx)
1539
1694
{
1540
1695
entry.push_back (Pair (" txid" , hash.GetHex ()));
1541
- TxToJSON (tx , entry);
1696
+ TxToJSON (*ptx , entry, decompositions );
1542
1697
if (hashBlock == 0 )
1543
1698
entry.push_back (Pair (" confirmations" , 0 ));
1544
1699
else
@@ -1561,6 +1716,22 @@ Value gettransaction(const Array& params, bool fHelp)
1561
1716
else
1562
1717
throw JSONRPCError (-5 , " No information available about transaction" );
1563
1718
}
1719
+ }
1720
+
1721
+ Value gettransaction (const Array& params, bool fHelp )
1722
+ {
1723
+ if (fHelp || params.size () < 1 || params.size () > 2 )
1724
+ throw runtime_error (
1725
+ " gettransaction <txid> [decompositions]\n "
1726
+ " Get detailed information about <txid>" );
1727
+
1728
+ uint256 hash;
1729
+ hash.SetHex (params[0 ].get_str ());
1730
+
1731
+ Object entry;
1732
+
1733
+ AnyTxToJSON (hash, NULL , entry,
1734
+ (params.size () > 1 ) ? params[1 ].get_obj () : emptyobj);
1564
1735
1565
1736
return entry;
1566
1737
}
@@ -2042,9 +2213,9 @@ Value getblockhash(const Array& params, bool fHelp)
2042
2213
2043
2214
Value getblock (const Array& params, bool fHelp )
2044
2215
{
2045
- if (fHelp || params.size () != 1 )
2216
+ if (fHelp || params.size () < 1 || params. size () > 2 )
2046
2217
throw runtime_error (
2047
- " getblock <hash>\n "
2218
+ " getblock <hash> [decompositions] \n "
2048
2219
" Returns details of a block with given block-hash." );
2049
2220
2050
2221
std::string strHash = params[0 ].get_str ();
@@ -2057,7 +2228,8 @@ Value getblock(const Array& params, bool fHelp)
2057
2228
CBlockIndex* pblockindex = mapBlockIndex[hash];
2058
2229
block.ReadFromDisk (pblockindex, true );
2059
2230
2060
- return blockToJSON (block, pblockindex);
2231
+ return blockToJSON (block, pblockindex,
2232
+ (params.size () > 1 ) ? params[1 ].get_obj () : emptyobj);
2061
2233
}
2062
2234
2063
2235
@@ -2715,7 +2887,9 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
2715
2887
if (strMethod == " listreceivedbyaccount" && n > 0 ) ConvertTo<boost::int64_t >(params[0 ]);
2716
2888
if (strMethod == " listreceivedbyaccount" && n > 1 ) ConvertTo<bool >(params[1 ]);
2717
2889
if (strMethod == " getbalance" && n > 1 ) ConvertTo<boost::int64_t >(params[1 ]);
2890
+ if (strMethod == " getblock" && n > 1 ) ConvertTo<Object>(params[1 ]);
2718
2891
if (strMethod == " getblockhash" && n > 0 ) ConvertTo<boost::int64_t >(params[0 ]);
2892
+ if (strMethod == " gettransaction" && n > 1 ) ConvertTo<Object>(params[1 ]);
2719
2893
if (strMethod == " move" && n > 2 ) ConvertTo<double >(params[2 ]);
2720
2894
if (strMethod == " move" && n > 3 ) ConvertTo<boost::int64_t >(params[3 ]);
2721
2895
if (strMethod == " sendfrom" && n > 2 ) ConvertTo<double >(params[2 ]);
0 commit comments