/// <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); }
/// <summary> /// 默认的区块链实例 /// </summary> public static BlockchainBase GetBlockchain(UInt256 hash) { BlockchainBase blockchain = null; Blockchains.TryGetValue(hash, out blockchain); return(blockchain); }
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(); } }
/// <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(); } }
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); }
/// <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); }
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); } }
/// <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()); }
/// <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); } }
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); }