diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp --- a/bitcoin/src/bitcoinrpc.cpp a71655bcd21408123e7be15f91803707bafca212787544d3e160855c170d596029847dc35ecd0f4dbe10f8e412bee114fba803d4e369c980d06691373106c18d +++ b/bitcoin/src/bitcoinrpc.cpp 12aaa6edce4f59b929ca6fd4c714e1be798b42c2293934d0861ee5cb300cc60d0320cbc5f4550fd7ed16af793e48b6dd84eb762e57ea458d93386cfcc0d45a50 @@ -1851,6 +1851,50 @@ return false; } +Value sendrawtransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "sendrawtransaction \n" + "Submits raw transaction (serialized, hex-encoded) to local node and network."); + + vector txData(ParseHex(params[0].get_str())); + CDataStream ssData(txData, SER_NETWORK, VERSION); + CTransaction tx; + + try { + ssData >> tx; + } + catch (std::exception &e) { + throw JSONRPCError(-22, "tx decode failed"); + } + + CTxDB txdb("r"); + uint256 txHash = tx.GetHash(); + uint256 hashBlock = 0; + + if (TransactionSeen(txHash, hashBlock)) + { + throw JSONRPCError(-5, string("tx already ") + + (hashBlock != 0 ? + string("included in block ") + hashBlock.ToString() : + "in memory pool")); + } + + bool fMissingInputs = false; + + if (!tx.AcceptToMemoryPool(txdb, true, &fMissingInputs) || fMissingInputs) + { + throw JSONRPCError(-22, string("tx rejected") + + (fMissingInputs ? ", missing inputs" : "")); + } + + SyncWithWallets(tx, NULL, true); + CInv inv(MSG_TX, txHash); + RelayMessage(inv, tx); + + return txHash.GetHex(); +} Value eatblock(const Array& params, bool fHelp) { @@ -1922,6 +1966,7 @@ make_pair("settxfee", &settxfee), make_pair("getmemorypool", &getmemorypool), make_pair("listsinceblock", &listsinceblock), + make_pair("sendrawtransaction", &sendrawtransaction), make_pair("dumpblock", &dumpblock), make_pair("eatblock", &eatblock), }; diff -uNr a/bitcoin/src/main.cpp b/bitcoin/src/main.cpp --- a/bitcoin/src/main.cpp 0ccb0c29c0a3217d57f9bc72d87b497e64116a9f79e69277408750ee3dc95738ce52a70afece7a1054314100d84f93f6525ab514b8abd8ce78ab8ebd50e599a2 +++ b/bitcoin/src/main.cpp 738ea5d28c72b586790716c124d219b8b132c5224ce07cc3b47eab4495e2c9009eae1a7d7fa3faaa24de465d5a46201dc1c4a468ab5a891cb59811d328b82084 @@ -98,6 +98,28 @@ return false; } +// return wether a given transaction is found on mempool or already included in a block +bool TransactionSeen(const uint256 &hash, uint256 &hashBlock) +{ + CRITICAL_BLOCK(cs_mapTransactions) + if (mapTransactions.count(hash)) + return true; + + CTransaction tx; + 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; +} + // erases transaction with the given hash from all wallets void static EraseFromWallets(uint256 hash) { @@ -106,7 +128,7 @@ } // make sure all wallets know about the given transaction, in the given block -void static SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false) +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate); diff -uNr a/bitcoin/src/main.h b/bitcoin/src/main.h --- a/bitcoin/src/main.h ff2bf8f8147dd8df5e1ef1bcea9b0159d3f83c1e30befef56415b99305aa99161ac1c05efb48be87a383ffb6d621fd3761bfb3e4952ca244a6e1398ca3c71dc6 +++ b/bitcoin/src/main.h 854e85a8217f8386fa7ec13775fdf7271a41a0132816f1a64acd40904b4b8300491dd368a26648afb11af019f0bdcc535ca327c19eaca698803f3afdd57b76d8 @@ -79,6 +79,8 @@ void RegisterWallet(CWallet* pwalletIn); void UnregisterWallet(CWallet* pwalletIn); +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false); +bool TransactionSeen(const uint256 &hash, uint256 &hashBlock); bool ProcessBlock(CNode* pfrom, CBlock* pblock); bool CheckDiskSpace(uint64 nAdditionalBytes=0); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");