Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/rawtransaction.cpp
Show First 20 Lines • Show All 280 Lines • ▼ Show 20 Lines | if (request.fHelp || | ||||
" ]\n" | " ]\n" | ||||
"2. \"blockhash\" (string, optional) If specified, looks for " | "2. \"blockhash\" (string, optional) If specified, looks for " | ||||
"txid in the block with this hash\n" | "txid in the block with this hash\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"\"data\" (string) A string that is a serialized, " | "\"data\" (string) A string that is a serialized, " | ||||
"hex-encoded data for the proof.\n"); | "hex-encoded data for the proof.\n"); | ||||
} | } | ||||
std::set<uint256> setTxids; | std::set<TxId> setTxIds; | ||||
uint256 oneTxid; | TxId oneTxId; | ||||
UniValue txids = request.params[0].get_array(); | UniValue txids = request.params[0].get_array(); | ||||
for (unsigned int idx = 0; idx < txids.size(); idx++) { | for (unsigned int idx = 0; idx < txids.size(); idx++) { | ||||
jasonbcox: Use a range-based loop | |||||
deadalnixAuthorUnsubmitted Not Done Inline Actionsunivalue is not iterrable. deadalnix: univalue is not iterrable. | |||||
const UniValue &txid = txids[idx]; | const UniValue &utxid = txids[idx]; | ||||
if (txid.get_str().length() != 64 || !IsHex(txid.get_str())) { | if (utxid.get_str().length() != 64 || !IsHex(utxid.get_str())) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
std::string("Invalid txid ") + txid.get_str()); | std::string("Invalid txid ") + utxid.get_str()); | ||||
} | } | ||||
uint256 hash(uint256S(txid.get_str())); | TxId txid(uint256S(utxid.get_str())); | ||||
if (setTxids.count(hash)) { | if (setTxIds.count(txid)) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
std::string("Invalid parameter, duplicated txid: ") + | std::string("Invalid parameter, duplicated txid: ") + | ||||
txid.get_str()); | utxid.get_str()); | ||||
} | } | ||||
setTxids.insert(hash); | setTxIds.insert(txid); | ||||
oneTxid = hash; | oneTxId = txid; | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = nullptr; | CBlockIndex *pblockindex = nullptr; | ||||
uint256 hashBlock; | uint256 hashBlock; | ||||
if (request.params.size() > 1) { | if (request.params.size() > 1) { | ||||
hashBlock = uint256S(request.params[1].get_str()); | hashBlock = uint256S(request.params[1].get_str()); | ||||
if (!mapBlockIndex.count(hashBlock)) | if (!mapBlockIndex.count(hashBlock)) | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
pblockindex = mapBlockIndex[hashBlock]; | pblockindex = mapBlockIndex[hashBlock]; | ||||
} else { | } else { | ||||
// Loop through txids and try to find which block they're in. Exit loop | // Loop through txids and try to find which block they're in. Exit loop | ||||
// once a block is found. | // once a block is found. | ||||
for (const auto &tx : setTxids) { | for (const auto &txid : setTxIds) { | ||||
const Coin &coin = AccessByTxid(*pcoinsTip, tx); | const Coin &coin = AccessByTxid(*pcoinsTip, txid); | ||||
if (!coin.IsSpent()) { | if (!coin.IsSpent()) { | ||||
pblockindex = chainActive[coin.GetHeight()]; | pblockindex = chainActive[coin.GetHeight()]; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (pblockindex == nullptr) { | if (pblockindex == nullptr) { | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
if (!GetTransaction(config, oneTxid, tx, hashBlock, false) || | if (!GetTransaction(config, oneTxId, tx, hashBlock, false) || | ||||
hashBlock.IsNull()) { | hashBlock.IsNull()) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Transaction not yet in block"); | "Transaction not yet in block"); | ||||
} | } | ||||
if (!mapBlockIndex.count(hashBlock)) { | if (!mapBlockIndex.count(hashBlock)) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); | ||||
} | } | ||||
pblockindex = mapBlockIndex[hashBlock]; | pblockindex = mapBlockIndex[hashBlock]; | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pblockindex, config)) { | if (!ReadBlockFromDisk(block, pblockindex, config)) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); | ||||
} | } | ||||
unsigned int ntxFound = 0; | unsigned int ntxFound = 0; | ||||
for (const auto &tx : block.vtx) { | for (const auto &tx : block.vtx) { | ||||
if (setTxids.count(tx->GetId())) { | if (setTxIds.count(tx->GetId())) { | ||||
ntxFound++; | ntxFound++; | ||||
} | } | ||||
} | } | ||||
if (ntxFound != setTxids.size()) { | if (ntxFound != setTxIds.size()) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_ADDRESS_OR_KEY, | RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Not all transactions found in specified or retrieved block"); | "Not all transactions found in specified or retrieved block"); | ||||
} | } | ||||
CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); | ||||
CMerkleBlock mb(block, setTxids); | CMerkleBlock mb(block, setTxIds); | ||||
ssMB << mb; | ssMB << mb; | ||||
std::string strHex = HexStr(ssMB.begin(), ssMB.end()); | std::string strHex = HexStr(ssMB.begin(), ssMB.end()); | ||||
return strHex; | return strHex; | ||||
} | } | ||||
static UniValue verifytxoutproof(const Config &config, | static UniValue verifytxoutproof(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | if (request.fHelp || request.params.size() != 1) { | ||||
▲ Show 20 Lines • Show All 821 Lines • Show Last 20 Lines |
Use a range-based loop