Beispiel #1
0
 /// <summary>
 /// 验证该区块是否合法
 /// </summary>
 /// <param name="completely">是否同时验证区块中的每一笔交易</param>
 /// <returns>返回该区块的合法性,返回true即为合法,否则,非法。</returns>
 public bool Verify(bool completely)
 {
     if (!Verify())
     {
         return(false);
     }
     if (Transactions[0].Type != TransactionType.MinerTransaction || Transactions.Skip(1).Any(p => p.Type == TransactionType.MinerTransaction))
     {
         return(false);
     }
     if (completely)
     {
         if (NextConsensus != BlockchainBase.GetConsensusAddress(Chain.GetValidators(Transactions).ToArray()))
         {
             return(false);
         }
         foreach (Transaction tx in Transactions)
         {
             if (!tx.Verify(Transactions.Where(p => !p.Hash.Equals(tx.Hash))))
             {
                 return(false);
             }
         }
         Transaction tx_gen = Transactions.FirstOrDefault(p => p.Type == TransactionType.MinerTransaction);
         if (tx_gen?.Outputs.Sum(p => p.Value) != CalculateNetFee(Transactions))
         {
             return(false);
         }
     }
     return(true);
 }
Beispiel #2
0
        /// <summary>
        /// 默认的区块链实例
        /// </summary>
        public static BlockchainBase GetBlockchain(UInt256 hash)
        {
            BlockchainBase blockchain = null;

            Blockchains.TryGetValue(hash, out blockchain);
            return(blockchain);
        }
Beispiel #3
0
 protected override void OnDeserialized()
 {
     base.OnDeserialized();
     if (AssetType == AssetType.GoverningToken && !Hash.Equals(BlockchainBase.GetStaticAttr().GoverningToken.Hash))
     {
         throw new FormatException();
     }
     if (AssetType == AssetType.UtilityToken && !Hash.Equals(BlockchainBase.GetStaticAttr().UtilityToken.Hash))
     {
         throw new FormatException();
     }
 }
Beispiel #4
0
 /// <summary>
 /// 反序列化进行完毕时触发
 /// </summary>
 protected override void OnDeserialized()
 {
     base.OnDeserialized();
     if (Inputs.Length != 0)
     {
         throw new FormatException();
     }
     if (Outputs.Any(p => p.AssetId != BlockchainBase.GetStaticAttr().UtilityToken.Hash))
     {
         throw new FormatException();
     }
 }
