public void Abs_ProvidePositiveFixed8_ReturnTheSameValue() { var positiveFixed8 = new Fixed8(1); var resultAbsoluteFixed8 = positiveFixed8.Abs(); Asserting .That(resultAbsoluteFixed8) .IsEqual(positiveFixed8); }
public void Abs_ProvideNegativeFixed8_ReturnPositiveVersionOfTheFixed8() { var negativeFixed8 = new Fixed8(-1); var expectedPositiveLongValue = negativeFixed8.Value * -1; var resultAbsoluteFixed8 = negativeFixed8.Abs(); Asserting .That(resultAbsoluteFixed8) .AsLongValue(expectedPositiveLongValue); }
//TODO: 此处需要较多的测试来证明它的正确性 //因为委托交易的验证算法有点太复杂了, //考虑未来是否可以优化这个算法 public override bool Verify() { if (!base.Verify()) { return(false); } foreach (Order order in Orders) { if (!order.VerifySignature()) { return(false); } } RegisterTransaction asset_value = Blockchain.Default.GetTransaction(ValueAssetId) as RegisterTransaction; if (asset_value?.AssetType != AssetType.Currency) { return(false); } List <Order> orders = new List <Order>(Orders); foreach (var group in Inputs.GroupBy(p => p.PrevHash)) { Transaction tx = Blockchain.Default.GetTransaction(group.Key); if (tx == null) { return(false); } AgencyTransaction tx_agency = tx as AgencyTransaction; if (tx_agency?.SplitOrder == null || tx_agency.AssetId != AssetId || tx_agency.ValueAssetId != ValueAssetId || tx_agency.Agent != Agent) { continue; } var outputs = group.Select(p => new { Input = p, Output = tx_agency.Outputs[p.PrevIndex] }).Where(p => p.Output.ScriptHash == tx_agency.SplitOrder.Client).ToDictionary(p => p.Input, p => p.Output); if (outputs.Count == 0) { continue; } if (outputs.Count != tx_agency.Outputs.Count(p => p.ScriptHash == tx_agency.SplitOrder.Client)) { return(false); } orders.Add(new Order { AssetId = this.AssetId, ValueAssetId = this.ValueAssetId, Agent = this.Agent, Amount = tx_agency.SplitOrder.Amount, Price = tx_agency.SplitOrder.Price, Client = tx_agency.SplitOrder.Client, Inputs = outputs.Keys.ToArray() }); } if (orders.Count < 2) { return(false); } if (orders.Count(p => p.Amount > Fixed8.Zero) == 0 || orders.Count(p => p.Amount < Fixed8.Zero) == 0) { return(false); } Fixed8 amount_unmatched = orders.Sum(p => p.Amount); if (amount_unmatched == Fixed8.Zero) { if (SplitOrder != null) { return(false); } } else { if (SplitOrder?.Amount != amount_unmatched) { return(false); } } foreach (Order order in orders) { TransactionOutput[] inputs = order.Inputs.Select(p => References[p]).ToArray(); if (order.Amount > Fixed8.Zero) { if (inputs.Any(p => p.AssetId != order.ValueAssetId)) { return(false); } if (inputs.Sum(p => p.Value) < order.Amount * order.Price) { return(false); } } else { if (inputs.Any(p => p.AssetId != order.AssetId)) { return(false); } if (inputs.Sum(p => p.Value) < order.Amount) { return(false); } } } if (SplitOrder != null) { Fixed8 price_worst = amount_unmatched > Fixed8.Zero ? orders.Min(p => p.Price) : orders.Max(p => p.Price); if (SplitOrder.Price != price_worst) { return(false); } Order[] orders_worst = orders.Where(p => p.Price == price_worst && p.Client == SplitOrder.Client).ToArray(); if (orders_worst.Length == 0) { return(false); } Fixed8 amount_worst = orders_worst.Sum(p => p.Amount); if (amount_worst.Abs() < amount_unmatched.Abs()) { return(false); } Order order_combine = new Order { AssetId = this.AssetId, ValueAssetId = this.ValueAssetId, Agent = this.Agent, Amount = amount_worst - amount_unmatched, Price = price_worst, Client = SplitOrder.Client, Inputs = orders_worst.SelectMany(p => p.Inputs).ToArray() }; foreach (Order order_worst in orders_worst) { orders.Remove(order_worst); } orders.Add(order_combine); } foreach (var group in orders.GroupBy(p => p.Client)) { TransactionOutput[] inputs = group.SelectMany(p => p.Inputs).Select(p => References[p]).ToArray(); TransactionOutput[] outputs = Outputs.Where(p => p.ScriptHash == group.Key).ToArray(); Fixed8 money_spent = inputs.Where(p => p.AssetId == ValueAssetId).Sum(p => p.Value) - outputs.Where(p => p.AssetId == ValueAssetId).Sum(p => p.Value); Fixed8 amount_changed = outputs.Where(p => p.AssetId == AssetId).Sum(p => p.Value) - inputs.Where(p => p.AssetId == AssetId).Sum(p => p.Value); if (amount_changed != group.Sum(p => p.Amount)) { return(false); } if (money_spent > group.Sum(p => p.Amount * p.Price)) { return(false); } } return(true); }