Browse Source

gettransaction RPC for non-wallet transactions

Works for wallet transactions, memory-pool transaction and block chain
transactions.

Available for all:
 * txid
 * version
 * locktime
 * size
 * coinbase/inputs/outputs
 * confirmations

Available only for wallet transactions:
 * amount
 * fee
 * details
 * blockindex

Available for wallet transactions and block chain transactions:
 * blockhash
 * time
miguelfreitas
Pieter Wuille 13 years ago
parent
commit
c73ba23eb5
  1. 95
      src/bitcoinrpc.cpp
  2. 26
      src/main.cpp
  3. 2
      src/main.h

95
src/bitcoinrpc.cpp

@ -130,6 +130,40 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second)); entry.push_back(Pair(item.first, item.second));
} }
void TxToJSON(const CTransaction &tx, Object& entry)
{
entry.push_back(Pair("version", tx.nVersion));
entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
Array vin;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
Object in;
if (tx.IsCoinBase())
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
else
{
Object prevout;
prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
in.push_back(Pair("prevout", prevout));
in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
}
in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
vin.push_back(in);
}
entry.push_back(Pair("vin", vin));
Array vout;
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
Object out;
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
vout.push_back(out);
}
entry.push_back(Pair("vout", vout));
}
string AccountFromValue(const Value& value) string AccountFromValue(const Value& value)
{ {
string strAccount = value.get_str(); string strAccount = value.get_str();
@ -1472,24 +1506,57 @@ Value gettransaction(const Array& params, bool fHelp)
Object entry; Object entry;
if (!pwalletMain->mapWallet.count(hash)) if (pwalletMain->mapWallet.count(hash))
throw JSONRPCError(-5, "Invalid or non-wallet transaction id"); {
const CWalletTx& wtx = pwalletMain->mapWallet[hash]; const CWalletTx& wtx = pwalletMain->mapWallet[hash];
TxToJSON(wtx, entry);
int64 nCredit = wtx.GetCredit(); int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit(); int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit; int64 nNet = nCredit - nDebit;
int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
if (wtx.IsFromMe()) if (wtx.IsFromMe())
entry.push_back(Pair("fee", ValueFromAmount(nFee))); entry.push_back(Pair("fee", ValueFromAmount(nFee)));
WalletTxToJSON(pwalletMain->mapWallet[hash], entry); WalletTxToJSON(wtx, entry);
Array details; Array details;
ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details); ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
entry.push_back(Pair("details", details)); entry.push_back(Pair("details", details));
}
else
{
CTransaction tx;
uint256 hashBlock = 0;
if (GetTransaction(hash, tx, hashBlock))
{
entry.push_back(Pair("txid", hash.GetHex()));
TxToJSON(tx, entry);
if (hashBlock == 0)
entry.push_back(Pair("confirmations", 0));
else
{
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
if (mi != mapBlockIndex.end() && (*mi).second)
{
CBlockIndex* pindex = (*mi).second;
if (pindex->IsInMainChain())
{
entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
}
else
entry.push_back(Pair("confirmations", 0));
}
}
}
else
throw JSONRPCError(-5, "No information available about transaction");
}
return entry; return entry;
} }

26
src/main.cpp

@ -733,7 +733,31 @@ int CTxIndex::GetDepthInMainChain() const
return 1 + nBestHeight - pindex->nHeight; return 1 + nBestHeight - pindex->nHeight;
} }
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
{
{
LOCK(cs_main);
{
LOCK(mempool.cs);
if (mempool.exists(hash))
{
tx = mempool.lookup(hash);
return true;
}
}
CTxDB txdb("r");
CTxIndex txindex;
if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex))
{
CBlock block;
if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
hashBlock = block.GetHash();
return true;
}
}
return false;
}

2
src/main.h

@ -101,7 +101,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
int GetNumBlocksOfPeers(); int GetNumBlocksOfPeers();
bool IsInitialBlockDownload(); bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor); std::string GetWarnings(std::string strFor);
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);

Loading…
Cancel
Save