protected static Coin[] FindUnspentCoins(IEnumerable <Coin> unspents, UInt256 asset_id, Fixed8 amount) { Coin[] unspents_asset = unspents.Where(p => p.Output.AssetId == asset_id).ToArray(); unspents_asset = VerifyTransactionContract.checkUtxo(unspents_asset);//By BHP Fixed8 sum = unspents_asset.Sum(p => p.Output.Value); if (sum < amount) { return(null); } if (sum == amount) { return(unspents_asset); } Coin[] unspents_ordered = unspents_asset.OrderByDescending(p => p.Output.Value).ToArray(); int i = 0; while (unspents_ordered[i].Output.Value <= amount) { amount -= unspents_ordered[i++].Output.Value; } if (amount == Fixed8.Zero) { return(unspents_ordered.Take(i).ToArray()); } else { return(unspents_ordered.Take(i).Concat(new[] { unspents_ordered.Last(p => p.Output.Value >= amount) }).ToArray()); } }
/* * public virtual bool Verify(Snapshot snapshot, IEnumerable<Transaction> mempool) * { * if (Size > MaxTransactionSize) return false; * for (int i = 1; i < Inputs.Length; i++) * for (int j = 0; j < i; j++) * if (Inputs[i].PrevHash == Inputs[j].PrevHash && Inputs[i].PrevIndex == Inputs[j].PrevIndex) * return false; * if (mempool.Where(p => p != this).SelectMany(p => p.Inputs).Intersect(Inputs).Count() > 0) * return false; * if (snapshot.IsDoubleSpend(this)) * return false; * foreach (var group in Outputs.GroupBy(p => p.AssetId)) * { * AssetState asset = snapshot.Assets.TryGet(group.Key); * if (asset == null) return false; * if (asset.Expiration <= snapshot.Height + 1 && asset.AssetType != AssetType.GoverningToken && asset.AssetType != AssetType.UtilityToken) * return false; * foreach (TransactionOutput output in group) * if (output.Value.GetData() % (long)Math.Pow(10, 8 - asset.Precision) != 0) * return false; * } * TransactionResult[] results = GetTransactionResults()?.ToArray(); * if (results == null) return false; * TransactionResult[] results_destroy = results.Where(p => p.Amount > Fixed8.Zero).ToArray(); * if (results_destroy.Length > 1) return false; * if (results_destroy.Length == 1 && results_destroy[0].AssetId != Blockchain.UtilityToken.Hash) * return false; * if (SystemFee > Fixed8.Zero && (results_destroy.Length == 0 || results_destroy[0].Amount < SystemFee)) * return false; * TransactionResult[] results_issue = results.Where(p => p.Amount < Fixed8.Zero).ToArray(); * switch (Type) * { * case TransactionType.MinerTransaction: * case TransactionType.ClaimTransaction: * if (results_issue.Any(p => p.AssetId != Blockchain.UtilityToken.Hash)) * return false; * break; * case TransactionType.IssueTransaction: * if (results_issue.Any(p => p.AssetId == Blockchain.UtilityToken.Hash)) * return false; * break; * default: * if (results_issue.Length > 0) * return false; * break; * } * if (Attributes.Count(p => p.Usage == TransactionAttributeUsage.ECDH02 || p.Usage == TransactionAttributeUsage.ECDH03) > 1) * return false; * if (!VerifyReceivingScripts()) return false; * return this.VerifyWitnesses(snapshot); * } */ public virtual bool Verify(Snapshot snapshot, IEnumerable <Transaction> mempool) { if (Size > MaxTransactionSize) { return(false); } for (int i = 1; i < Inputs.Length; i++) { for (int j = 0; j < i; j++) { if (Inputs[i].PrevHash == Inputs[j].PrevHash && Inputs[i].PrevIndex == Inputs[j].PrevIndex) { return(false); } } } if (mempool.Where(p => p != this).SelectMany(p => p.Inputs).Intersect(Inputs).Count() > 0) { return(false); } if (snapshot.IsDoubleSpend(this)) { return(false); } foreach (var group in Outputs.GroupBy(p => p.AssetId)) { AssetState asset = snapshot.Assets.TryGet(group.Key); if (asset == null) { return(false); } if (asset.Expiration <= snapshot.Height + 1 && asset.AssetType != AssetType.GoverningToken && asset.AssetType != AssetType.UtilityToken) { return(false); } foreach (TransactionOutput output in group) { if (output.Value.GetData() % (long)Math.Pow(10, 8 - asset.Precision) != 0) { return(false); } } } TransactionResult[] results = GetTransactionResults()?.ToArray(); if (results == null) { return(false); } TransactionResult[] results_destroy = results.Where(p => p.Amount > Fixed8.Zero).ToArray(); if (ServiceFee.Verify(this, results_destroy, SystemFee) == false) { return(false); //By BHP } if (SystemFee > Fixed8.Zero && (results_destroy.Length == 0 || results_destroy[0].Amount < SystemFee)) { return(false); } TransactionResult[] results_issue = results.Where(p => p.Amount < Fixed8.Zero).ToArray(); switch (Type) { //By BHP case TransactionType.MinerTransaction: if (VerifyMiningTransaction.Verify(Outputs, Attributes) == false) { return(false); } break; case TransactionType.ClaimTransaction: if (results_issue.Any(p => p.AssetId != Blockchain.UtilityToken.Hash)) { return(false); } break; case TransactionType.IssueTransaction: if (results_issue.Any(p => p.AssetId == Blockchain.UtilityToken.Hash)) { return(false); } break; default: if (results_issue.Length > 0) { return(false); } break; } if (Attributes.Count(p => p.Usage == TransactionAttributeUsage.ECDH02 || p.Usage == TransactionAttributeUsage.ECDH03) > 1) { return(false); } if (!VerifyReceivingScripts()) { return(false); } if (VerifyTransactionContract.Verify(snapshot, this) == false) { return(false); //By BHP } return(this.VerifyWitnesses(snapshot)); }