Esempio n. 1
0
        /// <summary>
        /// 获取需要校验的脚本散列值
        /// </summary>
        /// <returns>返回需要校验的脚本散列值</returns>
        public override UInt160[] GetScriptHashesForVerifying()
        {
            HashSet <UInt160> hashes = new HashSet <UInt160>(base.GetScriptHashesForVerifying());

            foreach (TransactionResult result in GetTransactionResults().Where(p => p.Amount < Fixed8.Zero))
            {
                AssetState asset = Blockchain.Default.GetAssetState(result.AssetId);
                if (asset == null)
                {
                    throw new InvalidOperationException();
                }
                hashes.Add(asset.Issuer);
            }
            return(hashes.OrderBy(p => p).ToArray());
        }
Esempio n. 2
0
        /// <summary>
        /// 获取需要校验的脚本散列值
        /// </summary>
        /// <returns>返回需要校验的脚本散列值</returns>
        public virtual UInt160[] GetScriptHashesForVerifying()
        {
            if (References == null)
            {
                throw new InvalidOperationException();
            }
            HashSet <UInt160> hashes = new HashSet <UInt160>(Inputs.Select(p => References[p].ScriptHash));

            hashes.UnionWith(Attributes.Where(p => p.Usage == TransactionAttributeUsage.Script).Select(p => new UInt160(p.Data)));
            foreach (var group in Outputs.GroupBy(p => p.AssetId))
            {
                AssetState asset = Blockchain.Default.GetAssetState(group.Key);
                if (asset == null)
                {
                    throw new InvalidOperationException();
                }
                if (asset.AssetType.HasFlag(AssetType.DutyFlag))
                {
                    hashes.UnionWith(group.Select(p => p.ScriptHash));
                }
            }
            return(hashes.OrderBy(p => p).ToArray());
        }
Esempio n. 3
0
        /// <summary>
        /// 验证交易
        /// </summary>
        /// <returns>返回验证的结果</returns>
        public virtual bool Verify(IEnumerable <Transaction> mempool)
        {
            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 (Blockchain.Default.IsDoubleSpend(this))
            {
                return(false);
            }
            foreach (var group in Outputs.GroupBy(p => p.AssetId))
            {
                AssetState asset = Blockchain.Default.GetAssetState(group.Key);
                if (asset == null)
                {
                    return(false);
                }
                if (asset.Expiration <= Blockchain.Default.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);
            }
            return(this.VerifyScripts());
        }