public bool TrackPrunedTransaction(Transaction transaction, MerkleBlock merkleProof) { var blockHash = this.tumblingState.blockStoreManager.BlockRepository?.GetTrxBlockIdAsync(transaction.GetHash()).Result; var chainBlock = this.tumblingState.chain.GetBlock(blockHash); var block = this.tumblingState.blockStoreManager.BlockRepository?.GetAsync(blockHash).Result; this.tumblingState.walletManager.ProcessTransaction(transaction, chainBlock.Height, block); _Cache.ImportTransaction(transaction, GetBlockConfirmations(merkleProof.Header.GetHash())); return(true); }
private bool TryBroadcastCore(Record tx, int currentHeight, out bool remove) { remove = currentHeight >= tx.Expiration; // Happens when the caller does not know the previous input yet if (tx.Transaction.Inputs.Count == 0 || tx.Transaction.Inputs[0].PrevOut.Hash == uint256.Zero) { return(false); } bool isFinal = tx.Transaction.IsFinal(DateTimeOffset.UtcNow, currentHeight + 1); if (!isFinal || IsDoubleSpend(tx.Transaction)) { return(false); } try { if (!this.tumblingState.walletManager.SendTransaction(tx.Transaction.ToHex())) { return(false); } _Cache.ImportTransaction(tx.Transaction, 0); Logs.Broadcasters.LogInformation($"Broadcasted {tx.Transaction.GetHash()}"); return(true); } // TODO: Change exception type to better reflect use of full node catch (RPCException ex) { if (ex.RPCResult == null || ex.RPCResult.Error == null) { return(false); } var error = ex.RPCResult.Error.Message; if (ex.RPCResult.Error.Code != RPCErrorCode.RPC_TRANSACTION_ALREADY_IN_CHAIN && !error.EndsWith("bad-txns-inputs-spent", StringComparison.OrdinalIgnoreCase) && !error.EndsWith("txn-mempool-conflict", StringComparison.OrdinalIgnoreCase) && !error.EndsWith("Missing inputs", StringComparison.OrdinalIgnoreCase)) { remove = false; } } return(false); }