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

[neox] Merge master #1789

Merged
merged 33 commits into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d275916
Allow call from native contract (#1700)
erikzhang Jun 22, 2020
8f509db
Fix MethodCallback (#1723)
shargon Jun 22, 2020
2047892
Fix #1714 (#1715)
erikzhang Jun 23, 2020
815180c
Add base64 SYSCALLs (#1717)
erikzhang Jun 23, 2020
cd988e8
Neo.VM.3.0.0-CI00230 (#1725)
erikzhang Jun 23, 2020
801ac7f
Allow to iterate buffer (#1726)
shargon Jun 24, 2020
66cfaf5
Update StorageContext.cs (#1728)
devhawk Jun 24, 2020
ae06696
Fix return value check (#1730)
erikzhang Jun 26, 2020
0874537
Fix ContractEventDescriptor (#1733)
erikzhang Jun 29, 2020
5ddf54b
fix enumerator (#1744)
Tommo-L Jul 1, 2020
76448e1
Change json fields to all lower case for consistency (#1736)
joeqian10 Jul 2, 2020
9001938
Replace DataCache.Find by DataCache.Seek (#1740)
Tommo-L Jul 2, 2020
ad5816a
Add MaxVerificationGas (#1745)
erikzhang Jul 3, 2020
54095fc
Create KeyBuilder (#1748)
erikzhang Jul 4, 2020
e91abdc
Speed up the initialization of ApplicationEngine. (#1749)
erikzhang Jul 6, 2020
699a28c
Change nef checksum to double SHA256 (#1751)
shargon Jul 8, 2020
5952ad2
Check witnesses on isStandard (#1754)
shargon Jul 8, 2020
791355c
Move NEP10 to manifest (#1729)
shargon Jul 9, 2020
39f7506
Capture fault Exception (#1761)
shargon Jul 10, 2020
c4799e9
Sender from signers (#1752)
shargon Jul 11, 2020
9d996e0
IApplicationEngineProvider (#1758)
devhawk Jul 11, 2020
54784e0
Remove the lock from SendersFeeMonitor and rename it to TransactionVe…
erikzhang Jul 13, 2020
d5b962c
Add EffectiveVoterTurnout (#1762)
erikzhang Jul 14, 2020
2c20df6
Remove AllowedTriggers from SYSCALLs (#1755)
erikzhang Jul 15, 2020
b471576
fix validatorscount (#1770)
Tommo-L Jul 16, 2020
6c01017
workflows: use checkout action v2 (#1775)
shargon Jul 17, 2020
da6be43
Add cache to native contract executions V2 (#1766)
shargon Jul 17, 2020
85543c7
Optimize attributes (#1774)
erikzhang Jul 18, 2020
9d83a64
Add length before compression data (#1768)
shargon Jul 18, 2020
d542ac3
Fix VerifyWitnesses (#1776)
erikzhang Jul 20, 2020
ae38366
Ensure non predictable peers (#1739)
shargon Jul 20, 2020
5406085
Add Exception Message For CreateContract (#1787)
cloud8little Jul 22, 2020
bee8588
Merge branch 'master' into neox-master
Jul 22, 2020
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
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
Expand All @@ -39,7 +39,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
Expand All @@ -61,7 +61,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
Expand All @@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Get version
id: get_version
run: |
Expand Down
14 changes: 7 additions & 7 deletions src/neo/IO/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using K4os.Compression.LZ4;
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -69,20 +70,19 @@ public static byte[] CompressLz4(this byte[] data)
int maxLength = LZ4Codec.MaximumOutputSize(data.Length);
using var buffer = MemoryPool<byte>.Shared.Rent(maxLength);
int length = LZ4Codec.Encode(data, buffer.Memory.Span);
byte[] result = new byte[length];
buffer.Memory[..length].CopyTo(result);
byte[] result = new byte[sizeof(uint) + length];
BinaryPrimitives.WriteInt32LittleEndian(result, data.Length);
buffer.Memory[..length].CopyTo(result.AsMemory(4));
return result;
}

public static byte[] DecompressLz4(this byte[] data, int maxOutput)
{
var maxDecompressDataLength = data.Length * 255;
if (maxDecompressDataLength > 0) maxOutput = Math.Min(maxOutput, maxDecompressDataLength);
using var buffer = MemoryPool<byte>.Shared.Rent(maxOutput);
int length = LZ4Codec.Decode(data, buffer.Memory.Span);
int length = BinaryPrimitives.ReadInt32LittleEndian(data);
if (length < 0 || length > maxOutput) throw new FormatException();
byte[] result = new byte[length];
buffer.Memory[..length].CopyTo(result);
if (LZ4Codec.Decode(data.AsSpan(4), result) != length)
throw new FormatException();
return result;
}

Expand Down
61 changes: 49 additions & 12 deletions src/neo/Ledger/StorageItem.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using Neo.IO;
using Neo.SmartContract;
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;

namespace Neo.Ledger
{
public class StorageItem : ICloneable<StorageItem>, ISerializable
{
private byte[] value;
private IInteroperable interoperable;
private object cache;
public bool IsConstant;

public int Size => Value.GetVarSize() + sizeof(bool);
Expand All @@ -16,33 +19,47 @@ public byte[] Value
{
get
{
if (value is null && interoperable != null)
value = BinarySerializer.Serialize(interoperable.ToStackItem(null), 4096);
return value;
return value ??= cache switch
{
BigInteger bi => bi.ToByteArrayStandard(),
IInteroperable interoperable => BinarySerializer.Serialize(interoperable.ToStackItem(null), 4096),
IReadOnlyCollection<ISerializable> list => list.ToByteArray(),
null => null,
_ => throw new InvalidCastException()
};
}
set
{
interoperable = null;
this.value = value;
cache = null;
}
}

public StorageItem()
{
}
public StorageItem() { }

public StorageItem(byte[] value, bool isConstant = false)
{
this.value = value;
this.IsConstant = isConstant;
}

public StorageItem(BigInteger value, bool isConstant = false)
{
this.cache = value;
this.IsConstant = isConstant;
}

public StorageItem(IInteroperable interoperable, bool isConstant = false)
{
this.interoperable = interoperable;
this.cache = interoperable;
this.IsConstant = isConstant;
}

public void Add(BigInteger integer)
{
Set(this + integer);
}

StorageItem ICloneable<StorageItem>.Clone()
{
return new StorageItem
Expand All @@ -66,19 +83,39 @@ void ICloneable<StorageItem>.FromReplica(StorageItem replica)

public T GetInteroperable<T>() where T : IInteroperable, new()
{
if (interoperable is null)
if (cache is null)
{
interoperable = new T();
var interoperable = new T();
interoperable.FromStackItem(BinarySerializer.Deserialize(value, 16, 34));
cache = interoperable;
}
value = null;
return (T)interoperable;
return (T)cache;
}

public List<T> GetSerializableList<T>() where T : ISerializable, new()
{
cache ??= new List<T>(value.AsSerializableArray<T>());
value = null;
return (List<T>)cache;
}

public void Serialize(BinaryWriter writer)
{
writer.WriteVarBytes(Value);
writer.Write(IsConstant);
}

public void Set(BigInteger integer)
{
cache = integer;
value = null;
}

public static implicit operator BigInteger(StorageItem item)
{
item.cache ??= new BigInteger(item.value);
return (BigInteger)item.cache;
}
}
}
15 changes: 14 additions & 1 deletion src/neo/Network/P2P/Payloads/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ public class Transaction : IEquatable<Transaction>, IInventory, IInteroperable
sizeof(long) + //NetworkFee
sizeof(uint); //ValidUntilBlock

private Dictionary<Type, TransactionAttribute[]> _attributesCache;
public TransactionAttribute[] Attributes
{
get => attributes;
set { attributes = value; _hash = null; _size = 0; }
set { attributes = value; _attributesCache = null; _hash = null; _size = 0; }
}

/// <summary>
Expand Down Expand Up @@ -219,6 +220,18 @@ void IInteroperable.FromStackItem(StackItem stackItem)
throw new NotSupportedException();
}

public T GetAttribute<T>() where T : TransactionAttribute
{
return GetAttributes<T>()?.First();
}

public T[] GetAttributes<T>() where T : TransactionAttribute
{
_attributesCache ??= attributes.GroupBy(p => p.GetType()).ToDictionary(p => p.Key, p => (TransactionAttribute[])p.OfType<T>().ToArray());
_attributesCache.TryGetValue(typeof(T), out var result);
return (T[])result;
}

public override int GetHashCode()
{
return Hash.GetHashCode();
Expand Down
4 changes: 3 additions & 1 deletion src/neo/Network/P2P/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ private void OnTimer()
// If there aren't available UnconnectedPeers, it triggers an abstract implementation of NeedMorePeers
if (UnconnectedPeers.Count == 0)
NeedMorePeers(MinDesiredConnections - ConnectedPeers.Count);
IPEndPoint[] endpoints = UnconnectedPeers.Take(MinDesiredConnections - ConnectedPeers.Count).ToArray();

Random rand = new Random();
IPEndPoint[] endpoints = UnconnectedPeers.OrderBy(u => rand.Next()).Take(MinDesiredConnections - ConnectedPeers.Count).ToArray();
ImmutableInterlocked.Update(ref UnconnectedPeers, p => p.Except(endpoints));
foreach (IPEndPoint endpoint in endpoints)
{
Expand Down
32 changes: 17 additions & 15 deletions src/neo/SmartContract/ApplicationEngine.Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,24 @@ partial class ApplicationEngine

internal ContractState CreateContract(byte[] script, byte[] manifest)
{
if (script.Length == 0 || script.Length > MaxContractLength || manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
throw new ArgumentException();
if (script.Length == 0 || script.Length > MaxContractLength)
throw new ArgumentException($"Invalid Script Length: {script.Length}");
if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");

AddGas(StoragePrice * (script.Length + manifest.Length));

UInt160 hash = script.ToScriptHash();
ContractState contract = Snapshot.Contracts.TryGet(hash);
if (contract != null) throw new InvalidOperationException();
if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}");
contract = new ContractState
{
Id = Snapshot.ContractId.GetAndChange().NextId++,
Script = script.ToArray(),
Manifest = ContractManifest.Parse(manifest)
};

if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException();
if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException($"Invalid Manifest Hash: {hash}");

Snapshot.Contracts.Add(hash, contract);
return contract;
Expand All @@ -56,15 +58,15 @@ internal void UpdateContract(byte[] script, byte[] manifest)
AddGas(StoragePrice * (script?.Length ?? 0 + manifest?.Length ?? 0));

var contract = Snapshot.Contracts.TryGet(CurrentScriptHash);
if (contract is null) throw new InvalidOperationException();
if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {CurrentScriptHash}");

if (script != null)
{
if (script.Length == 0 || script.Length > MaxContractLength)
throw new ArgumentException();
throw new ArgumentException($"Invalid Script Length: {script.Length}");
UInt160 hash_new = script.ToScriptHash();
if (hash_new.Equals(CurrentScriptHash) || Snapshot.Contracts.TryGet(hash_new) != null)
throw new InvalidOperationException();
throw new InvalidOperationException($"Adding Contract Hash Already Exist: {hash_new}");
contract = new ContractState
{
Id = contract.Id,
Expand All @@ -78,13 +80,13 @@ internal void UpdateContract(byte[] script, byte[] manifest)
if (manifest != null)
{
if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
throw new ArgumentException();
throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
contract = Snapshot.Contracts.GetAndChange(contract.ScriptHash);
contract.Manifest = ContractManifest.Parse(manifest);
if (!contract.Manifest.IsValid(contract.ScriptHash))
throw new InvalidOperationException();
throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}");
if (!contract.HasStorage && Snapshot.Storages.Find(BitConverter.GetBytes(contract.Id)).Any())
throw new InvalidOperationException();
throw new InvalidOperationException($"Contract Does Not Support Storage But Uses Storage");
}
}

Expand Down Expand Up @@ -113,15 +115,15 @@ internal void CallContractEx(UInt160 contractHash, string method, Array args, Ca

private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags)
{
if (method.StartsWith('_')) throw new ArgumentException();
if (method.StartsWith('_')) throw new ArgumentException($"Invalid Method Name: {method}");

ContractState contract = Snapshot.Contracts.TryGet(contractHash);
if (contract is null) throw new InvalidOperationException();
if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}");

ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest;

if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method))
throw new InvalidOperationException();
throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}");

if (invocationCounter.TryGetValue(contract.ScriptHash, out var counter))
{
Expand All @@ -139,8 +141,8 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg
CallFlags callingFlags = state.CallFlags;

ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method);
if (md is null) throw new InvalidOperationException();
if (args.Count != md.Parameters.Length) throw new InvalidOperationException();
if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}");
if (args.Count != md.Parameters.Length) throw new InvalidOperationException($"Method {method} Expects {md.Parameters.Length} Arguments But Receives {args.Count} Arguments");
ExecutionContext context_new = LoadScript(contract.Script);
state = context_new.GetState<ExecutionContextState>();
state.CallingScriptHash = callingScriptHash;
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap
}
using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.Clone(), gas))
{
engine.LoadScript(verification, CallFlags.ReadOnly).InstructionPointer = offset;
engine.LoadScript(verification, CallFlags.None).InstructionPointer = offset;
engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None);
if (engine.Execute() == VMState.FAULT) return false;
if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) return false;
Expand Down
Loading