From 0eea25e9facbbce64d5820f3288a3e875a368044 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 14 Aug 2020 11:28:50 +0200 Subject: [PATCH 1/5] Optimize --- src/neo/Network/P2P/Payloads/Transaction.cs | 2 +- .../SmartContract/Native/PolicyContract.cs | 24 ++++++++++ .../SmartContract/Native/UT_PolicyContract.cs | 46 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs index 056a29b9ca..6c610344bf 100644 --- a/src/neo/Network/P2P/Payloads/Transaction.cs +++ b/src/neo/Network/P2P/Payloads/Transaction.cs @@ -286,7 +286,7 @@ public virtual VerifyResult VerifyForEachBlock(StoreView snapshot, TransactionVe if (ValidUntilBlock <= snapshot.Height || ValidUntilBlock > snapshot.Height + MaxValidUntilBlockIncrement) return VerifyResult.Expired; UInt160[] hashes = GetScriptHashesForVerifying(snapshot); - if (NativeContract.Policy.GetBlockedAccounts(snapshot).Intersect(hashes).Any()) + if (NativeContract.Policy.IsAnyAccountBlocked(snapshot, hashes)) return VerifyResult.PolicyFail; if (NativeContract.Policy.GetMaxBlockSystemFee(snapshot) < SystemFee) return VerifyResult.PolicyFail; diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index b4b19dd5fa..624c9fd0e9 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -71,6 +71,29 @@ public UInt160[] GetBlockedAccounts(StoreView snapshot) ?? Array.Empty(); } + public bool IsAnyAccountBlocked(StoreView snapshot, params UInt160[] hashes) + { + if (hashes.Length == 0) return false; + + var blockedList = snapshot.Storages.TryGet(CreateStorageKey(Prefix_BlockedAccounts)) + ?.GetSerializableList().ToArray() + ?? Array.Empty(); + + if (blockedList.Length == 0) return false; + + foreach (var acc in hashes) + { + foreach (var blockAccount in blockedList) + { + var comp = blockAccount.CompareTo(acc); + if (comp == 0) return true; + if (comp > 0) break; // It's already sorted + } + } + + return false; + } + [ContractMethod(0_03000000, CallFlags.AllowModifyStates)] private bool SetMaxBlockSize(ApplicationEngine engine, uint value) { @@ -119,6 +142,7 @@ private bool BlockAccount(ApplicationEngine engine, UInt160 account) if (accounts.Contains(account)) return false; engine.Snapshot.Storages.GetAndChange(key); accounts.Add(account); + accounts.Sort(); return true; } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index ea25873654..76a8322157 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -211,6 +211,52 @@ public void Check_SetFeePerByte() ret.GetInteger().Should().Be(1); } + [TestMethod] + public void Check_BlockAccount() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + + // Fake blockchain + + snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + + NativeContract.Policy.Initialize(ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0)); + + // Without signature + + var ret = NativeContract.Policy.Call(snapshot, "getBlockedAccounts"); + ret.Should().BeOfType(); + (ret as VM.Types.Array).Count.Should().Be(0); + + // With signature + + UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr), + "blockAccount", + new ContractParameter(ContractParameterType.ByteArray) { Value = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01").ToArray() }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeTrue(); + + // Same account + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr), + "blockAccount", + new ContractParameter(ContractParameterType.ByteArray) { Value = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01").ToArray() }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeFalse(); + + // Check + + NativeContract.Policy.IsAnyAccountBlocked(snapshot).Should().BeFalse(); + NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero).Should().BeFalse(); + NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero, UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).Should().BeTrue(); + + ret = NativeContract.Policy.Call(snapshot, "getBlockedAccounts"); + ret.Should().BeOfType(); + (ret as VM.Types.Array).Count.Should().Be(1); + (ret as VM.Types.Array)[0].GetSpan().ToHexString().Should().Be("01ff00ff00ff00ff00ff00ff00ff00ff00ff00a4"); + } + [TestMethod] public void Check_Block_UnblockAccount() { From 76153fe88fe785fb5ddf39a90956463ae64a8d23 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 14 Aug 2020 15:40:59 +0200 Subject: [PATCH 2/5] Change to BinarySearch --- src/neo/SmartContract/Native/PolicyContract.cs | 10 +++------- .../SmartContract/Native/UT_PolicyContract.cs | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index 624c9fd0e9..128c0788f3 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -79,15 +79,11 @@ public bool IsAnyAccountBlocked(StoreView snapshot, params UInt160[] hashes) ?.GetSerializableList().ToArray() ?? Array.Empty(); - if (blockedList.Length == 0) return false; - - foreach (var acc in hashes) + if (blockedList.Length > 0) { - foreach (var blockAccount in blockedList) + foreach (var acc in hashes) { - var comp = blockAccount.CompareTo(acc); - if (comp == 0) return true; - if (comp > 0) break; // It's already sorted + if (Array.BinarySearch(blockedList, acc) == 0) return true; } } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index 76a8322157..1c1efda521 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -250,6 +250,7 @@ public void Check_BlockAccount() NativeContract.Policy.IsAnyAccountBlocked(snapshot).Should().BeFalse(); NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero).Should().BeFalse(); NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero, UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).Should().BeTrue(); + NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), UInt160.Zero).Should().BeTrue(); ret = NativeContract.Policy.Call(snapshot, "getBlockedAccounts"); ret.Should().BeOfType(); From 9ab62bdc5be8261a91ca5680843408090e92db02 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 15 Aug 2020 12:57:35 +0200 Subject: [PATCH 3/5] Fix index --- src/neo/SmartContract/Native/PolicyContract.cs | 2 +- .../SmartContract/Native/UT_PolicyContract.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index 128c0788f3..908ad842bf 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -83,7 +83,7 @@ public bool IsAnyAccountBlocked(StoreView snapshot, params UInt160[] hashes) { foreach (var acc in hashes) { - if (Array.BinarySearch(blockedList, acc) == 0) return true; + if (Array.BinarySearch(blockedList, acc) != -1) return true; } } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index 1c1efda521..fcae3943d6 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -245,12 +245,22 @@ public void Check_BlockAccount() ret.Should().BeOfType(); ret.GetBoolean().Should().BeFalse(); + // Account B + + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr), + "blockAccount", + new ContractParameter(ContractParameterType.ByteArray) { Value = UInt160.Parse("0xb400ff00ff00ff00ff00ff00ff00ff00ff00ff01").ToArray() }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeTrue(); + // Check NativeContract.Policy.IsAnyAccountBlocked(snapshot).Should().BeFalse(); NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero).Should().BeFalse(); NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero, UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).Should().BeTrue(); NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), UInt160.Zero).Should().BeTrue(); + NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Zero, UInt160.Parse("0xb400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).Should().BeTrue(); + NativeContract.Policy.IsAnyAccountBlocked(snapshot, UInt160.Parse("0xb400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), UInt160.Zero).Should().BeTrue(); ret = NativeContract.Policy.Call(snapshot, "getBlockedAccounts"); ret.Should().BeOfType(); From e10e3d28a38341dfea9f5c3f61d1f721d5cb573c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 15 Aug 2020 13:07:20 +0200 Subject: [PATCH 4/5] fix ut --- tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index fcae3943d6..9cf22fae78 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -264,8 +264,9 @@ public void Check_BlockAccount() ret = NativeContract.Policy.Call(snapshot, "getBlockedAccounts"); ret.Should().BeOfType(); - (ret as VM.Types.Array).Count.Should().Be(1); + (ret as VM.Types.Array).Count.Should().Be(2); (ret as VM.Types.Array)[0].GetSpan().ToHexString().Should().Be("01ff00ff00ff00ff00ff00ff00ff00ff00ff00a4"); + (ret as VM.Types.Array)[1].GetSpan().ToHexString().Should().Be("01ff00ff00ff00ff00ff00ff00ff00ff00ff00b4"); } [TestMethod] From 477e9d6454003fe3a20cdc3c4e95d2b7639228cc Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 16 Aug 2020 09:32:51 +0200 Subject: [PATCH 5/5] Update src/neo/SmartContract/Native/PolicyContract.cs Co-authored-by: Erik Zhang --- src/neo/SmartContract/Native/PolicyContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index 908ad842bf..244b64deb2 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -83,7 +83,7 @@ public bool IsAnyAccountBlocked(StoreView snapshot, params UInt160[] hashes) { foreach (var acc in hashes) { - if (Array.BinarySearch(blockedList, acc) != -1) return true; + if (Array.BinarySearch(blockedList, acc) >= 0) return true; } }