Beispiel #5
0
 internal static bool VerifyScripts(this IVerifiable verifiable)
 {
     UInt160[] hashes;
     try
     {
         hashes = verifiable.GetScriptHashesForVerifying();
     }
     catch (InvalidOperationException)
     {
         return(false);
     }
     if (hashes.Length != verifiable.Scripts.Length)
     {
         return(false);
     }
     for (int i = 0; i < hashes.Length; i++)
     {
         byte[] verification = verifiable.Scripts[i].VerificationScript;
         if (verification.Length == 0)
         {
             using (ScriptBuilder sb = new ScriptBuilder())
             {
                 sb.EmitAppCall(hashes[i].ToArray());
                 verification = sb.ToArray();
             }
         }
         else
         {
             if (hashes[i] != verifiable.Scripts[i].ScriptHash)
             {
                 return(false);
             }
         }
         using (StateReader service = new StateReader(verifiable))
         {
             ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable,
                                                              BlockchainBase.GetBlockchain(verifiable.ChainHash), service, Fixed8.Zero);
             engine.LoadScript(verification, false);
             engine.LoadScript(verifiable.Scripts[i].InvocationScript, true);
             if (!engine.Execute())
             {
                 return(false);
             }
             if (engine.EvaluationStack.Count != 1 || !engine.EvaluationStack.Pop().GetBoolean())
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Beispiel #6
0
 /// <summary>
 /// 注册默认的区块链实例
 /// </summary>
 /// <param name="blockchain">区块链实例</param>
 /// <returns>返回注册后的区块链实例</returns>
 public static BlockchainBase RegisterBlockchain(UInt256 hash, BlockchainBase blockchain)
 {
     if (blockchain == null)
     {
         return(blockchain);
     }
     if (Blockchains.ContainsKey(hash))
     {
         // error : already exist
         return(Blockchains[hash]);
     }
     Blockchains[hash] = blockchain;
     return(blockchain);
 }
Beispiel #7
0
        private bool VerifyAccountState(UInt256 ChainHash)
        {
            switch (Field)
            {
            case "Votes":
                BlockchainBase chain = BlockchainBase.GetBlockchain(ChainHash);
                if (chain == null)
                {
                    return(false);
                }
                ECPoint[] pubkeys;
                try
                {
                    pubkeys = Value.AsSerializableArray <ECPoint>((int)BlockchainBase.MaxValidators);
                }
                catch (FormatException)
                {
                    return(false);
                }
                UInt160      hash    = new UInt160(Key);
                AccountState account = chain.GetAccountState(hash);
                if (account?.IsFrozen != false)
                {
                    return(false);
                }
                if (pubkeys.Length > 0)
                {
                    if (account.GetBalance(BlockchainBase.GetStaticAttr().GoverningToken.Hash).Equals(Fixed8.Zero))
                    {
                        return(false);
                    }
                    HashSet <ECPoint> sv = new HashSet <ECPoint>(chain.StandbyValidators);
                    DataCache <ECPoint, ValidatorState> validators = chain.GetStates <ECPoint, ValidatorState>();
                    foreach (ECPoint pubkey in pubkeys)
                    {
                        if (!sv.Contains(pubkey) && validators.TryGet(pubkey)?.Registered != true)
                        {
                            return(false);
                        }
                    }
                }
                return(true);

            default:
                return(false);
            }
        }
Beispiel #8
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 (Chain.IsDoubleSpend(this))
            {
                return(false);
            }
            foreach (var group in Outputs.GroupBy(p => p.AssetId))
            {
                AssetState asset = Chain.GetAssetState(group.Key);
                if (asset == null)
                {
                    return(false);
                }
                if (asset.Expiration <= Chain.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 != BlockchainBase.GetStaticAttr().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 != BlockchainBase.GetStaticAttr().UtilityToken.Hash))
                {
                    return(false);
                }
                break;

            case TransactionType.IssueTransaction:
                if (results_issue.Any(p => p.AssetId == BlockchainBase.GetStaticAttr().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());
        }
Beispiel #9
0
        /// <summary>
        /// 验证交易
        /// </summary>
        /// <returns>返回验证结果</returns>
        public override bool Verify(IEnumerable <Transaction> mempool)
        {
            if (!base.Verify(mempool))
            {
                return(false);
            }
            if (Claims.Length != Claims.Distinct().Count())
            {
                return(false);
            }
            if (mempool.OfType <ClaimTransaction>().Where(p => p != this).SelectMany(p => p.Claims).Intersect(Claims).Count() > 0)
            {
                return(false);
            }
            TransactionResult result = GetTransactionResults().FirstOrDefault(p => p.AssetId == BlockchainBase.GetStaticAttr().UtilityToken.Hash);

            if (result == null || result.Amount > Fixed8.Zero)
            {
                return(false);
            }
            try
            {
                return(Chain.CalculateBonus(Claims, false) == -result.Amount);
            }
            catch (ArgumentException)
            {
                return(false);
            }
            catch (NotSupportedException)
            {
                return(false);
            }
        }
Beispiel #10
0
        public static Fixed8 CalculateNetFee(IEnumerable <Transaction> transactions)
        {
            Transaction[] ts            = transactions.Where(p => p.Type != TransactionType.MinerTransaction && p.Type != TransactionType.ClaimTransaction).ToArray();
            Fixed8        amount_in     = ts.SelectMany(p => p.References.Values.Where(o => o.AssetId == BlockchainBase.GetStaticAttr().UtilityToken.Hash)).Sum(p => p.Value);
            Fixed8        amount_out    = ts.SelectMany(p => p.Outputs.Where(o => o.AssetId == BlockchainBase.GetStaticAttr().UtilityToken.Hash)).Sum(p => p.Value);
            Fixed8        amount_sysfee = ts.Sum(p => p.SystemFee);

            return(amount_in - amount_out - amount_sysfee);
        }