Skip to content

Commit

Permalink
Neo.VM.3.0.0-CI00201 (neo-project#1374)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzhang authored and Tommo-L committed Jun 22, 2020
1 parent aa73ecb commit 830c4a5
Show file tree
Hide file tree
Showing 21 changed files with 232 additions and 195 deletions.
10 changes: 10 additions & 0 deletions src/neo/IO/Helper.cs
Expand Up @@ -89,6 +89,16 @@ public static byte[] DecompressLz4(this byte[] data, int maxOutput)
return result;
}

public static void FillBuffer(this BinaryReader reader, Span<byte> buffer)
{
while (!buffer.IsEmpty)
{
int count = reader.Read(buffer);
if (count == 0) throw new EndOfStreamException();
buffer = buffer[count..];
}
}

public static int GetVarSize(int value)
{
if (value < 0xFD)
Expand Down
92 changes: 73 additions & 19 deletions src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs
Expand Up @@ -78,60 +78,114 @@ partial class ApplicationEngine
[OpCode.REVERSE3] = 60,
[OpCode.REVERSE4] = 60,
[OpCode.REVERSEN] = 400,
[OpCode.TOALTSTACK] = 60,
[OpCode.FROMALTSTACK] = 60,
[OpCode.DUPFROMALTSTACK] = 60,
[OpCode.DUPFROMALTSTACKBOTTOM] = 60,
[OpCode.ISNULL] = 60,
[OpCode.INITSSLOT] = 400,
[OpCode.INITSLOT] = 800,
[OpCode.LDSFLD0] = 60,
[OpCode.LDSFLD1] = 60,
[OpCode.LDSFLD2] = 60,
[OpCode.LDSFLD3] = 60,
[OpCode.LDSFLD4] = 60,
[OpCode.LDSFLD5] = 60,
[OpCode.LDSFLD6] = 60,
[OpCode.LDSFLD] = 60,
[OpCode.STSFLD0] = 60,
[OpCode.STSFLD1] = 60,
[OpCode.STSFLD2] = 60,
[OpCode.STSFLD3] = 60,
[OpCode.STSFLD4] = 60,
[OpCode.STSFLD5] = 60,
[OpCode.STSFLD6] = 60,
[OpCode.STSFLD] = 60,
[OpCode.LDLOC0] = 60,
[OpCode.LDLOC1] = 60,
[OpCode.LDLOC2] = 60,
[OpCode.LDLOC3] = 60,
[OpCode.LDLOC4] = 60,
[OpCode.LDLOC5] = 60,
[OpCode.LDLOC6] = 60,
[OpCode.LDLOC] = 60,
[OpCode.STLOC0] = 60,
[OpCode.STLOC1] = 60,
[OpCode.STLOC2] = 60,
[OpCode.STLOC3] = 60,
[OpCode.STLOC4] = 60,
[OpCode.STLOC5] = 60,
[OpCode.STLOC6] = 60,
[OpCode.STLOC] = 60,
[OpCode.LDARG0] = 60,
[OpCode.LDARG1] = 60,
[OpCode.LDARG2] = 60,
[OpCode.LDARG3] = 60,
[OpCode.LDARG4] = 60,
[OpCode.LDARG5] = 60,
[OpCode.LDARG6] = 60,
[OpCode.LDARG] = 60,
[OpCode.STARG0] = 60,
[OpCode.STARG1] = 60,
[OpCode.STARG2] = 60,
[OpCode.STARG3] = 60,
[OpCode.STARG4] = 60,
[OpCode.STARG5] = 60,
[OpCode.STARG6] = 60,
[OpCode.STARG] = 60,
[OpCode.NEWBUFFER] = 80000,
[OpCode.MEMCPY] = 80000,
[OpCode.CAT] = 80000,
[OpCode.SUBSTR] = 80000,
[OpCode.LEFT] = 80000,
[OpCode.RIGHT] = 80000,
[OpCode.SIZE] = 60,
[OpCode.INVERT] = 100,
[OpCode.AND] = 200,
[OpCode.OR] = 200,
[OpCode.XOR] = 200,
[OpCode.EQUAL] = 200,
[OpCode.INC] = 100,
[OpCode.DEC] = 100,
[OpCode.NOTEQUAL] = 200,
[OpCode.SIGN] = 100,
[OpCode.NEGATE] = 100,
[OpCode.ABS] = 100,
[OpCode.NOT] = 100,
[OpCode.NZ] = 100,
[OpCode.NEGATE] = 100,
[OpCode.INC] = 100,
[OpCode.DEC] = 100,
[OpCode.ADD] = 200,
[OpCode.SUB] = 200,
[OpCode.MUL] = 300,
[OpCode.DIV] = 300,
[OpCode.MOD] = 300,
[OpCode.SHL] = 300,
[OpCode.SHR] = 300,
[OpCode.NOT] = 100,
[OpCode.BOOLAND] = 200,
[OpCode.BOOLOR] = 200,
[OpCode.NZ] = 100,
[OpCode.NUMEQUAL] = 200,
[OpCode.NUMNOTEQUAL] = 200,
[OpCode.LT] = 200,
[OpCode.LE] = 200,
[OpCode.GT] = 200,
[OpCode.LTE] = 200,
[OpCode.GTE] = 200,
[OpCode.GE] = 200,
[OpCode.MIN] = 200,
[OpCode.MAX] = 200,
[OpCode.WITHIN] = 200,
[OpCode.ARRAYSIZE] = 150,
[OpCode.PACK] = 7000,
[OpCode.UNPACK] = 7000,
[OpCode.PICKITEM] = 270000,
[OpCode.SETITEM] = 270000,
[OpCode.NEWARRAY0] = 400,
[OpCode.NEWARRAY] = 15000,
[OpCode.NEWARRAY_T] = 15000,
[OpCode.NEWSTRUCT0] = 400,
[OpCode.NEWSTRUCT] = 15000,
[OpCode.NEWMAP] = 200,
[OpCode.APPEND] = 15000,
[OpCode.REVERSE] = 500,
[OpCode.REMOVE] = 500,
[OpCode.SIZE] = 150,
[OpCode.HASKEY] = 270000,
[OpCode.KEYS] = 500,
[OpCode.VALUES] = 7000,
[OpCode.PICKITEM] = 270000,
[OpCode.APPEND] = 15000,
[OpCode.SETITEM] = 270000,
[OpCode.REVERSEITEMS] = 500,
[OpCode.REMOVE] = 500,
[OpCode.CLEARITEMS] = 400,
[OpCode.ISNULL] = 60,
[OpCode.ISTYPE] = 60,
[OpCode.CONVERT] = 80000,
};
}
}
15 changes: 15 additions & 0 deletions src/neo/SmartContract/ApplicationEngine.cs
Expand Up @@ -5,6 +5,7 @@
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Text;
using Array = System.Array;

