From d542ac3eb822da41743d0a0c5dd9872768f1dc81 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 20 Jul 2020 16:32:46 +0800 Subject: [PATCH 1/5] Fix VerifyWitnesses (#1776) --- src/neo/SmartContract/Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index b2cdb416a2..4448ff83b6 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -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; From ae383669a6d4e324f71265d83060d5d90b808892 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 20 Jul 2020 15:00:59 +0200 Subject: [PATCH 2/5] Ensure non predictable peers (#1739) * Plugins from List to array * Move false to init * Fix UT * Refactor --- src/neo/Network/P2P/Peer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index dc921b9526..106f530b71 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -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) { From 5406085af441bdf916a735b676bfbc67cf10cdc9 Mon Sep 17 00:00:00 2001 From: cloud8little <34291844+cloud8little@users.noreply.github.com> Date: Wed, 22 Jul 2020 15:16:25 +0800 Subject: [PATCH 3/5] Add Exception Message For CreateContract (#1787) * Add Exception Message When Create Contract * Add Exception Message * Code optimization * add UT Co-authored-by: Shargon Co-authored-by: Qiao Jin <43407364+Qiao-Jin@users.noreply.github.com> --- .../ApplicationEngine.Contract.cs | 32 ++++++++++--------- .../SmartContract/UT_InteropService.NEO.cs | 10 ++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 4ecfdde31e..19e20b071f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -30,14 +30,16 @@ 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++, @@ -45,7 +47,7 @@ internal ContractState CreateContract(byte[] script, byte[] manifest) 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; @@ -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, @@ -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"); } } @@ -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)) { @@ -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(); state.CallingScriptHash = callingScriptHash; diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 4d4eaf4b07..95a7ad7b66 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -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; @@ -135,6 +136,15 @@ public void TestContract_Create() var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); Assert.ThrowsException(() => engine.CreateContract(script, manifest.ToJson().ToByteArray(false))); + var script_exceedMaxLength = new byte[ApplicationEngine.MaxContractLength + 1]; + Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength, manifest.ToJson().ToByteArray(true))); + + var script_zeroLength = new byte[] { }; + Assert.ThrowsException(() => engine.CreateContract(script_zeroLength, manifest.ToJson().ToByteArray(true))); + + var manifest_zeroLength = new byte[] { }; + Assert.ThrowsException(() => engine.CreateContract(script, manifest_zeroLength)); + manifest.Abi.Hash = script.ToScriptHash(); engine.CreateContract(script, manifest.ToJson().ToByteArray(false)); From daa6e7a3b95524534107cfb6e174d9a52f3cd617 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 24 Jul 2020 16:40:33 +0800 Subject: [PATCH 4/5] Remove PolicyContract.Initialize() (#1795) --- .../SmartContract/Native/PolicyContract.cs | 58 +++++++------------ .../SmartContract/Native/UT_PolicyContract.cs | 7 +-- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index 872e9ec666..b4b19dd5fa 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -1,6 +1,5 @@ #pragma warning disable IDE0051 -using Neo.IO; using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract.Manifest; @@ -32,58 +31,44 @@ 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().ToArray(); + return snapshot.Storages.TryGet(CreateStorageKey(Prefix_BlockedAccounts)) + ?.GetSerializableList().ToArray() + ?? Array.Empty(); } [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] @@ -91,7 +76,7 @@ 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; } @@ -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; } @@ -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; } @@ -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; } @@ -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 accounts = storage.GetSerializableList(); if (accounts.Contains(account)) return false; engine.Snapshot.Storages.GetAndChange(key); @@ -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 accounts = storage.GetSerializableList(); int index = accounts.IndexOf(account); if (index < 0) return false; diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index 8eba15bf5c..ea25873654 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -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(); From aaa3dc7e6d58e786e78a0f49b5b3fc6e2b0f6bf6 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 30 Jul 2020 17:55:43 +0800 Subject: [PATCH 5/5] Fix PublishMyGet --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bef6f53e43..80959c6df5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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: