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

v2.10.1 #667

Merged
merged 7 commits into from
Apr 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions neo.UnitTests/UT_InteropPrices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,91 +259,99 @@ public void ApplicationEngineVariablePrices()
byte[] SyscallAssetRenewHash = new byte[]{0x59, 0x59, 0x68, 0x04, 0x78, 0x84, 0x90, 0x71};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallAssetRenewHash);
ae.StepInto(); // push 9
ae.StepInto(); // push 9
debugger.StepInto(); // push 9
debugger.StepInto(); // push 9
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(9L * 5000L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// Neo.Contract.Create: f66ca56e (requires push properties on fourth position)
byte[] SyscallContractCreateHash00 = new byte[]{(byte)ContractPropertyState.NoProperty, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallContractCreateHash00);
ae.StepInto(); // push 0 - ContractPropertyState.NoProperty
ae.StepInto(); // push 0
ae.StepInto(); // push 0
ae.StepInto(); // push 0
debugger.StepInto(); // push 0 - ContractPropertyState.NoProperty
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(100L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// Neo.Contract.Create: f66ca56e (requires push properties on fourth position)
byte[] SyscallContractCreateHash01 = new byte[]{0x51, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallContractCreateHash01);
ae.StepInto(); // push 01 - ContractPropertyState.HasStorage
ae.StepInto(); // push 0
ae.StepInto(); // push 0
ae.StepInto(); // push 0
debugger.StepInto(); // push 01 - ContractPropertyState.HasStorage
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(500L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// Neo.Contract.Create: f66ca56e (requires push properties on fourth position)
byte[] SyscallContractCreateHash02 = new byte[]{0x52, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallContractCreateHash02);
ae.StepInto(); // push 02 - ContractPropertyState.HasDynamicInvoke
ae.StepInto(); // push 0
ae.StepInto(); // push 0
ae.StepInto(); // push 0
debugger.StepInto(); // push 02 - ContractPropertyState.HasDynamicInvoke
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(600L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// Neo.Contract.Create: f66ca56e (requires push properties on fourth position)
byte[] SyscallContractCreateHash03 = new byte[]{0x53, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallContractCreateHash03);
ae.StepInto(); // push 03 - HasStorage and HasDynamicInvoke
ae.StepInto(); // push 0
ae.StepInto(); // push 0
ae.StepInto(); // push 0
debugger.StepInto(); // push 03 - HasStorage and HasDynamicInvoke
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(1000L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// Neo.Contract.Migrate: 471b6290 (requires push properties on fourth position)
byte[] SyscallContractMigrateHash00 = new byte[]{(byte)ContractPropertyState.NoProperty, 0x00, 0x00, 0x00, 0x68, 0x04, 0x47, 0x1b, 0x62, 0x90};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallContractMigrateHash00);
ae.StepInto(); // push 0 - ContractPropertyState.NoProperty
ae.StepInto(); // push 0
ae.StepInto(); // push 0
ae.StepInto(); // push 0
debugger.StepInto(); // push 0 - ContractPropertyState.NoProperty
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
debugger.StepInto(); // push 0
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(100L * 100000000L / 100000); // assuming private ae.ratio = 100000
}

// System.Storage.Put: e63f1884 (requires push key and value)
byte[] SyscallStoragePutHash = new byte[]{0x53, 0x53, 0x00, 0x68, 0x04, 0xe6, 0x3f, 0x18, 0x84};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallStoragePutHash);
ae.StepInto(); // push 03 (length 1)
ae.StepInto(); // push 03 (length 1)
ae.StepInto(); // push 00
debugger.StepInto(); // push 03 (length 1)
debugger.StepInto(); // push 03 (length 1)
debugger.StepInto(); // push 00
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(1000L); //((1+1-1) / 1024 + 1) * 1000);
}

// System.Storage.PutEx: 73e19b3a (requires push key and value)
byte[] SyscallStoragePutExHash = new byte[]{0x53, 0x53, 0x00, 0x68, 0x04, 0x73, 0xe1, 0x9b, 0x3a};
using ( ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, Fixed8.Zero) )
{
Debugger debugger = new Debugger(ae);
ae.LoadScript(SyscallStoragePutExHash);
ae.StepInto(); // push 03 (length 1)
ae.StepInto(); // push 03 (length 1)
ae.StepInto(); // push 00
debugger.StepInto(); // push 03 (length 1)
debugger.StepInto(); // push 03 (length 1)
debugger.StepInto(); // push 00
GetPriceForSysCall.Invoke(ae, new object[]{}).Should().Be(1000L); //((1+1-1) / 1024 + 1) * 1000);
}
}
Expand Down
25 changes: 25 additions & 0 deletions neo/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,31 @@ internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int si
return new BigInteger(b);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
unsafe internal static bool NotZero(this byte[] x)
{
if (x is null)
throw new ArgumentNullException(nameof(x));
int len = x.Length;
if (len == 0) return false;
fixed (byte* xp = x)
{
long* xlp = (long*)xp;
for (; len >= 8; len -= 8)
{
if (*xlp != 0) return true;
xlp++;
}
byte* xbp = (byte*)xlp;
for (; len > 0; len--)
{
if (*xbp != 0) return true;
xbp++;
}
}
return false;
}

