Skip to content

Commit

Permalink
IApplicationEngineProvider (#1758)
Browse files Browse the repository at this point in the history
  • Loading branch information
devhawk authored Jul 11, 2020
1 parent c4799e9 commit 9d996e0
Show file tree
Hide file tree
Showing 21 changed files with 196 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ private void Persist(Block block)
snapshot.PersistingBlock = block;
if (block.Index > 0)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.System, null, snapshot, 0, true))
{
engine.LoadScript(onPersistNativeContractScript);
if (engine.Execute() != VMState.HALT) throw new InvalidOperationException();
Expand All @@ -434,7 +434,7 @@ private void Persist(Block block)
clonedSnapshot.Transactions.Add(tx.Hash, state);
clonedSnapshot.Transactions.Commit();

using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee))
{
engine.LoadScript(tx.Script);
state.VMState = engine.Execute();
Expand Down
11 changes: 11 additions & 0 deletions src/neo/Plugins/IApplicationEngineProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;

namespace Neo.Plugins
{
public interface IApplicationEngineProvider
{
ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Neo.Plugins
{
public interface IStoragePlugin
public interface IStorageProvider
{
IStore GetStore();
}
Expand Down
6 changes: 4 additions & 2 deletions src/neo/Plugins/Plugin.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Configuration;
using Neo.SmartContract;
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -13,7 +14,7 @@ public abstract class Plugin : IDisposable
{
public static readonly List<Plugin> Plugins = new List<Plugin>();
internal static readonly List<ILogPlugin> Loggers = new List<ILogPlugin>();
internal static readonly Dictionary<string, IStoragePlugin> Storages = new Dictionary<string, IStoragePlugin>();
internal static readonly Dictionary<string, IStorageProvider> Storages = new Dictionary<string, IStorageProvider>();
internal static readonly List<IPersistencePlugin> PersistencePlugins = new List<IPersistencePlugin>();
internal static readonly List<IP2PPlugin> P2PPlugins = new List<IP2PPlugin>();
internal static readonly List<IMemoryPoolTxObserverPlugin> TxObserverPlugins = new List<IMemoryPoolTxObserverPlugin>();
Expand Down Expand Up @@ -50,10 +51,11 @@ protected Plugin()
Plugins.Add(this);

if (this is ILogPlugin logger) Loggers.Add(logger);
if (this is IStoragePlugin storage) Storages.Add(Name, storage);
if (this is IStorageProvider storage) Storages.Add(Name, storage);
if (this is IP2PPlugin p2p) P2PPlugins.Add(p2p);
if (this is IPersistencePlugin persistence) PersistencePlugins.Add(persistence);
if (this is IMemoryPoolTxObserverPlugin txObserver) TxObserverPlugins.Add(txObserver);
if (this is IApplicationEngineProvider provider) ApplicationEngine.SetApplicationEngineProvider(provider);

Configure();
}
Expand Down
21 changes: 19 additions & 2 deletions src/neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using static System.Threading.Interlocked;
using Array = System.Array;
using VMArray = Neo.VM.Types.Array;

Expand All @@ -26,6 +28,7 @@ private class InvocationState
public static event EventHandler<NotifyEventArgs> Notify;
public static event EventHandler<LogEventArgs> Log;

private static IApplicationEngineProvider applicationEngineProvider;
private static Dictionary<uint, InteropDescriptor> services;
private readonly long gas_amount;
private readonly bool testMode;
Expand All @@ -46,7 +49,7 @@ private class InvocationState
public UInt160 EntryScriptHash => EntryContext?.GetState<ExecutionContextState>().ScriptHash;
public IReadOnlyList<NotifyEventArgs> Notifications => notifications ?? (IReadOnlyList<NotifyEventArgs>)Array.Empty<NotifyEventArgs>();

public ApplicationEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false)
protected ApplicationEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false)
{
this.Trigger = trigger;
this.ScriptContainer = container;
Expand Down Expand Up @@ -108,6 +111,10 @@ protected override void ContextUnloaded(ExecutionContext context)
}
}

public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false)
=> applicationEngineProvider?.Create(trigger, container, snapshot, gas, testMode)
?? new ApplicationEngine(trigger, container, snapshot, gas, testMode);

