Skip to content

Commit

Permalink
Merge pull request #137 from Ashuaidehao/dev-back
Browse files Browse the repository at this point in the history
Fix OOM
  • Loading branch information
Ashuaidehao committed Mar 8, 2022
2 parents 8eb5d85 + 1c7d4df commit 4d4ec35
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 80 deletions.
2 changes: 1 addition & 1 deletion neo3-gui/neo3-gui.tests/neo3-gui.tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>neo3_gui.tests</RootNamespace>

<IsPackable>false</IsPackable>
Expand Down
2 changes: 1 addition & 1 deletion neo3-gui/neo3-gui/Common/Analyzers/BlockAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private void AnalysisAppExecuteResult(Blockchain.ApplicationExecuted appExec)
execResult.GasConsumed = appExec.GasConsumed;
try
{
execResult.ResultStack = appExec.Stack.Select(q => q.ToContractParameter().ToJson()).ToArray();
execResult.ResultStack = appExec.Stack.Select(q => q.ToJObject()).ToArray();
}
catch (InvalidOperationException)
{
Expand Down
31 changes: 31 additions & 0 deletions neo3-gui/neo3-gui/Common/ByteArrayValueComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Neo.Common
{
public class ByteArrayValueComparer : IEqualityComparer<byte[]>
{

public static readonly ByteArrayValueComparer Default = new();

public bool Equals(byte[] x, byte[] y)
{
return x.AsSpan().SequenceEqual(y.AsSpan());
}

public int GetHashCode(byte[] obj)
{
unchecked
{
int hash = 17;
foreach (byte element in obj)
hash = hash * 31 + element;
return hash;
}
}

}
}
2 changes: 1 addition & 1 deletion neo3-gui/neo3-gui/Common/Consoles/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ private bool OnInvokeCommand(string[] args)
{
Console.WriteLine($"VM State: {engine.State}");
Console.WriteLine($"Gas Consumed: {engine.GasConsumed}");
Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToContractParameter().ToJson()))}");
Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToJObject()))}");
Console.WriteLine();
if (engine.State.HasFlag(VMState.FAULT))
{
Expand Down
16 changes: 13 additions & 3 deletions neo3-gui/neo3-gui/Common/Json/JObjectConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.Json;
Expand All @@ -11,10 +12,15 @@ namespace Neo.Common.Json
{
public class JObjectConverter : JsonConverter<JObject>
{
public const int MaxJsonLength = 10 * 1024 * 1024;
public override JObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using JsonDocument document = JsonDocument.ParseValue(ref reader);
var text= document.RootElement.Clone().ToString();
var text = document.RootElement.Clone().ToString();
if (!text.StartsWith("{"))
{
return (JString)text;
}
return JObject.Parse(text);
}

Expand Down Expand Up @@ -47,11 +53,15 @@ public override void Write(Utf8JsonWriter writer, JObject value, JsonSerializerO
if (pair.Value is null)
writer.WriteNullValue();
else
Write(writer, pair.Value,options);
Write(writer, pair.Value, options);
}
writer.WriteEndObject();
break;

}

if (writer.BytesCommitted > MaxJsonLength)
{
throw new InvalidCastException("json is too long to write!");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,15 @@ public void SaveTxExecuteLog(ExecuteResultInfo log)
{
if (log != null && log.TxId != null)
{
writeBatch.Put(ExecuteLogKey(log.TxId), log.SerializeJsonBytes());
try
{
writeBatch.Put(ExecuteLogKey(log.TxId), log.SerializeJsonBytes());
}
catch (InvalidCastException e)
{
log.ResultStack = e.ToString();
writeBatch.Put(ExecuteLogKey(log.TxId), log.SerializeJsonBytes());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public void Delete(byte[] key)

public void Put(byte[] key, byte[] value)
{
Native.leveldb_writebatch_put(handle, key, (UIntPtr)key.Length, value, (UIntPtr)value.Length);
if (value != null)
{
Native.leveldb_writebatch_put(handle, key, (UIntPtr)key.Length, value, (UIntPtr)value.Length);
}
}
}
}
138 changes: 71 additions & 67 deletions neo3-gui/neo3-gui/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
using Buffer = Neo.VM.Types.Buffer;
using VmArray = Neo.VM.Types.Array;
using JsonSerializer = System.Text.Json.JsonSerializer;
using Pointer = Neo.VM.Types.Pointer;

namespace Neo
{
Expand Down Expand Up @@ -388,6 +389,26 @@ public static byte[] SerializeJsonBytes<T>(this T obj)
return JsonSerializer.SerializeToUtf8Bytes(obj, SerializeOptions);
}


/// <summary>
/// serialize to utf8 json bytes, more performance than to json string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] SerializeJsonBytesSafely<T>(this T obj)
{
try
{
return SerializeJsonBytes(obj);
}
catch (Exception e)
{
Console.WriteLine(e);
return null;
}
}

/// <summary>
/// serialize to utf8 json string
/// </summary>
Expand Down Expand Up @@ -1281,91 +1302,59 @@ public static string GetExMessage(this Exception ex)
return msg;
}


/// <summary>
/// Converts the <see cref="StackItem"/> to a <see cref="ContractParameter"/>.
/// Convert StackItem to JObject
/// </summary>
/// <param name="item">The <see cref="StackItem"/> to convert.</param>
/// <returns>The converted <see cref="ContractParameter"/>.</returns>
public static ContractParameter ToContractParameter(this StackItem item, List<(StackItem, ContractParameter)> context = null)
/// <param name="item"></param>
/// <returns></returns>
public static JObject ToJObject(this StackItem item)
{
if (item is null) throw new ArgumentNullException(nameof(item));
return ToJson(item, null);
}


ContractParameter parameter = null;
private static JObject ToJson(StackItem item, HashSet<StackItem> context)
{
JObject json = new();
json["type"] = item.Type;
switch (item)
{
case VmArray array:
if (context is null)
context = new List<(StackItem, ContractParameter)>();
else
(_, parameter) = context.FirstOrDefault(p => ReferenceEquals(p.Item1, item));
if (parameter is null)
{
parameter = new ContractParameter { Type = ContractParameterType.Array };
context.Add((item, parameter));
parameter.Value = array.Select(p => ToContractParameter(p, context)).ToList();
}
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(array)) throw new InvalidOperationException();
json["value"] = new JArray(array.Select(p => ToJson(p, context)));
break;
case Map map:
if (context is null)
context = new List<(StackItem, ContractParameter)>();
else
(_, parameter) = context.FirstOrDefault(p => ReferenceEquals(p.Item1, item));
if (parameter is null)
{
parameter = new ContractParameter { Type = ContractParameterType.Map };
context.Add((item, parameter));
parameter.Value = map.Select(p =>
new KeyValuePair<ContractParameter, ContractParameter>(ToContractParameter(p.Key, context),
ToContractParameter(p.Value, context))).ToList();
}
case Boolean boolean:
json["value"] = boolean.GetBoolean();
break;
case Boolean _:
parameter = new ContractParameter
{
Type = ContractParameterType.Boolean,
Value = item.GetBoolean()
};
case Buffer buffer:
json["value"] = buffer.InnerBuffer.ToBase64String();
break;
case ByteString array:
parameter = new ContractParameter
{
Type = ContractParameterType.ByteArray,
Value = array.GetSpan().ToArray()
};
case ByteString _:
json["value"] = item.GetSpan().ToBase64String();
break;
case Buffer array:
parameter = new ContractParameter
{
Type = ContractParameterType.ByteArray,
Value = array.GetSpan().ToArray()
};
break;
case Integer i:
parameter = new ContractParameter
{
Type = ContractParameterType.Integer,
Value = i.GetInteger()
};
case Integer integer:
json["value"] = integer.GetInteger().ToString();
break;
case InteropInterface _:
parameter = new ContractParameter
case Map map:
context ??= new HashSet<StackItem>(ReferenceEqualityComparer.Instance);
if (!context.Add(map)) throw new InvalidOperationException();
json["value"] = new JArray(map.Select(p =>
{
Type = ContractParameterType.InteropInterface
};
JObject item = new();
item["key"] = ToJson(p.Key, context);
item["value"] = ToJson(p.Value, context);
return item;
}));
break;
case Null _:
parameter = new ContractParameter
{
Type = ContractParameterType.Any
};
case Pointer pointer:
json["value"] = pointer.Position;
break;
default:
throw new ArgumentException($"StackItemType({item.Type}) is not supported to ContractParameter.");
}
return parameter;
return json;
}



