Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow contracts to load script at runtime dynamically #2756

Merged
merged 12 commits into from
Sep 16, 2022
28 changes: 28 additions & 0 deletions src/Neo/SmartContract/ApplicationEngine.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Neo.IO;
using Neo.Network.P2P.Payloads;
using Neo.SmartContract.Native;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -90,6 +91,12 @@ partial class ApplicationEngine
/// </summary>
public static readonly InteropDescriptor System_Runtime_GetEntryScriptHash = Register("System.Runtime.GetEntryScriptHash", nameof(EntryScriptHash), 1 << 4, CallFlags.None);

/// <summary>
/// The <see cref="InteropDescriptor"/> of System.Runtime.LoadScript.
/// Loads a script at rumtime.
/// </summary>
public static readonly InteropDescriptor System_Runtime_LoadScript = Register("System.Runtime.LoadScript", nameof(RuntimeLoadScript), 1 << 15, CallFlags.AllowCall);

/// <summary>
/// The <see cref="InteropDescriptor"/> of System.Runtime.CheckWitness.
/// Determines whether the specified account has witnessed the current transaction.
Expand Down Expand Up @@ -189,6 +196,27 @@ protected internal StackItem GetScriptContainer()
return interop.ToStackItem(ReferenceCounter);
}

/// <summary>
/// The implementation of System.Runtime.LoadScript.
/// Loads a script at rumtime.
/// </summary>
protected internal void RuntimeLoadScript(byte[] script, CallFlags callFlags, Array args)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
if ((callFlags & ~CallFlags.All) != 0)
throw new ArgumentOutOfRangeException(nameof(callFlags));

ExecutionContextState state = CurrentContext.GetState<ExecutionContextState>();
ExecutionContext context = LoadScript(script, configureState: p =>
{
p.CallingContext = CurrentContext;
p.CallFlags = callFlags & state.CallFlags & CallFlags.ReadOnly;
p.IsDynamicCall = true;
});

for (int i = args.Count - 1; i >= 0; i--)
context.EvaluationStack.Push(args[i]);
}

/// <summary>
/// The implementation of System.Runtime.CheckWitness.
/// Determines whether the specified account has witnessed the current transaction.
Expand Down