private InvocationState GetInvocationState(ExecutionContext context)
{
if (!invocationStates.TryGetValue(context, out InvocationState state))
Expand Down Expand Up @@ -266,11 +273,16 @@ private static InteropDescriptor Register(string name, string handler, long fixe
return descriptor;
}

internal static void ResetApplicationEngineProvider()
{
Exchange(ref applicationEngineProvider, null);
}

public static ApplicationEngine Run(byte[] script, StoreView snapshot,
IVerifiable container = null, Block persistingBlock = null, int offset = 0, bool testMode = false, long gas = default)
{
snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot);
ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, container, snapshot, gas, testMode);
ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, gas, testMode);
engine.LoadScript(script).InstructionPointer = offset;
engine.Execute();
return engine;
Expand All @@ -283,5 +295,10 @@ public static ApplicationEngine Run(byte[] script, IVerifiable container = null,
return Run(script, snapshot, container, persistingBlock, offset, testMode, gas);
}
}

internal static bool SetApplicationEngineProvider(IApplicationEngineProvider provider)
{
return CompareExchange(ref applicationEngineProvider, provider, null) is null;
}
}
}
2 changes: 1 addition & 1 deletion src/neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap
if (hashes[i] != verifiable.Witnesses[i].ScriptHash) return false;
offset = 0;
}
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, snapshot, gas))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot, gas))
{
engine.LoadScript(verification, CallFlags.ReadOnly).InstructionPointer = offset;
engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None);
Expand Down
2 changes: 1 addition & 1 deletion tests/neo.UnitTests/Extensions/NativeContractExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static StackItem Call(this NativeContract contract, StoreView snapshot, s

public static StackItem Call(this NativeContract contract, StoreView snapshot, IVerifiable container, string method, params ContractParameter[] args)
{
var engine = new ApplicationEngine(TriggerType.Application, container, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, container, snapshot, 0, true);

engine.LoadScript(contract.Script);

Expand Down
12 changes: 6 additions & 6 deletions tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void SerializeUnsigned(BinaryWriter writer) { }

public static bool Transfer(this NativeContract contract, StoreView snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom)
{
var engine = new ApplicationEngine(TriggerType.Application,
var engine = ApplicationEngine.Create(TriggerType.Application,
new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, 0, true);

engine.LoadScript(contract.Script);
Expand All @@ -69,7 +69,7 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by

public static BigInteger TotalSupply(this NativeContract contract, StoreView snapshot)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0, true);

engine.LoadScript(contract.Script);

Expand All @@ -89,7 +89,7 @@ public static BigInteger TotalSupply(this NativeContract contract, StoreView sna

public static BigInteger BalanceOf(this NativeContract contract, StoreView snapshot, byte[] account)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0, true);

engine.LoadScript(contract.Script);

Expand All @@ -110,7 +110,7 @@ public static BigInteger BalanceOf(this NativeContract contract, StoreView snaps

public static BigInteger Decimals(this NativeContract contract)
{
var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 0, testMode: true);

engine.LoadScript(contract.Script);

Expand All @@ -130,7 +130,7 @@ public static BigInteger Decimals(this NativeContract contract)

public static string Symbol(this NativeContract contract)
{
var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 0, testMode: true);

engine.LoadScript(contract.Script);

Expand All @@ -150,7 +150,7 @@ public static string Symbol(this NativeContract contract)

public static string Name(this NativeContract contract)
{
var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 0, testMode: true);

engine.LoadScript(contract.Script);

Expand Down
2 changes: 1 addition & 1 deletion tests/neo.UnitTests/Ledger/UT_MemoryPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered()
SnapshotView snapshot = Blockchain.Singleton.GetSnapshot();
BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, sender);

ApplicationEngine applicationEngine = new ApplicationEngine(TriggerType.All, block, snapshot, (long)balance);
ApplicationEngine applicationEngine = ApplicationEngine.Create(TriggerType.All, block, snapshot, (long)balance);
NativeContract.GAS.Burn(applicationEngine, sender, balance);
NativeContract.GAS.Mint(applicationEngine, sender, txFee * 30); // Set the balance to meet 30 txs only

Expand Down
14 changes: 7 additions & 7 deletions tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void FeeIsMultiSigContract()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -227,7 +227,7 @@ public void FeeIsSignatureContractDetailed()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -340,7 +340,7 @@ public void FeeIsSignatureContract_TestScope_Global()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -427,7 +427,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -517,7 +517,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -659,7 +659,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down Expand Up @@ -1009,7 +1009,7 @@ public void FeeIsSignatureContract_TestScope_FeeOnly_Default()
long verificationGas = 0;
foreach (var witness in tx.Witnesses)
{
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false))
{
engine.LoadScript(witness.VerificationScript);
engine.LoadScript(witness.InvocationScript);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void Check_BalanceOfTransferAndBurn()

// Burn

var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0);
var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0);
keyCount = snapshot.Storages.GetChangeSet().Count();

Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
Expand Down Expand Up @@ -124,7 +124,7 @@ public void Check_BalanceOfTransferAndBurn()
[TestMethod]
public void Check_BadScript()
{
var engine = new ApplicationEngine(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0);
var engine = ApplicationEngine.Create(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0);

var script = new ScriptBuilder();
script.Emit(OpCode.NOP);
Expand Down
12 changes: 6 additions & 6 deletions tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public void Check_Initialize()
[TestMethod]
public void Check_BadScript()
{
var engine = new ApplicationEngine(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0);
var engine = ApplicationEngine.Create(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0);

var script = new ScriptBuilder();
script.Emit(OpCode.NOP);
Expand Down Expand Up @@ -424,7 +424,7 @@ public void TestVote()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
snapshot.PersistingBlock = Blockchain.GenesisBlock;
var engine = new ApplicationEngine(TriggerType.Application, Blockchain.GenesisBlock, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, Blockchain.GenesisBlock, snapshot, 0, true);
ScriptBuilder sb = new ScriptBuilder();
var tmp = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot);
UInt160 from = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot)[0];
Expand Down Expand Up @@ -455,7 +455,7 @@ public void TestVote()

internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] account, byte[] pubkey, bool signAccount)
{
var engine = new ApplicationEngine(TriggerType.Application,
var engine = ApplicationEngine.Create(TriggerType.Application,
new Nep5NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot, 0, true);

engine.LoadScript(NativeContract.NEO.Script);
Expand Down Expand Up @@ -485,7 +485,7 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[]

internal static (bool State, bool Result) Check_RegisterValidator(StoreView snapshot, byte[] pubkey)
{
var engine = new ApplicationEngine(TriggerType.Application,
var engine = ApplicationEngine.Create(TriggerType.Application,
new Nep5NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot, 0, true);

engine.LoadScript(NativeContract.NEO.Script);
Expand All @@ -510,7 +510,7 @@ internal static (bool State, bool Result) Check_RegisterValidator(StoreView snap

internal static ECPoint[] Check_GetValidators(StoreView snapshot)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0, true);

engine.LoadScript(NativeContract.NEO.Script);

Expand All @@ -530,7 +530,7 @@ internal static ECPoint[] Check_GetValidators(StoreView snapshot)

internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snapshot, byte[] address)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0, true);

engine.LoadScript(NativeContract.NEO.Script);

Expand Down
Loading

0 comments on commit 9d996e0

Please sign in to comment.