'sendrawtransaction' improvements

- Make it report the reject code and reason
- Make it possible to re-send transactions that are already in the mempool
This commit is contained in:
Wladimir J. van der Laan 2014-02-22 12:02:42 +01:00
parent ebb783a9f2
commit 1d46fe3327
2 changed files with 17 additions and 16 deletions

View File

@ -49,6 +49,9 @@ enum RPCErrorCode
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
RPC_DATABASE_ERROR = -20, // Database error RPC_DATABASE_ERROR = -20, // Database error
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
RPC_TRANSACTION_ERROR = -25, // General error during transaction submission
RPC_TRANSACTION_REJECTED = -26, // Transaction was rejected by network rules
RPC_TRANSACTION_ALREADY_IN_CHAIN= -27, // Transaction already in chain
// P2P client errors // P2P client errors
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected

View File

@ -777,25 +777,23 @@ Value sendrawtransaction(const Array& params, bool fHelp)
} }
uint256 hashTx = tx.GetHash(); uint256 hashTx = tx.GetHash();
bool fHave = false;
CCoinsViewCache &view = *pcoinsTip; CCoinsViewCache &view = *pcoinsTip;
CCoins existingCoins; CCoins existingCoins;
{ bool fHaveMempool = mempool.exists(hashTx);
fHave = view.GetCoins(hashTx, existingCoins); bool fHaveChain = view.GetCoins(hashTx, existingCoins) && existingCoins.nHeight < 1000000000;
if (!fHave) { if (!fHaveMempool && !fHaveChain) {
// push to local node // push to local node and sync with wallets
CValidationState state; CValidationState state;
if (!AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees))
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); // TODO: report validation state SyncWithWallets(hashTx, tx, NULL);
else {
if(state.IsInvalid())
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
else
throw JSONRPCError(RPC_TRANSACTION_ERROR, state.GetRejectReason());
} }
} } else if (fHaveChain) {
if (fHave) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
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 {
SyncWithWallets(hashTx, tx, NULL);
} }
RelayTransaction(tx, hashTx); RelayTransaction(tx, hashTx);