From d3a9adf85e088758876397480f4098a7d965e446 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Thu, 23 Apr 2020 15:02:31 +0800 Subject: [PATCH 01/12] Create only one snapshot for persist --- src/neo/Ledger/Blockchain.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index fd76d1ebca..64e68cd1f9 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -488,6 +488,7 @@ private void Persist(Block block) } } snapshot.Blocks.Add(block.Hash, block.Trim()); + StoreView clonedSnapshot = snapshot.Clone(); foreach (Transaction tx in block.Transactions) { var state = new TransactionState @@ -498,7 +499,7 @@ private void Persist(Block block) snapshot.Transactions.Add(tx.Hash, state); - using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, snapshot.Clone(), tx.SystemFee)) + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { engine.LoadScript(tx.Script); state.VMState = engine.Execute(); From c3310ff13943d54dac8273ad149ba4c5c2705840 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Thu, 23 Apr 2020 15:49:00 +0800 Subject: [PATCH 02/12] Add vm fault handler --- src/neo/Ledger/Blockchain.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 64e68cd1f9..9e730eb2f1 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -507,6 +507,10 @@ private void Persist(Block block) { engine.Snapshot.Commit(); } + else + { + clonedSnapshot = snapshot.Clone(); + } ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); all_application_executed.Add(application_executed); From 6220b56a2de7a682571494186a126c8759046561 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Thu, 23 Apr 2020 15:53:17 +0800 Subject: [PATCH 03/12] Code optimization --- src/neo/Ledger/Blockchain.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 9e730eb2f1..9c329e0808 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -505,7 +505,7 @@ private void Persist(Block block) state.VMState = engine.Execute(); if (state.VMState == VMState.HALT) { - engine.Snapshot.Commit(); + clonedSnapshot.Commit(); } else { From cce60d5fcad490b60042609baaf808745508f494 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Wed, 29 Apr 2020 10:31:47 +0800 Subject: [PATCH 04/12] Add TODO comment to warn future delete case --- src/neo/Ledger/Blockchain.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 941f3e7e69..28f149dc20 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -489,6 +489,7 @@ private void Persist(Block block) } snapshot.Blocks.Add(block.Hash, block.Trim()); StoreView clonedSnapshot = snapshot.Clone(); + // TODO: Handle occassions where Datacache.Delete() is called by variable snapshot foreach (Transaction tx in block.Transactions) { var state = new TransactionState From 21f39b4f172f53f69544d5202a01ae18dd504cd3 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Wed, 29 Apr 2020 14:54:51 +0800 Subject: [PATCH 05/12] Write into cloned snapshot instead of snapshot during persist --- src/neo/Ledger/Blockchain.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 28f149dc20..eaa2a3f880 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -498,7 +498,8 @@ private void Persist(Block block) Transaction = tx }; - snapshot.Transactions.Add(tx.Hash, state); + clonedSnapshot.Transactions.Add(tx.Hash, state); + clonedSnapshot.Transactions.Commit(); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { From a4eaea04c924a1a2530c4ed68bc77f54bb05bbe9 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Wed, 29 Apr 2020 14:59:27 +0800 Subject: [PATCH 06/12] Update comment --- src/neo/Ledger/Blockchain.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index eaa2a3f880..5c3ae4bea0 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -489,7 +489,7 @@ private void Persist(Block block) } snapshot.Blocks.Add(block.Hash, block.Trim()); StoreView clonedSnapshot = snapshot.Clone(); - // TODO: Handle occassions where Datacache.Delete() is called by variable snapshot + // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (Transaction tx in block.Transactions) { var state = new TransactionState From cf01de0eca32415ef9fa34d05d8f7908a066a7c0 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Wed, 29 Apr 2020 18:22:35 +0800 Subject: [PATCH 07/12] Employ Func Datacache.AddAndCommit --- src/neo/IO/Caching/DataCache.cs | 6 ++++++ src/neo/Ledger/Blockchain.cs | 3 +-- tests/neo.UnitTests/IO/Caching/UT_DataCache.cs | 7 +++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/neo/IO/Caching/DataCache.cs b/src/neo/IO/Caching/DataCache.cs index dd0d5221c8..528f7c654e 100644 --- a/src/neo/IO/Caching/DataCache.cs +++ b/src/neo/IO/Caching/DataCache.cs @@ -314,6 +314,12 @@ public TValue TryGet(TKey key) } } + public void AddAndCommit(TKey key, TValue value) + { + Add(key, value); + Commit(); + } + protected abstract TValue TryGetInternal(TKey key); protected abstract void UpdateInternal(TKey key, TValue value); diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 5c3ae4bea0..37bcc52033 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -498,8 +498,7 @@ private void Persist(Block block) Transaction = tx }; - clonedSnapshot.Transactions.Add(tx.Hash, state); - clonedSnapshot.Transactions.Commit(); + clonedSnapshot.Transactions.AddAndCommit(tx.Hash, state); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { diff --git a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs index cd9752c819..a4eee602e9 100644 --- a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs +++ b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs @@ -343,5 +343,12 @@ public void TestTryGet() myDataCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2")); myDataCache.TryGet(new MyKey("key3")).Should().BeNull(); } + + [TestMethod] + public void TestAddAndCommit() + { + myDataCache.AddAndCommit(new MyKey("key1"), new MyValue("value1")); + myDataCache.InnerDict[new MyKey("key1")].Should().Be(new MyValue("value1")); + } } } From 76682a9c9b178fd0808dcbaafe6b356ff7d01eed Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 8 May 2020 16:35:21 +0800 Subject: [PATCH 08/12] remove AddAndCommit --- src/neo/IO/Caching/DataCache.cs | 6 ------ src/neo/Ledger/Blockchain.cs | 3 ++- tests/neo.UnitTests/IO/Caching/UT_DataCache.cs | 7 ------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/neo/IO/Caching/DataCache.cs b/src/neo/IO/Caching/DataCache.cs index 41568d64ea..687aae8f71 100644 --- a/src/neo/IO/Caching/DataCache.cs +++ b/src/neo/IO/Caching/DataCache.cs @@ -318,12 +318,6 @@ public TValue TryGet(TKey key) } } - public void AddAndCommit(TKey key, TValue value) - { - Add(key, value); - Commit(); - } - protected abstract TValue TryGetInternal(TKey key); protected abstract void UpdateInternal(TKey key, TValue value); diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index e0719a6111..58b4b9868f 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -497,7 +497,8 @@ private void Persist(Block block) Transaction = tx }; - clonedSnapshot.Transactions.AddAndCommit(tx.Hash, state); + clonedSnapshot.Transactions.Add(tx.Hash, state); + clonedSnapshot.Transactions.Commit(); using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee)) { diff --git a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs index e2b67b5904..e3cf329d43 100644 --- a/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs +++ b/tests/neo.UnitTests/IO/Caching/UT_DataCache.cs @@ -326,12 +326,5 @@ public void TestTryGet() myDataCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2")); myDataCache.TryGet(new MyKey("key3")).Should().BeNull(); } - - [TestMethod] - public void TestAddAndCommit() - { - myDataCache.AddAndCommit(new MyKey("key1"), new MyValue("value1")); - myDataCache.InnerDict[new MyKey("key1")].Should().Be(new MyValue("value1")); - } } } From 2de4df065a75534c3fbd8b746c78f6f5bb3c4763 Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Mon, 11 May 2020 19:07:17 +0800 Subject: [PATCH 09/12] Add fault transaction testcase --- tests/neo.UnitTests/Ledger/UT_Blockchain.cs | 59 +++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index 6faf336290..846b5bbec8 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -1,3 +1,4 @@ +using Akka.Actor; using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -10,6 +11,7 @@ using Neo.SmartContract.Native.Tokens; using Neo.Wallets; using Neo.Wallets.NEP6; +using System; using System.Linq; using System.Reflection; @@ -135,6 +137,63 @@ public void TestValidTransaction() } } + [TestMethod] + public void TestInvalidTransactionInPersist() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + //var validators = NativeContract.NEO.GetValidators(snapshot).Reverse().ToArray(); + var tx = new Transaction() + { + Attributes = Array.Empty(), + NetworkFee = 0, + Nonce = (uint)Environment.TickCount, + Script = new byte[] { 1 }, + Sender = UInt160.Zero, + SystemFee = 0, + ValidUntilBlock = Blockchain.GenesisBlock.Index + 1, + Version = 0, + Witnesses = new Witness[0], + }; + snapshot.Transactions.TryGet(tx.Hash).Should().BeNull(); + var block = new TestBlock + { + Version = 0, + PrevHash = UInt256.Zero, + MerkleRoot = UInt256.Zero, + Timestamp = 0, + Index = 1, + NextConsensus = UInt160.Zero, + Transactions = new Transaction[] { tx }, + ConsensusData = new ConsensusData + { + PrimaryIndex = 0 + }, + Witness = new Witness() + }; + system.Blockchain.Ask(block).Wait(); + snapshot = Blockchain.Singleton.GetSnapshot(); + snapshot.Transactions.TryGet(tx.Hash).Should().NotBeNull(); + snapshot.Transactions.Delete(tx.Hash); + snapshot.Blocks.Delete(block.Hash); + snapshot.PersistingBlock = null; + snapshot.BlockHashIndex.GetAndChange().Set(Blockchain.GenesisBlock); + snapshot.HeaderHashIndex.GetAndChange().Set(Blockchain.GenesisBlock); + snapshot.Storages.Delete(CreateStorageKey(14)); + snapshot.Commit(); + } + + internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) + { + StorageKey storageKey = new StorageKey + { + Id = NativeContract.NEO.Id, + Key = new byte[sizeof(byte) + (key?.Length ?? 0)] + }; + storageKey.Key[0] = prefix; + key?.CopyTo(storageKey.Key.AsSpan(1)); + return storageKey; + } + private Transaction CreateValidTx(NEP6Wallet wallet, UInt160 account, uint nonce) { var tx = wallet.MakeTransaction(new TransferOutput[] From 5000d8cf7b3fc6a1145df9d33fcd51d38e97e47f Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Tue, 12 May 2020 18:01:50 +0800 Subject: [PATCH 10/12] Fault transaction state test --- tests/neo.UnitTests/Ledger/UT_Blockchain.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index 846b5bbec8..917d58dd5a 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -9,6 +9,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.SmartContract.Native.Tokens; +using Neo.VM; using Neo.Wallets; using Neo.Wallets.NEP6; using System; @@ -173,6 +174,7 @@ public void TestInvalidTransactionInPersist() system.Blockchain.Ask(block).Wait(); snapshot = Blockchain.Singleton.GetSnapshot(); snapshot.Transactions.TryGet(tx.Hash).Should().NotBeNull(); + snapshot.Transactions.TryGet(tx.Hash).VMState.Should().Be(VMState.FAULT); snapshot.Transactions.Delete(tx.Hash); snapshot.Blocks.Delete(block.Hash); snapshot.PersistingBlock = null; From 334adc53f9a65bf44627c3c31ecbea0ff802799c Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 12 May 2020 19:51:29 +0800 Subject: [PATCH 11/12] fix ut --- tests/neo.UnitTests/Ledger/UT_Blockchain.cs | 37 ++++++--------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index 917d58dd5a..5569bd6de2 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -142,7 +142,6 @@ public void TestValidTransaction() public void TestInvalidTransactionInPersist() { var snapshot = Blockchain.Singleton.GetSnapshot(); - //var validators = NativeContract.NEO.GetValidators(snapshot).Reverse().ToArray(); var tx = new Transaction() { Attributes = Array.Empty(), @@ -155,33 +154,17 @@ public void TestInvalidTransactionInPersist() Version = 0, Witnesses = new Witness[0], }; - snapshot.Transactions.TryGet(tx.Hash).Should().BeNull(); - var block = new TestBlock - { - Version = 0, - PrevHash = UInt256.Zero, - MerkleRoot = UInt256.Zero, - Timestamp = 0, - Index = 1, - NextConsensus = UInt160.Zero, - Transactions = new Transaction[] { tx }, - ConsensusData = new ConsensusData - { - PrimaryIndex = 0 - }, - Witness = new Witness() - }; - system.Blockchain.Ask(block).Wait(); - snapshot = Blockchain.Singleton.GetSnapshot(); - snapshot.Transactions.TryGet(tx.Hash).Should().NotBeNull(); + + StoreView clonedSnapshot = snapshot.Clone(); + var state = new TransactionState + { + BlockIndex = 0, + Transaction = tx + }; + clonedSnapshot.Transactions.Add(tx.Hash, state); + clonedSnapshot.Transactions.Commit(); + state.VMState = VMState.FAULT; snapshot.Transactions.TryGet(tx.Hash).VMState.Should().Be(VMState.FAULT); - snapshot.Transactions.Delete(tx.Hash); - snapshot.Blocks.Delete(block.Hash); - snapshot.PersistingBlock = null; - snapshot.BlockHashIndex.GetAndChange().Set(Blockchain.GenesisBlock); - snapshot.HeaderHashIndex.GetAndChange().Set(Blockchain.GenesisBlock); - snapshot.Storages.Delete(CreateStorageKey(14)); - snapshot.Commit(); } internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) From a111535797965464dc0c394aefc50af22ae3e7ac Mon Sep 17 00:00:00 2001 From: Tommo-L Date: Tue, 12 May 2020 19:54:40 +0800 Subject: [PATCH 12/12] format --- tests/neo.UnitTests/Ledger/UT_Blockchain.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs index 5569bd6de2..c200bec7c8 100644 --- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs +++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs @@ -154,13 +154,12 @@ public void TestInvalidTransactionInPersist() Version = 0, Witnesses = new Witness[0], }; - StoreView clonedSnapshot = snapshot.Clone(); var state = new TransactionState - { - BlockIndex = 0, - Transaction = tx - }; + { + BlockIndex = 0, + Transaction = tx + }; clonedSnapshot.Transactions.Add(tx.Hash, state); clonedSnapshot.Transactions.Commit(); state.VMState = VMState.FAULT;