private void Persist(Block block) { using (SnapshotView snapshot = GetSnapshot()) { if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Set(block); } List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; if (block.Index > 0) { using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true)) { engine.LoadScript(onPersistNativeContractScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.Blocks.Add(block.Hash, block.Trim()); StoreView clonedSnapshot = snapshot.Clone(); // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { var state = new TransactionState { BlockIndex = block.Index, Transaction = tx }; clonedSnapshot.Transactions.Add(tx.Hash, state); clonedSnapshot.Transactions.Commit(); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { engine.LoadScript(tx.Script); state.VMState = engine.Execute(); if (state.VMState == VMState.HALT) { clonedSnapshot.Commit(); } else { clonedSnapshot = snapshot.Clone(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Set(block); foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); block_cache.Remove(block.PrevHash); MemPool.UpdatePoolForBlockPersisted(block, currentSnapshot); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); }
private void Persist(Block block) { WriteBatch batch = new WriteBatch(); DbCache <UInt160, AccountState> accounts = new DbCache <UInt160, AccountState>(db, DataEntryPrefix.ST_Account, batch); DbCache <UInt256, UnspentCoinState> unspentcoins = new DbCache <UInt256, UnspentCoinState>(db, DataEntryPrefix.ST_Coin, batch); DbCache <UInt256, SpentCoinState> spentcoins = new DbCache <UInt256, SpentCoinState>(db, DataEntryPrefix.ST_SpentCoin, batch); DbCache <ECPoint, ValidatorState> validators = new DbCache <ECPoint, ValidatorState>(db, DataEntryPrefix.ST_Validator, batch); DbCache <UInt256, AssetState> assets = new DbCache <UInt256, AssetState>(db, DataEntryPrefix.ST_Asset, batch); DbCache <UInt160, ContractState> contracts = new DbCache <UInt160, ContractState>(db, DataEntryPrefix.ST_Contract, batch); DbCache <StorageKey, StorageItem> storages = new DbCache <StorageKey, StorageItem>(db, DataEntryPrefix.ST_Storage, batch); DbMetaDataCache <ValidatorsCountState> validators_count = new DbMetaDataCache <ValidatorsCountState>(db, DataEntryPrefix.IX_ValidatorsCount); long amount_sysfee = GetSysFeeAmount(block.PrevHash) + (long)block.Transactions.Sum(p => p.SystemFee); batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Block).Add(block.Hash), SliceBuilder.Begin().Add(amount_sysfee).Add(block.Trim())); foreach (Transaction tx in block.Transactions) { batch.Put(SliceBuilder.Begin(DataEntryPrefix.DATA_Transaction).Add(tx.Hash), SliceBuilder.Begin().Add(block.Index).Add(tx.ToArray())); unspentcoins.Add(tx.Hash, new UnspentCoinState { Items = Enumerable.Repeat(CoinState.Confirmed, tx.Outputs.Length).ToArray() }); foreach (TransactionOutput output in tx.Outputs) { AccountState account = accounts.GetAndChange(output.ScriptHash, () => new AccountState(output.ScriptHash)); if (account.Balances.ContainsKey(output.AssetId)) { account.Balances[output.AssetId] += output.Value; } else { account.Balances[output.AssetId] = output.Value; } if (output.AssetId.Equals(GoverningToken.Hash) && account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { validators.GetAndChange(pubkey, () => new ValidatorState(pubkey)).Votes += output.Value; } validators_count.GetAndChange().Votes[account.Votes.Length - 1] += output.Value; } } foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash)) { Transaction tx_prev = GetTransaction(ReadOptions.Default, group.Key, out int height); foreach (CoinReference input in group) { unspentcoins.GetAndChange(input.PrevHash).Items[input.PrevIndex] |= CoinState.Spent; TransactionOutput out_prev = tx_prev.Outputs[input.PrevIndex]; AccountState account = accounts.GetAndChange(out_prev.ScriptHash); if (out_prev.AssetId.Equals(GoverningToken.Hash)) { spentcoins.GetAndChange(input.PrevHash, () => new SpentCoinState { TransactionHash = input.PrevHash, TransactionHeight = (uint)height, Items = new Dictionary <ushort, uint>() }).Items.Add(input.PrevIndex, block.Index); if (account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { ValidatorState validator = validators.GetAndChange(pubkey); validator.Votes -= out_prev.Value; if (!validator.Registered && validator.Votes.Equals(Fixed8.Zero)) { validators.Delete(pubkey); } } validators_count.GetAndChange().Votes[account.Votes.Length - 1] -= out_prev.Value; } } account.Balances[out_prev.AssetId] -= out_prev.Value; } } switch (tx) { #pragma warning disable CS0612 case RegisterTransaction tx_register: assets.Add(tx.Hash, new AssetState { AssetId = tx_register.Hash, AssetType = tx_register.AssetType, Name = tx_register.Name, Amount = tx_register.Amount, Available = Fixed8.Zero, Precision = tx_register.Precision, Fee = Fixed8.Zero, FeeAddress = new UInt160(), Owner = tx_register.Owner, Admin = tx_register.Admin, Issuer = tx_register.Admin, Expiration = block.Index + 2 * 2000000, IsFrozen = false }); break; #pragma warning restore CS0612 case IssueTransaction _: foreach (TransactionResult result in tx.GetTransactionResults().Where(p => p.Amount < Fixed8.Zero)) { assets.GetAndChange(result.AssetId).Available -= result.Amount; } break; case ClaimTransaction _: foreach (CoinReference input in ((ClaimTransaction)tx).Claims) { if (spentcoins.TryGet(input.PrevHash)?.Items.Remove(input.PrevIndex) == true) { spentcoins.GetAndChange(input.PrevHash); } } break; #pragma warning disable CS0612 case EnrollmentTransaction tx_enrollment: validators.GetAndChange(tx_enrollment.PublicKey, () => new ValidatorState(tx_enrollment.PublicKey)).Registered = true; break; #pragma warning restore CS0612 case StateTransaction tx_state: foreach (StateDescriptor descriptor in tx_state.Descriptors) { switch (descriptor.Type) { case StateType.Account: ProcessAccountStateDescriptor(descriptor, accounts, validators, validators_count); break; case StateType.Validator: ProcessValidatorStateDescriptor(descriptor, validators); break; } } break; #pragma warning disable CS0612 case PublishTransaction tx_publish: contracts.GetOrAdd(tx_publish.ScriptHash, () => new ContractState { Script = tx_publish.Script, ParameterList = tx_publish.ParameterList, ReturnType = tx_publish.ReturnType, ContractProperties = (ContractPropertyState)Convert.ToByte(tx_publish.NeedStorage), Name = tx_publish.Name, CodeVersion = tx_publish.CodeVersion, Author = tx_publish.Author, Email = tx_publish.Email, Description = tx_publish.Description }); break; #pragma warning restore CS0612 case InvocationTransaction tx_invocation: CachedScriptTable script_table = new CachedScriptTable(contracts); using (StateMachine service = new StateMachine(block, accounts, assets, contracts, storages)) { ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx_invocation, script_table, service, tx_invocation.Gas); ///add log bool bLog = false; var split = block.Header.Index % this.fulllog_splitcount; if (this.FullLogPath != null && split == this.fulllog_splitindex) // && this.FullLogSkip.Contains(itx.Hash.ToString()) == false) { bLog = true; } if (bLog) { engine.BeginDebug(); } engine.LoadScript(tx_invocation.Script, false); if (engine.Execute()) { service.Commit(); } ApplicationExecuted?.Invoke(this, new ApplicationExecutedEventArgs(tx_invocation, service.Notifications.ToArray(), engine)); //write fulllog if (bLog) { string filename = System.IO.Path.Combine(this.FullLogPath, tx.Hash.ToString() + ".llvmhex.txt"); if (engine.FullLog != null) { engine.FullLog.Save(filename); } } } break; } } accounts.DeleteWhere((k, v) => !v.IsFrozen && v.Votes.Length == 0 && v.Balances.All(p => p.Value <= Fixed8.Zero)); accounts.Commit(); unspentcoins.DeleteWhere((k, v) => v.Items.All(p => p.HasFlag(CoinState.Spent))); unspentcoins.Commit(); spentcoins.DeleteWhere((k, v) => v.Items.Count == 0); spentcoins.Commit(); validators.Commit(); assets.Commit(); contracts.Commit(); storages.Commit(); validators_count.Commit(batch); batch.Put(SliceBuilder.Begin(DataEntryPrefix.SYS_CurrentBlock), SliceBuilder.Begin().Add(block.Hash).Add(block.Index)); db.Write(WriteOptions.Default, batch); current_block_height = block.Index; }
private void Persist(Block block) { using (Snapshot snapshot = GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; snapshot.Blocks.Add(block.Hash, new BlockState { SystemFeeAmount = snapshot.GetSysFeeAmount(block.PrevHash) + (long)block.Transactions.Sum(p => p.SystemFee), TrimmedBlock = block.Trim() }); foreach (Transaction tx in block.Transactions) { snapshot.Transactions.Add(tx.Hash, new TransactionState { BlockIndex = block.Index, Transaction = tx }); snapshot.UnspentCoins.Add(tx.Hash, new UnspentCoinState { Items = Enumerable.Repeat(CoinState.Confirmed, tx.Outputs.Length).ToArray() }); foreach (TransactionOutput output in tx.Outputs) { AccountState account = snapshot.Accounts.GetAndChange(output.ScriptHash, () => new AccountState(output.ScriptHash)); if (account.Balances.ContainsKey(output.AssetId)) { account.Balances[output.AssetId] += output.Value; } else { account.Balances[output.AssetId] = output.Value; } if (output.AssetId.Equals(GoverningToken.Hash) && account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { snapshot.Validators.GetAndChange(pubkey, () => new ValidatorState(pubkey)).Votes += output.Value; } snapshot.ValidatorsCount.GetAndChange().Votes[account.Votes.Length - 1] += output.Value; } } foreach (var group in tx.Inputs.GroupBy(p => p.PrevHash)) { TransactionState tx_prev = snapshot.Transactions[group.Key]; foreach (CoinReference input in group) { snapshot.UnspentCoins.GetAndChange(input.PrevHash).Items[input.PrevIndex] |= CoinState.Spent; TransactionOutput out_prev = tx_prev.Transaction.Outputs[input.PrevIndex]; AccountState account = snapshot.Accounts.GetAndChange(out_prev.ScriptHash); if (out_prev.AssetId.Equals(GoverningToken.Hash)) { snapshot.SpentCoins.GetAndChange(input.PrevHash, () => new SpentCoinState { TransactionHash = input.PrevHash, TransactionHeight = tx_prev.BlockIndex, Items = new Dictionary <ushort, uint>() }).Items.Add(input.PrevIndex, block.Index); if (account.Votes.Length > 0) { foreach (ECPoint pubkey in account.Votes) { ValidatorState validator = snapshot.Validators.GetAndChange(pubkey); validator.Votes -= out_prev.Value; if (!validator.Registered && validator.Votes.Equals(Fixed8.Zero)) { snapshot.Validators.Delete(pubkey); } } snapshot.ValidatorsCount.GetAndChange().Votes[account.Votes.Length - 1] -= out_prev.Value; } } account.Balances[out_prev.AssetId] -= out_prev.Value; } } List <ApplicationExecutionResult> execution_results = new List <ApplicationExecutionResult>(); switch (tx) { #pragma warning disable CS0612 case RegisterTransaction tx_register: snapshot.Assets.Add(tx.Hash, new AssetState { AssetId = tx_register.Hash, AssetType = tx_register.AssetType, Name = tx_register.Name, Amount = tx_register.Amount, Available = Fixed8.Zero, Precision = tx_register.Precision, Fee = Fixed8.Zero, FeeAddress = new UInt160(), Owner = tx_register.Owner, Admin = tx_register.Admin, Issuer = tx_register.Admin, Expiration = block.Index + 2 * 2000000, IsFrozen = false }); break; #pragma warning restore CS0612 case IssueTransaction _: foreach (TransactionResult result in tx.GetTransactionResults().Where(p => p.Amount < Fixed8.Zero)) { snapshot.Assets.GetAndChange(result.AssetId).Available -= result.Amount; } break; case ClaimTransaction _: foreach (CoinReference input in ((ClaimTransaction)tx).Claims) { if (snapshot.SpentCoins.TryGet(input.PrevHash)?.Items.Remove(input.PrevIndex) == true) { snapshot.SpentCoins.GetAndChange(input.PrevHash); } } break; #pragma warning disable CS0612 case EnrollmentTransaction tx_enrollment: snapshot.Validators.GetAndChange(tx_enrollment.PublicKey, () => new ValidatorState(tx_enrollment.PublicKey)).Registered = true; break; #pragma warning restore CS0612 case StateTransaction tx_state: foreach (StateDescriptor descriptor in tx_state.Descriptors) { switch (descriptor.Type) { case StateType.Account: ProcessAccountStateDescriptor(descriptor, snapshot); break; case StateType.Validator: ProcessValidatorStateDescriptor(descriptor, snapshot); break; } } break; #pragma warning disable CS0612 case PublishTransaction tx_publish: snapshot.Contracts.GetOrAdd(tx_publish.ScriptHash, () => new ContractState { Script = tx_publish.Script, ParameterList = tx_publish.ParameterList, ReturnType = tx_publish.ReturnType, ContractProperties = (ContractPropertyState)Convert.ToByte(tx_publish.NeedStorage), Name = tx_publish.Name, CodeVersion = tx_publish.CodeVersion, Author = tx_publish.Author, Email = tx_publish.Email, Description = tx_publish.Description }); break; #pragma warning restore CS0612 case InvocationTransaction tx_invocation: using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx_invocation, snapshot.Clone(), tx_invocation.Gas)) { engine.LoadScript(tx_invocation.Script); engine.Execute(); if (!engine.State.HasFlag(VMState.FAULT)) { engine.Service.Commit(); } execution_results.Add(new ApplicationExecutionResult { Trigger = TriggerType.Application, ScriptHash = tx_invocation.Script.ToScriptHash(), VMState = engine.State, GasConsumed = engine.GasConsumed, Stack = engine.ResultStack.ToArray(), Notifications = engine.Service.Notifications.ToArray() }); } break; } if (execution_results.Count > 0) { ApplicationExecuted application_executed = new ApplicationExecuted { Transaction = tx, ExecutionResults = execution_results.ToArray() }; Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Hash = block.Hash; snapshot.BlockHashIndex.GetAndChange().Index = block.Index; if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Hash = block.Hash; snapshot.HeaderHashIndex.GetAndChange().Index = block.Index; } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); OnPersistCompleted(block); }
private void Persist(Block block) { using (Snapshot snapshot = GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; if (block.Index > 0) { NativeContract[] contracts = { NativeContract.GAS, NativeContract.NEO }; using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true)) { using (ScriptBuilder sb = new ScriptBuilder()) { foreach (NativeContract contract in contracts) { sb.EmitAppCall(contract.Hash, "onPersist"); } engine.LoadScript(sb.ToArray()); } if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.Blocks.Add(block.Hash, block.Trim()); foreach (Transaction tx in block.Transactions) { var state = new TransactionState { BlockIndex = block.Index, Transaction = tx }; snapshot.Transactions.Add(tx.Hash, state); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, snapshot.Clone(), tx.SystemFee)) { engine.LoadScript(tx.Script); state.VMState = engine.Execute(); if (state.VMState == VMState.HALT) { engine.Snapshot.Commit(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Hash = block.Hash; snapshot.BlockHashIndex.GetAndChange().Index = block.Index; if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Hash = block.Hash; snapshot.HeaderHashIndex.GetAndChange().Index = block.Index; } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); OnPersistCompleted(block); }
private void Persist(Block block) { using (Snapshot snapshot = GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); snapshot.PersistingBlock = block; if (block.Index > 0) { snapshot.NextValidators.GetAndChange().Validators = snapshot.GetValidators(); } snapshot.Blocks.Add(block.Hash, new BlockState { SystemFeeAmount = snapshot.GetSysFeeAmount(block.PrevHash) + (long)block.Transactions.Sum(p => p.SystemFee), TrimmedBlock = block.Trim() }); foreach (Transaction tx in block.Transactions) { snapshot.Transactions.Add(tx.Hash, new TransactionState { BlockIndex = block.Index, Transaction = tx }); snapshot.UnspentCoins.Add(tx.Hash, new UnspentCoinState { Items = Enumerable.Repeat(CoinState.Confirmed, tx.Outputs.Length).ToArray() }); foreach (CoinReference input in tx.Inputs) { snapshot.UnspentCoins.GetAndChange(input.PrevHash).Items[input.PrevIndex] |= CoinState.Spent; } List <ApplicationExecutionResult> execution_results = new List <ApplicationExecutionResult>(); switch (tx) { #pragma warning disable CS0612 case RegisterTransaction tx_register: snapshot.Assets.Add(tx.Hash, new AssetState { AssetId = tx_register.Hash, AssetType = tx_register.AssetType, Name = tx_register.Name, Amount = tx_register.Amount, Available = Fixed8.Zero, Precision = tx_register.Precision, Fee = Fixed8.Zero, FeeAddress = new UInt160(), Owner = tx_register.Owner, Admin = tx_register.Admin, Issuer = tx_register.Admin, Expiration = block.Index + 2 * 2000000, IsFrozen = false }); break; #pragma warning restore CS0612 case InvocationTransaction tx_invocation: using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx_invocation, snapshot.Clone(), tx_invocation.Gas)) { engine.LoadScript(tx_invocation.Script); engine.Execute(); if (!engine.State.HasFlag(VMState.FAULT)) { engine.Service.Commit(); } execution_results.Add(new ApplicationExecutionResult { Trigger = TriggerType.Application, ScriptHash = tx_invocation.Script.ToScriptHash(), VMState = engine.State, GasConsumed = engine.GasConsumed, Stack = engine.ResultStack.ToArray(), Notifications = engine.Service.Notifications.ToArray() }); } break; } if (execution_results.Count > 0) { ApplicationExecuted application_executed = new ApplicationExecuted { Transaction = tx, ExecutionResults = execution_results.ToArray() }; Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } snapshot.BlockHashIndex.GetAndChange().Hash = block.Hash; snapshot.BlockHashIndex.GetAndChange().Index = block.Index; if (block.Index == header_index.Count) { header_index.Add(block.Hash); snapshot.HeaderHashIndex.GetAndChange().Hash = block.Hash; snapshot.HeaderHashIndex.GetAndChange().Index = block.Index; } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } } UpdateCurrentSnapshot(); OnPersistCompleted(block); }
private void Persist(Block block) { using (SnapshotCache snapshot = system.GetSnapshot()) { List <ApplicationExecuted> all_application_executed = new List <ApplicationExecuted>(); using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, block)) { engine.LoadScript(onPersistScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } DataCache clonedSnapshot = snapshot.CreateSnapshot(); // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, block, tx.SystemFee)) { engine.LoadScript(tx.Script); if (engine.Execute() == VMState.HALT) { clonedSnapshot.Commit(); } else { clonedSnapshot = snapshot.CreateSnapshot(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } } using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.PostPersist, null, snapshot, block)) { engine.LoadScript(postPersistScript); if (engine.Execute() != VMState.HALT) { throw new InvalidOperationException(); } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { plugin.OnPersist(block, snapshot, all_application_executed); } snapshot.Commit(); List <Exception> commitExceptions = null; foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) { try { plugin.OnCommit(block, snapshot); } catch (Exception ex) { if (plugin.ShouldThrowExceptionFromCommit(ex)) { if (commitExceptions == null) { commitExceptions = new List <Exception>(); } commitExceptions.Add(ex); } } } if (commitExceptions != null) { throw new AggregateException(commitExceptions); } system.MemPool.UpdatePoolForBlockPersisted(block, snapshot); } extensibleWitnessWhiteList = null; block_cache.Remove(block.PrevHash); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); if (system.HeaderCache.TryRemoveFirst(out Header header)) { Debug.Assert(header.Index == block.Index); } }