Skip to content

Commit

Permalink
Merge pull request neo-project#17 from neo-project/master
Browse files Browse the repository at this point in the history
update
  • Loading branch information
longfeiWan9 committed Jul 31, 2020
2 parents 6b9cb8c + aaa3dc7 commit 69d2b45
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 59 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
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
58 changes: 22 additions & 36 deletions src/neo/SmartContract/Native/PolicyContract.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma warning disable IDE0051

using Neo.IO;
using Neo.Ledger;
using Neo.Persistence;
using Neo.SmartContract.Manifest;
Expand Down Expand Up @@ -32,66 +31,52 @@ private bool CheckCommittees(ApplicationEngine engine)
return engine.CheckWitnessInternal(committeeMultiSigAddr);
}

internal override void Initialize(ApplicationEngine engine)
{
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MaxBlockSize), new StorageItem
{
Value = BitConverter.GetBytes(1024u * 256u)
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MaxTransactionsPerBlock), new StorageItem
{
Value = BitConverter.GetBytes(512u)
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MaxBlockSystemFee), new StorageItem
{
Value = BitConverter.GetBytes(9000 * (long)GAS.Factor) // For the transfer method of NEP5, the maximum persisting time is about three seconds.
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_FeePerByte), new StorageItem
{
Value = BitConverter.GetBytes(1000L)
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_BlockedAccounts), new StorageItem
{
Value = new UInt160[0].ToByteArray()
});
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public uint GetMaxTransactionsPerBlock(StoreView snapshot)
{
return (uint)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_MaxTransactionsPerBlock)];
StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxTransactionsPerBlock));
if (item is null) return 512;
return (uint)(BigInteger)item;
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public uint GetMaxBlockSize(StoreView snapshot)
{
return (uint)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_MaxBlockSize)];
StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSize));
if (item is null) return 1024 * 256;
return (uint)(BigInteger)item;
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public long GetMaxBlockSystemFee(StoreView snapshot)
{
return (long)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_MaxBlockSystemFee)];
StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_MaxBlockSystemFee));
if (item is null) return 9000 * (long)GAS.Factor; // For the transfer method of NEP5, the maximum persisting time is about three seconds.
return (long)(BigInteger)item;
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public long GetFeePerByte(StoreView snapshot)
{
return (long)(BigInteger)snapshot.Storages[CreateStorageKey(Prefix_FeePerByte)];
StorageItem item = snapshot.Storages.TryGet(CreateStorageKey(Prefix_FeePerByte));
if (item is null) return 1000;
return (long)(BigInteger)item;
}

[ContractMethod(0_01000000, CallFlags.AllowStates)]
public UInt160[] GetBlockedAccounts(StoreView snapshot)
{
return snapshot.Storages[CreateStorageKey(Prefix_BlockedAccounts)].GetSerializableList<UInt160>().ToArray();
return snapshot.Storages.TryGet(CreateStorageKey(Prefix_BlockedAccounts))
?.GetSerializableList<UInt160>().ToArray()
?? Array.Empty<UInt160>();
}

[ContractMethod(0_03000000, CallFlags.AllowModifyStates)]
private bool SetMaxBlockSize(ApplicationEngine engine, uint value)
{
if (!CheckCommittees(engine)) return false;
if (Network.P2P.Message.PayloadMaxSize <= value) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize));
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize), () => new StorageItem());
storage.Set(value);
return true;
}
Expand All @@ -100,7 +85,7 @@ private bool SetMaxBlockSize(ApplicationEngine engine, uint value)
private bool SetMaxTransactionsPerBlock(ApplicationEngine engine, uint value)
{
if (!CheckCommittees(engine)) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxTransactionsPerBlock));
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxTransactionsPerBlock), () => new StorageItem());
storage.Set(value);
return true;
}
Expand All @@ -110,7 +95,7 @@ private bool SetMaxBlockSystemFee(ApplicationEngine engine, long value)
{
if (!CheckCommittees(engine)) return false;
if (value <= 4007600) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSystemFee));
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSystemFee), () => new StorageItem());
storage.Set(value);
return true;
}
Expand All @@ -119,7 +104,7 @@ private bool SetMaxBlockSystemFee(ApplicationEngine engine, long value)
private bool SetFeePerByte(ApplicationEngine engine, long value)
{
if (!CheckCommittees(engine)) return false;
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_FeePerByte));
StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_FeePerByte), () => new StorageItem());
storage.Set(value);
return true;
}
Expand All @@ -129,7 +114,7 @@ private bool BlockAccount(ApplicationEngine engine, UInt160 account)
{
if (!CheckCommittees(engine)) return false;
StorageKey key = CreateStorageKey(Prefix_BlockedAccounts);
StorageItem storage = engine.Snapshot.Storages[key];
StorageItem storage = engine.Snapshot.Storages.GetOrAdd(key, () => new StorageItem(new byte[1]));
List<UInt160> accounts = storage.GetSerializableList<UInt160>();
if (accounts.Contains(account)) return false;
engine.Snapshot.Storages.GetAndChange(key);
Expand All @@ -142,7 +127,8 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account)
{
if (!CheckCommittees(engine)) return false;
StorageKey key = CreateStorageKey(Prefix_BlockedAccounts);
StorageItem storage = engine.Snapshot.Storages[key];
StorageItem storage = engine.Snapshot.Storages.TryGet(key);
if (storage is null) return false;
List<UInt160> accounts = storage.GetSerializableList<UInt160>();
int index = accounts.IndexOf(account);
if (index < 0) return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ public void TestSetup()
}

[TestMethod]
public void Check_Initialize()
public void Check_Default()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
var keyCount = snapshot.Storages.GetChangeSet().Count();

NativeContract.Policy.Initialize(ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0));

(keyCount + 5).Should().Be(snapshot.Storages.GetChangeSet().Count());

var ret = NativeContract.Policy.Call(snapshot, "getMaxTransactionsPerBlock");
ret.Should().BeOfType<VM.Types.Integer>();
Expand Down
10 changes: 10 additions & 0 deletions tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Neo.SmartContract;
using Neo.SmartContract.Iterators;
using Neo.SmartContract.Manifest;
using Neo.SmartContract.Native;
using Neo.VM.Types;
using Neo.Wallets;
using System;
Expand Down Expand Up @@ -135,6 +136,15 @@ public void TestContract_Create()
var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"));
Assert.ThrowsException<InvalidOperationException>(() => engine.CreateContract(script, manifest.ToJson().ToByteArray(false)));

var script_exceedMaxLength = new byte[ApplicationEngine.MaxContractLength + 1];
Assert.ThrowsException<ArgumentException>(() => engine.CreateContract(script_exceedMaxLength, manifest.ToJson().ToByteArray(true)));

var script_zeroLength = new byte[] { };
Assert.ThrowsException<ArgumentException>(() => engine.CreateContract(script_zeroLength, manifest.ToJson().ToByteArray(true)));

var manifest_zeroLength = new byte[] { };
Assert.ThrowsException<ArgumentException>(() => engine.CreateContract(script, manifest_zeroLength));

manifest.Abi.Hash = script.ToScriptHash();
engine.CreateContract(script, manifest.ToJson().ToByteArray(false));

Expand Down

0 comments on commit 69d2b45

Please sign in to comment.