public static Fixed8 Sum(this IEnumerable<Fixed8> source)
{
long sum = 0;
Expand Down
3 changes: 2 additions & 1 deletion neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,8 @@ private void Persist(Block block)
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx_invocation, snapshot.Clone(), tx_invocation.Gas))
{
engine.LoadScript(tx_invocation.Script);
if (engine.Execute())
engine.Execute();
if (!engine.State.HasFlag(VMState.FAULT))
{
engine.Service.Commit();
}
Expand Down
61 changes: 15 additions & 46 deletions neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Neo.Persistence;
using Neo.VM;
using Neo.VM.Types;
using System.Text;

namespace Neo.SmartContract
{
Expand All @@ -27,16 +26,14 @@ public ApplicationEngine(TriggerType trigger, IScriptContainer container, Snapsh
this.snapshot = snapshot;
}

private bool CheckDynamicInvoke(OpCode nextInstruction)
private bool CheckDynamicInvoke()
{
switch (nextInstruction)
Instruction instruction = CurrentContext.CurrentInstruction;
switch (instruction.OpCode)
{
case OpCode.APPCALL:
case OpCode.TAILCALL:
for (int i = CurrentContext.InstructionPointer + 1; i < CurrentContext.InstructionPointer + 21; i++)
{
if (CurrentContext.Script[i] != 0) return true;
}
if (instruction.Operand.NotZero()) return true;
// if we get this far it is a dynamic call
// now look at the current executing script
// to determine if it can do dynamic calls
Expand All @@ -55,35 +52,11 @@ public override void Dispose()
Service.Dispose();
}

public new bool Execute()
{
try
{
while (true)
{
OpCode nextOpcode = CurrentContext.InstructionPointer >= CurrentContext.Script.Length ? OpCode.RET : CurrentContext.NextInstruction;
if (!PreStepInto(nextOpcode))
{
State |= VMState.FAULT;
return false;
}
StepInto();
if (State.HasFlag(VMState.HALT) || State.HasFlag(VMState.FAULT))
break;
}
}
catch
{
State |= VMState.FAULT;
return false;
}
return !State.HasFlag(VMState.FAULT);
}

protected virtual long GetPrice(OpCode nextInstruction)
protected virtual long GetPrice()
{
if (nextInstruction <= OpCode.NOP) return 0;
switch (nextInstruction)
Instruction instruction = CurrentContext.CurrentInstruction;
if (instruction.OpCode <= OpCode.NOP) return 0;
switch (instruction.OpCode)
{
case OpCode.APPCALL:
case OpCode.TAILCALL:
Expand Down Expand Up @@ -118,14 +91,10 @@ protected virtual long GetPrice(OpCode nextInstruction)

protected virtual long GetPriceForSysCall()
{
if (CurrentContext.InstructionPointer >= CurrentContext.Script.Length - 3)
return 1;
byte length = (byte)CurrentContext.Script[CurrentContext.InstructionPointer + 1];
if (CurrentContext.InstructionPointer > CurrentContext.Script.Length - length - 2)
return 1;
uint api_hash = length == 4
? System.BitConverter.ToUInt32(CurrentContext.Script, CurrentContext.InstructionPointer + 2)
: Encoding.ASCII.GetString(CurrentContext.Script, CurrentContext.InstructionPointer + 2, length).ToInteropMethodHash();
Instruction instruction = CurrentContext.CurrentInstruction;
uint api_hash = instruction.Operand.Length == 4
? instruction.TokenU32
: instruction.TokenString.ToInteropMethodHash();
long price = Service.GetPrice(api_hash);
if (price > 0) return price;
if (api_hash == "Neo.Asset.Create".ToInteropMethodHash() ||
Expand Down Expand Up @@ -161,13 +130,13 @@ protected virtual long GetPriceForSysCall()
return 1;
}

private bool PreStepInto(OpCode nextOpcode)
protected override bool PreExecuteInstruction()
{
if (CurrentContext.InstructionPointer >= CurrentContext.Script.Length)
return true;
gas_consumed = checked(gas_consumed + GetPrice(nextOpcode) * ratio);
gas_consumed = checked(gas_consumed + GetPrice() * ratio);
if (!testMode && gas_consumed > gas_amount) return false;
if (!CheckDynamicInvoke(nextOpcode)) return false;
if (!CheckDynamicInvoke()) return false;
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, Snapshot snaps
{
engine.LoadScript(verification);
engine.LoadScript(verifiable.Witnesses[i].InvocationScript);
if (!engine.Execute()) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could preserve the boolean return

engine.Execute();
if (engine.State.HasFlag(VMState.FAULT)) return false;
if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) return false;
}
}
Expand Down
11 changes: 3 additions & 8 deletions neo/neo.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Copyright>2015-2018 The Neo Project</Copyright>
<Copyright>2015-2019 The Neo Project</Copyright>
<AssemblyTitle>Neo</AssemblyTitle>
<Version>2.10.0</Version>
<Version>2.10.1</Version>
<Authors>The Neo Project</Authors>
<TargetFrameworks>netstandard2.0;net47</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand All @@ -19,11 +19,6 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>none</DebugType>
<DebugSymbols>False</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka" Version="1.3.11" />
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
Expand All @@ -32,7 +27,7 @@
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Neo.VM" Version="2.4.0" />
<PackageReference Include="Neo.VM" Version="2.4.1" />
<PackageReference Include="System.Text.Encodings.Web" Version="4.5.0" />
</ItemGroup>

Expand Down