/// <inheritdoc /> public bool ValidateTransaction(Transaction transaction, bool checkSignature = false) { lock (this.lockObject) { // All the input UTXO's should be present in spending details of the multi-sig address. List <Coin> coins = checkSignature ? new List <Coin>() : null; // Verify that the transaction has valid UTXOs. if (!this.TransactionHasValidUTXOs(transaction, coins)) { return(false); } // Verify that there are no earlier unspent UTXOs. Comparer <TransactionData> comparer = Comparer <TransactionData> .Create(DeterministicCoinOrdering.CompareTransactionData); TransactionData earliestUnspent = this.Wallet.MultiSigAddress.Transactions.Where(t => t.SpendingDetails == null).OrderBy(t => t, comparer).FirstOrDefault(); if (earliestUnspent != null) { TransactionData oldestInput = transaction.Inputs .Where(i => this.outpointLookup.ContainsKey(i.PrevOut)) .Select(i => this.outpointLookup[i.PrevOut]) .OrderByDescending(t => t, comparer) .FirstOrDefault(); if (oldestInput != null && DeterministicCoinOrdering.CompareTransactionData(earliestUnspent, oldestInput) < 0) { return(false); } } // Verify that all inputs are signed. if (checkSignature) { TransactionBuilder builder = new TransactionBuilder(this.Wallet.Network).AddCoins(coins); if (!builder.Verify(transaction, this.federationGatewaySettings.TransactionFee, out TransactionPolicyError[] errors))
/// <inheritdoc /> public int CompareOutpoints(OutPoint outPoint1, OutPoint outPoint2) { lock (this.lockObject) { TransactionData transactionData1 = this.outpointLookup[outPoint1]; TransactionData transactionData2 = this.outpointLookup[outPoint2]; return(DeterministicCoinOrdering.CompareTransactionData(transactionData1, transactionData2)); } }