From de8e801d3f7c61634b4fdec2a389ca36abbd9e9a Mon Sep 17 00:00:00 2001
From: Pieter Wuille <pieter.wuille@gmail.com>
Date: Wed, 3 Dec 2014 14:13:09 +0100
Subject: Report missing inputs in sendrawtransaction

---
 src/rpcrawtransaction.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 1e13f5dbba..ca5aba8759 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -756,11 +756,16 @@ Value sendrawtransaction(const Array& params, bool fHelp)
     if (!fHaveMempool && !fHaveChain) {
         // push to local node and sync with wallets
         CValidationState state;
-        if (!AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) {
-            if(state.IsInvalid())
+        bool fMissingInputs;
+        if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
+            if (state.IsInvalid()) {
                 throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
-            else
+            } else {
+                if (fMissingInputs) {
+                    throw JSONRPCError(RPC_TRANSACTION_ERROR, "Missing inputs");
+                }
                 throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
+            }
         }
     } else if (fHaveChain) {
         throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
-- 
cgit v1.2.3


From bba2216fc14d949e560c83ba0be6cdc3eedfa73f Mon Sep 17 00:00:00 2001
From: Jonas Schnelli <jonas.schnelli@include7.ch>
Date: Mon, 29 Dec 2014 20:17:21 +0100
Subject: RPC test for "#5418 Report missing inputs in sendrawtransaction"

---
 qa/pull-tester/rpc-tests.sh     |  1 +
 qa/rpc-tests/rawtransactions.py | 69 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100755 qa/rpc-tests/rawtransactions.py

diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
index dd2f8d4e5e..caa679e70b 100755
--- a/qa/pull-tester/rpc-tests.sh
+++ b/qa/pull-tester/rpc-tests.sh
@@ -29,6 +29,7 @@ testScripts=(
     'zapwallettxes.py'
     'proxy_test.py'
     'merkle_blocks.py'
+    'rawtransactions.py'
 #    'forknotify.py'
 );
 if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
new file mode 100755
index 0000000000..c02c929d8d
--- /dev/null
+++ b/qa/rpc-tests/rawtransactions.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test re-org scenarios with a mempool that contains transactions
+# that spend (directly or indirectly) coinbase transactions.
+#
+
+from test_framework import BitcoinTestFramework
+from util import *
+from pprint import pprint
+from time import sleep
+
+# Create one-input, one-output, no-fee transaction:
+class RawTransactionsTest(BitcoinTestFramework):
+    
+    def setup_chain(self):
+        print("Initializing test directory "+self.options.tmpdir)
+        initialize_chain_clean(self.options.tmpdir, 3)
+
+    def setup_network(self, split=False):
+        self.nodes = start_nodes(3, self.options.tmpdir)
+
+        #connect to a local machine for debugging
+        #url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18332)
+        #proxy = AuthServiceProxy(url)
+        #proxy.url = url # store URL on proxy for info
+        #self.nodes.append(proxy)
+        
+        connect_nodes_bi(self.nodes,0,1)
+        connect_nodes_bi(self.nodes,1,2)
+        connect_nodes_bi(self.nodes,0,2)
+        
+        self.is_network_split=False
+        self.sync_all()
+    
+    def run_test(self):
+        
+        #prepare some coins for multiple *rawtransaction commands
+        self.nodes[2].generate(1)
+        self.nodes[0].generate(101)
+        self.sync_all()
+        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5);
+        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0);
+        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0);
+        self.sync_all()
+        self.nodes[0].generate(5)
+        self.sync_all()
+
+        #########################################
+        # sendrawtransaction with missing input #
+        #########################################
+        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
+        outputs = { self.nodes[0].getnewaddress() : 4.998 }
+        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
+        rawtx   = self.nodes[2].signrawtransaction(rawtx)
+        
+        errorString = ""
+        try:
+            rawtx   = self.nodes[2].sendrawtransaction(rawtx['hex'])
+        except JSONRPCException,e:
+            errorString = e.error['message']
+        
+        assert_equal("Missing inputs" in errorString, True);        
+
+if __name__ == '__main__':
+    RawTransactionsTest().main()
-- 
cgit v1.2.3