namespace Neo.SmartContract
Expand Down Expand Up @@ -140,5 +141,19 @@ internal void SendNotification(UInt160 script_hash, StackItem state)
Notify?.Invoke(this, notification);
notifications.Add(notification);
}

public bool TryPop(out string s)
{
if (TryPop(out ReadOnlySpan<byte> b))
{
s = Encoding.UTF8.GetString(b);
return true;
}
else
{
s = default;
return false;
}
}
}
}
75 changes: 34 additions & 41 deletions src/neo/SmartContract/BinarySerializer.cs
Expand Up @@ -8,30 +8,31 @@
using System.Numerics;
using Array = Neo.VM.Types.Array;
using Boolean = Neo.VM.Types.Boolean;
using Buffer = Neo.VM.Types.Buffer;

namespace Neo.SmartContract
{
internal static class BinarySerializer
{
public static StackItem Deserialize(byte[] data, uint maxItemSize, ReferenceCounter referenceCounter = null)
public static StackItem Deserialize(byte[] data, uint maxArraySize, uint maxItemSize, ReferenceCounter referenceCounter = null)
{
using MemoryStream ms = new MemoryStream(data, false);
using BinaryReader reader = new BinaryReader(ms);
return Deserialize(reader, maxItemSize, referenceCounter);
return Deserialize(reader, maxArraySize, maxItemSize, referenceCounter);
}

public static unsafe StackItem Deserialize(ReadOnlySpan<byte> data, uint maxItemSize, ReferenceCounter referenceCounter = null)
public static unsafe StackItem Deserialize(ReadOnlySpan<byte> data, uint maxArraySize, uint maxItemSize, ReferenceCounter referenceCounter = null)
{
if (data.IsEmpty) throw new FormatException();
fixed (byte* pointer = data)
{
using UnmanagedMemoryStream ms = new UnmanagedMemoryStream(pointer, data.Length);
using BinaryReader reader = new BinaryReader(ms);
return Deserialize(reader, maxItemSize, referenceCounter);
return Deserialize(reader, maxArraySize, maxItemSize, referenceCounter);
}
}

private static StackItem Deserialize(BinaryReader reader, uint maxItemSize, ReferenceCounter referenceCounter)
private static StackItem Deserialize(BinaryReader reader, uint maxArraySize, uint maxItemSize, ReferenceCounter referenceCounter)
{
Stack<StackItem> deserialized = new Stack<StackItem>();
int undeserialized = 1;
Expand All @@ -40,41 +41,38 @@ private static StackItem Deserialize(BinaryReader reader, uint maxItemSize, Refe
StackItemType type = (StackItemType)reader.ReadByte();
switch (type)
{
case StackItemType.ByteArray:
deserialized.Push(new ByteArray(reader.ReadVarBytes((int)maxItemSize)));
case StackItemType.Any:
deserialized.Push(StackItem.Null);
break;
case StackItemType.Boolean:
deserialized.Push(new Boolean(reader.ReadBoolean()));
deserialized.Push(reader.ReadBoolean());
break;
case StackItemType.Integer:
deserialized.Push(new Integer(new BigInteger(reader.ReadVarBytes(Integer.MaxSize))));
deserialized.Push(new BigInteger(reader.ReadVarBytes(Integer.MaxSize)));
break;
case StackItemType.ByteArray:
deserialized.Push(reader.ReadVarBytes((int)maxItemSize));
break;
case StackItemType.Buffer:
Buffer buffer = new Buffer((int)reader.ReadVarInt(maxItemSize));
reader.FillBuffer(buffer.InnerBuffer);
deserialized.Push(buffer);
break;
case StackItemType.Array:
case StackItemType.Struct:
{
int count = (int)reader.ReadVarInt(maxItemSize);
deserialized.Push(new ContainerPlaceholder
{
Type = type,
ElementCount = count
});
int count = (int)reader.ReadVarInt(maxArraySize);
deserialized.Push(new ContainerPlaceholder(type, count));
undeserialized += count;
}
break;
case StackItemType.Map:
{
int count = (int)reader.ReadVarInt(maxItemSize);
deserialized.Push(new ContainerPlaceholder
{
Type = type,
ElementCount = count
});
int count = (int)reader.ReadVarInt(maxArraySize);
deserialized.Push(new ContainerPlaceholder(type, count));
undeserialized += count * 2;
}
break;
case StackItemType.Null:
deserialized.Push(StackItem.Null);
break;
default:
throw new FormatException();
}
Expand Down Expand Up @@ -127,36 +125,33 @@ public static byte[] Serialize(StackItem item, uint maxSize)

private static void Serialize(StackItem item, BinaryWriter writer, uint maxSize)
{
List<StackItem> serialized = new List<StackItem>();
List<CompoundType> serialized = new List<CompoundType>();
Stack<StackItem> unserialized = new Stack<StackItem>();
unserialized.Push(item);
while (unserialized.Count > 0)
{
item = unserialized.Pop();
writer.Write((byte)item.Type);
switch (item)
{
case ByteArray bytes:
writer.Write((byte)StackItemType.ByteArray);
writer.WriteVarBytes(bytes.ToByteArray());
case Null _:
break;
case Boolean _:
writer.Write((byte)StackItemType.Boolean);
writer.Write(item.ToBoolean());
break;
case Integer integer:
writer.Write((byte)StackItemType.Integer);
writer.WriteVarBytes(integer.ToByteArray());
writer.WriteVarBytes(integer.Span);
break;
case ByteArray bytes:
writer.WriteVarBytes(bytes.Span);
break;
case Buffer buffer:
writer.WriteVarBytes(buffer.InnerBuffer);
break;
case InteropInterface _:
throw new NotSupportedException();
case Array array:
if (serialized.Any(p => ReferenceEquals(p, array)))
throw new NotSupportedException();
serialized.Add(array);
if (array is Struct)
writer.Write((byte)StackItemType.Struct);
else
writer.Write((byte)StackItemType.Array);
writer.WriteVarInt(array.Count);
for (int i = array.Count - 1; i >= 0; i--)
unserialized.Push(array[i]);
Expand All @@ -165,17 +160,15 @@ private static void Serialize(StackItem item, BinaryWriter writer, uint maxSize)
if (serialized.Any(p => ReferenceEquals(p, map)))
throw new NotSupportedException();
serialized.Add(map);
writer.Write((byte)StackItemType.Map);
writer.WriteVarInt(map.Count);
foreach (var pair in map.Reverse())
{
unserialized.Push(pair.Value);
unserialized.Push(pair.Key);
}
break;
case Null _:
writer.Write((byte)StackItemType.Null);
break;
default:
throw new NotSupportedException();
}
if (writer.BaseStream.Position > maxSize)
throw new InvalidOperationException();
Expand Down
12 changes: 9 additions & 3 deletions src/neo/SmartContract/ContainerPlaceholder.cs
Expand Up @@ -5,10 +5,16 @@ namespace Neo.SmartContract
{
internal class ContainerPlaceholder : StackItem
{
public StackItemType Type;
public int ElementCount;
public override StackItemType Type { get; }
public int ElementCount { get; }

public override bool Equals(StackItem other) => throw new NotSupportedException();
public ContainerPlaceholder(StackItemType type, int count)
{
Type = type;
ElementCount = count;
}

public override bool Equals(object obj) => throw new NotSupportedException();

public override int GetHashCode() => throw new NotSupportedException();

Expand Down
17 changes: 2 additions & 15 deletions src/neo/SmartContract/InteropService.Binary.cs
@@ -1,7 +1,5 @@
using Neo.VM;
using Neo.VM.Types;
using System;
using System.IO;

namespace Neo.SmartContract
{
Expand Down Expand Up @@ -29,19 +27,8 @@ private static bool Binary_Serialize(ApplicationEngine engine)

private static bool Binary_Deserialize(ApplicationEngine engine)
{
StackItem item;
try
{
item = BinarySerializer.Deserialize(engine.CurrentContext.EvaluationStack.Pop().GetSpan(), engine.MaxItemSize, engine.ReferenceCounter);
}
catch (FormatException)
{
return false;
}
catch (IOException)
{
return false;
}
if (!engine.TryPop(out ReadOnlySpan<byte> data)) return false;
StackItem item = BinarySerializer.Deserialize(data, engine.MaxStackSize, engine.MaxItemSize, engine.ReferenceCounter);
engine.CurrentContext.EvaluationStack.Push(item);
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/Iterators/ByteArrayWrapper.cs
Expand Up @@ -10,7 +10,7 @@ internal class ByteArrayWrapper : IIterator

public ByteArrayWrapper(PrimitiveType value)
{
this.array = value.ToByteArray().ToArray();
this.array = value.Span.ToArray();
}

public void Dispose() { }
Expand Down

0 comments on commit 830c4a5

Please sign in to comment.