aboutsummaryrefslogtreecommitdiff
path: root/src/rpcrawtransaction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpcrawtransaction.cpp')
-rw-r--r--src/rpcrawtransaction.cpp87
1 files changed, 43 insertions, 44 deletions
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index cb5bae62da..c62898316c 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -118,7 +118,7 @@ Value getrawtransaction(const Array& params, bool fHelp)
CTransaction tx;
uint256 hashBlock = 0;
- if (!GetTransaction(hash, tx, hashBlock))
+ if (!GetTransaction(hash, tx, hashBlock, true))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
@@ -335,26 +335,22 @@ Value signrawtransaction(const Array& params, bool fHelp)
bool fComplete = true;
// Fetch previous transactions (inputs):
- map<COutPoint, CScript> mapPrevOut;
- for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
+ CCoinsView viewDummy;
+ CCoinsViewCache view(viewDummy);
{
- CTransaction tempTx;
- MapPrevTx mapPrevTx;
- CTxDB txdb("r");
- map<uint256, CTxIndex> unused;
- bool fInvalid;
-
- // FetchInputs aborts on failure, so we go one at a time.
- tempTx.vin.push_back(mergedTx.vin[i]);
- tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid);
-
- // Copy results into mapPrevOut:
- BOOST_FOREACH(const CTxIn& txin, tempTx.vin)
- {
+ LOCK(mempool.cs);
+ CCoinsDB coinsdb("r");
+ CCoinsViewDB viewDB(coinsdb);
+ CCoinsViewMemPool viewMempool(viewDB, mempool);
+ view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view
+
+ BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
const uint256& prevHash = txin.prevout.hash;
- if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n)
- mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey;
+ CCoins coins;
+ view.GetCoins(prevHash, coins); // this is certainly allowed to fail
}
+
+ view.SetBackend(viewDummy); // switch back to avoid locking db/mempool too long
}
// Add previous txouts given in the RPC call:
@@ -386,20 +382,19 @@ Value signrawtransaction(const Array& params, bool fHelp)
vector<unsigned char> pkData(ParseHex(pkHex));
CScript scriptPubKey(pkData.begin(), pkData.end());
- COutPoint outpoint(txid, nOut);
- if (mapPrevOut.count(outpoint))
- {
- // Complain if scriptPubKey doesn't match
- if (mapPrevOut[outpoint] != scriptPubKey)
- {
+ CCoins coins;
+ if (view.GetCoins(txid, coins)) {
+ if (coins.IsAvailable(nOut) && coins.vout[nOut].scriptPubKey != scriptPubKey) {
string err("Previous output scriptPubKey mismatch:\n");
- err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+
+ err = err + coins.vout[nOut].scriptPubKey.ToString() + "\nvs:\n"+
scriptPubKey.ToString();
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
}
+ // what todo if txid is known, but the actual output isn't?
}
- else
- mapPrevOut[outpoint] = scriptPubKey;
+ coins.vout[nOut].scriptPubKey = scriptPubKey;
+ coins.vout[nOut].nValue = 0; // we don't know the actual output value
+ view.SetCoins(txid, coins);
}
}
@@ -452,12 +447,13 @@ Value signrawtransaction(const Array& params, bool fHelp)
for (unsigned int i = 0; i < mergedTx.vin.size(); i++)
{
CTxIn& txin = mergedTx.vin[i];
- if (mapPrevOut.count(txin.prevout) == 0)
+ CCoins coins;
+ if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n))
{
fComplete = false;
continue;
}
- const CScript& prevPubKey = mapPrevOut[txin.prevout];
+ const CScript& prevPubKey = coins.vout[txin.prevout.n].scriptPubKey;
txin.scriptSig.clear();
// Only sign SIGHASH_SINGLE if there's a corresponding output:
@@ -505,24 +501,27 @@ Value sendrawtransaction(const Array& params, bool fHelp)
}
uint256 hashTx = tx.GetHash();
- // See if the transaction is already in a block
- // or in the memory pool:
- CTransaction existingTx;
- uint256 hashBlock = 0;
- if (GetTransaction(hashTx, existingTx, hashBlock))
+ bool fHave = false;
+ CCoins existingCoins;
{
- if (hashBlock != 0)
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex());
+ CCoinsDB coinsdb("r");
+ {
+ CCoinsViewDB coinsviewDB(coinsdb);
+ CCoinsViewMemPool coinsview(coinsviewDB, mempool);
+ fHave = coinsview.GetCoins(hashTx, existingCoins);
+ }
+ if (!fHave) {
+ // push to local node
+ if (!tx.AcceptToMemoryPool(coinsdb))
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
+ }
+ }
+ if (fHave) {
+ if (existingCoins.nHeight < 1000000000)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "transaction already in block chain");
// Not in block, but already in the memory pool; will drop
// through to re-relay it.
- }
- else
- {
- // push to local node
- CTxDB txdb("r");
- if (!tx.AcceptToMemoryPool(txdb))
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected");
-
+ } else {
SyncWithWallets(tx, NULL, true);
}
RelayMessage(CInv(MSG_TX, hashTx), tx);