Beispiel #1
0
        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());
            }
        }
Beispiel #2
0
        /*
         * 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));
        }