Ejemplo n.º 1
0
        public void Abs_ProvidePositiveFixed8_ReturnTheSameValue()
        {
            var positiveFixed8 = new Fixed8(1);

            var resultAbsoluteFixed8 = positiveFixed8.Abs();

            Asserting
            .That(resultAbsoluteFixed8)
            .IsEqual(positiveFixed8);
        }
Ejemplo n.º 2
0
        public void Abs_ProvideNegativeFixed8_ReturnPositiveVersionOfTheFixed8()
        {
            var negativeFixed8            = new Fixed8(-1);
            var expectedPositiveLongValue = negativeFixed8.Value * -1;

            var resultAbsoluteFixed8 = negativeFixed8.Abs();

            Asserting
            .That(resultAbsoluteFixed8)
            .AsLongValue(expectedPositiveLongValue);
        }
Ejemplo n.º 3
0
        //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);
        }