/// <summary>
/// /检查Nep Token
Expand Down Expand Up @@ -1423,5 +1412,20 @@ public static AssetType CheckNepAsset(this ContractState contract)
}
return AssetType.None;
}



private static readonly ConcurrentDictionary<byte[], string> _strCache = new(ByteArrayValueComparer.Default);

public static string ToBase64String(this byte[] data)
{
return _strCache.GetOrAdd(data, Convert.ToBase64String);
}


public static string ToBase64String(this ReadOnlySpan<byte> data)
{
return data.ToArray().ToBase64String();
}
}
}
8 changes: 4 additions & 4 deletions neo3-gui/neo3-gui/Services/ApiServices/ContractApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public async Task<object> InvokeContract(InvokeContractParameterModel para)
}
catch (Exception e)
{
return Error(ErrorCode.InvalidPara);
return Error(ErrorCode.InvalidPara, e.GetExMessage());
}

var signers = new List<Signer>();
Expand All @@ -261,11 +261,11 @@ public async Task<object> InvokeContract(InvokeContractParameterModel para)
var result = new InvokeResultModel();
result.VmState = engine.State;
result.GasConsumed = new BigDecimal((BigInteger)engine.GasConsumed, NativeContract.GAS.Decimals);
result.ResultStack = engine.ResultStack.Select(p => JStackItem.FromJson(p.ToContractParameter().ToJson())).ToList();
result.ResultStack = engine.ResultStack.Select(p => JStackItem.FromJson(p.ToJObject())).ToList();
result.Notifications = engine.Notifications?.Select(ConvertToEventModel).ToList();
if (engine.State.HasFlag(VMState.FAULT))
{
return Error(ErrorCode.EngineFault);
return Error(ErrorCode.EngineFault, engine.FaultException?.ToString());
}
if (!para.SendTx)
{
Expand Down Expand Up @@ -310,7 +310,7 @@ private static InvokeEventValueModel ConvertToEventModel(NotifyEventArgs notify)
if (eventMeta?.Parameters.Any() == true)
{
var json = new Dictionary<string, object>();
for (var i = 0; i < eventMeta.Parameters.Length; i++)
for (var i = 0; i < eventMeta.Parameters.Length && i < notify.State.Count; i++)
{
var p = eventMeta.Parameters[i];
json[p.Name] = ConvertValue(notify.State[i], p.Type);
Expand Down
12 changes: 11 additions & 1 deletion neo3-gui/neo3-gui/Services/ApiServices/TransactionApiService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Akka.Actor;
using Neo.Common;
using Neo.Common.Consoles;
using Neo.Common.Storage;
Expand Down Expand Up @@ -144,6 +146,14 @@ public async Task<object> RemoveUnconfirmTransaction(UInt256 txId)
return true;
}


public async Task<object> SendTransaction(string txRaw)
{
Transaction tx = Convert.FromBase64String(txRaw).AsSerializable<Transaction>();
Blockchain.RelayResult reason = Program.Starter.NeoSystem.Blockchain.Ask<Blockchain.RelayResult>(tx).Result;
return tx.ToJson(null);
}

/// <summary>
/// query all transactions(on chain)
/// </summary>
Expand Down

0 comments on commit 4d4ec35

Please sign in to comment.