From ee20bc944ca2c8d6512cfbd5b50dafa94ef12ddb Mon Sep 17 00:00:00 2001 From: Charis Date: Tue, 16 Jul 2019 12:49:12 +0800 Subject: [PATCH 01/11] add internal to DB and WriteBatch --- neo/IO/Data/LevelDB/DB.cs | 16 ++++++++-------- neo/IO/Data/LevelDB/WriteBatch.cs | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/neo/IO/Data/LevelDB/DB.cs b/neo/IO/Data/LevelDB/DB.cs index 559a109594..5f4a9f359a 100644 --- a/neo/IO/Data/LevelDB/DB.cs +++ b/neo/IO/Data/LevelDB/DB.cs @@ -16,7 +16,7 @@ private DB(IntPtr handle) this.handle = handle; } - public void Dispose() + public virtual void Dispose() { if (handle != IntPtr.Zero) { @@ -25,14 +25,14 @@ public void Dispose() } } - public void Delete(WriteOptions options, Slice key) + public virtual void Delete(WriteOptions options, Slice key) { IntPtr error; Native.leveldb_delete(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, out error); NativeHelper.CheckError(error); } - public Slice Get(ReadOptions options, Slice key) + public virtual Slice Get(ReadOptions options, Slice key) { UIntPtr length; IntPtr error; @@ -50,12 +50,12 @@ public Slice Get(ReadOptions options, Slice key) } } - public Snapshot GetSnapshot() + public virtual Snapshot GetSnapshot() { return new Snapshot(handle); } - public Iterator NewIterator(ReadOptions options) + public virtual Iterator NewIterator(ReadOptions options) { return new Iterator(Native.leveldb_create_iterator(handle, options.handle)); } @@ -73,14 +73,14 @@ public static DB Open(string name, Options options) return new DB(handle); } - public void Put(WriteOptions options, Slice key, Slice value) + public virtual void Put(WriteOptions options, Slice key, Slice value) { IntPtr error; Native.leveldb_put(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length, out error); NativeHelper.CheckError(error); } - public bool TryGet(ReadOptions options, Slice key, out Slice value) + public virtual bool TryGet(ReadOptions options, Slice key, out Slice value) { UIntPtr length; IntPtr error; @@ -101,7 +101,7 @@ public bool TryGet(ReadOptions options, Slice key, out Slice value) return true; } - public void Write(WriteOptions options, WriteBatch write_batch) + public virtual void Write(WriteOptions options, WriteBatch write_batch) { // There's a bug in .Net Core. // When calling DB.Write(), it will throw LevelDBException sometimes. diff --git a/neo/IO/Data/LevelDB/WriteBatch.cs b/neo/IO/Data/LevelDB/WriteBatch.cs index eaa3e08bd6..29d04643a1 100644 --- a/neo/IO/Data/LevelDB/WriteBatch.cs +++ b/neo/IO/Data/LevelDB/WriteBatch.cs @@ -11,17 +11,17 @@ public class WriteBatch Native.leveldb_writebatch_destroy(handle); } - public void Clear() + public virtual void Clear() { Native.leveldb_writebatch_clear(handle); } - public void Delete(Slice key) + public virtual void Delete(Slice key) { Native.leveldb_writebatch_delete(handle, key.buffer, (UIntPtr)key.buffer.Length); } - public void Put(Slice key, Slice value) + public virtual void Put(Slice key, Slice value) { Native.leveldb_writebatch_put(handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length); } From b76b04daa18414b4fa9d7ea2ce09234db7a8e328 Mon Sep 17 00:00:00 2001 From: luchuan Date: Sat, 12 Oct 2019 16:07:45 +0800 Subject: [PATCH 02/11] reset db.cs writebatch.cs --- neo/IO/Data/LevelDB/DB.cs | 16 ++++++++-------- neo/IO/Data/LevelDB/WriteBatch.cs | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/neo/IO/Data/LevelDB/DB.cs b/neo/IO/Data/LevelDB/DB.cs index b446f0eb56..04e8f50e8f 100644 --- a/neo/IO/Data/LevelDB/DB.cs +++ b/neo/IO/Data/LevelDB/DB.cs @@ -16,7 +16,7 @@ private DB(IntPtr handle) this.handle = handle; } - public virtual void Dispose() + public void Dispose() { if (handle != IntPtr.Zero) { @@ -25,14 +25,14 @@ public virtual void Dispose() } } - public virtual void Delete(WriteOptions options, Slice key) + public void Delete(WriteOptions options, Slice key) { IntPtr error; Native.leveldb_delete(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, out error); NativeHelper.CheckError(error); } - public virtual Slice Get(ReadOptions options, Slice key) + public Slice Get(ReadOptions options, Slice key) { UIntPtr length; IntPtr error; @@ -50,12 +50,12 @@ public virtual Slice Get(ReadOptions options, Slice key) } } - public virtual Snapshot GetSnapshot() + public Snapshot GetSnapshot() { return new Snapshot(handle); } - public virtual Iterator NewIterator(ReadOptions options) + public Iterator NewIterator(ReadOptions options) { return new Iterator(Native.leveldb_create_iterator(handle, options.handle)); } @@ -73,14 +73,14 @@ public static DB Open(string name, Options options) return new DB(handle); } - public virtual void Put(WriteOptions options, Slice key, Slice value) + public void Put(WriteOptions options, Slice key, Slice value) { IntPtr error; Native.leveldb_put(handle, options.handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length, out error); NativeHelper.CheckError(error); } - public virtual bool TryGet(ReadOptions options, Slice key, out Slice value) + public bool TryGet(ReadOptions options, Slice key, out Slice value) { UIntPtr length; IntPtr error; @@ -101,7 +101,7 @@ public virtual bool TryGet(ReadOptions options, Slice key, out Slice value) return true; } - public virtual void Write(WriteOptions options, WriteBatch write_batch) + public void Write(WriteOptions options, WriteBatch write_batch) { // There's a bug in .Net Core. // When calling DB.Write(), it will throw LevelDBException sometimes. diff --git a/neo/IO/Data/LevelDB/WriteBatch.cs b/neo/IO/Data/LevelDB/WriteBatch.cs index 03dcab1f3d..b3a9782108 100644 --- a/neo/IO/Data/LevelDB/WriteBatch.cs +++ b/neo/IO/Data/LevelDB/WriteBatch.cs @@ -11,17 +11,17 @@ public class WriteBatch Native.leveldb_writebatch_destroy(handle); } - public virtual void Clear() + public void Clear() { Native.leveldb_writebatch_clear(handle); } - public virtual void Delete(Slice key) + public void Delete(Slice key) { Native.leveldb_writebatch_delete(handle, key.buffer, (UIntPtr)key.buffer.Length); } - public virtual void Put(Slice key, Slice value) + public void Put(Slice key, Slice value) { Native.leveldb_writebatch_put(handle, key.buffer, (UIntPtr)key.buffer.Length, value.buffer, (UIntPtr)value.buffer.Length); } From 1c743e01ead5cfaf10321ba6247c1c724a047503 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 15 Nov 2019 18:39:32 +0800 Subject: [PATCH 03/11] fix Nep5Token.Burn method --- .../Native/Tokens/UT_GasToken.cs | 15 +++----------- neo/SmartContract/Native/Tokens/GasToken.cs | 20 ++++++++++++++++--- neo/SmartContract/Native/Tokens/Nep5Token.cs | 17 +++++++++++++--- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 7e811d3eda..d14285e67e 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -104,22 +104,13 @@ public void Check_BalanceOfTransferAndBurn() Assert.ThrowsException(() => NativeContract.GAS.Burn(engine, new UInt160(to), BigInteger.MinusOne)); - // Burn more than expected - - Assert.ThrowsException(() => - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000600000000001))); - // Real burn - - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1)); + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1)).Should().Be(1); NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000599999999999); - keyCount.Should().Be(snapshot.Storages.GetChangeSet().Count()); - - // Burn all - - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000599999999999)); + // Burn more than expected + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000600000000000)).Should().Be(3000599999999999); (keyCount - 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs index 7ef522dab7..0485e6ebf6 100644 --- a/neo/SmartContract/Native/Tokens/GasToken.cs +++ b/neo/SmartContract/Native/Tokens/GasToken.cs @@ -37,12 +37,26 @@ internal override bool Initialize(ApplicationEngine engine) protected override bool OnPersist(ApplicationEngine engine) { if (!base.OnPersist(engine)) return false; + BigInteger totalNetworkFee = 0; + BigInteger totalSysFee = 0; foreach (Transaction tx in engine.Snapshot.PersistingBlock.Transactions) - Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); + { + BigInteger burned = Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); + if (burned >= tx.NetworkFee) + { + totalNetworkFee += tx.NetworkFee; + totalSysFee += burned - tx.NetworkFee; + } + else + { + totalNetworkFee += burned; + } + } + ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.Snapshot.PersistingBlock.ConsensusData.PrimaryIndex]).ToScriptHash(); - Mint(engine, primary, engine.Snapshot.PersistingBlock.Transactions.Sum(p => p.NetworkFee)); - BigInteger sys_fee = GetSysFeeAmount(engine.Snapshot, engine.Snapshot.PersistingBlock.Index - 1) + engine.Snapshot.PersistingBlock.Transactions.Sum(p => p.SystemFee); + Mint(engine, primary, totalNetworkFee); + BigInteger sys_fee = GetSysFeeAmount(engine.Snapshot, engine.Snapshot.PersistingBlock.Index - 1) + totalSysFee; StorageKey key = CreateStorageKey(Prefix_SystemFeeAmount, BitConverter.GetBytes(engine.Snapshot.PersistingBlock.Index)); engine.Snapshot.Storages.Add(key, new StorageItem { diff --git a/neo/SmartContract/Native/Tokens/Nep5Token.cs b/neo/SmartContract/Native/Tokens/Nep5Token.cs index a95885a665..5a506e50e8 100644 --- a/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -87,15 +87,25 @@ internal protected virtual void Mint(ApplicationEngine engine, UInt160 account, engine.SendNotification(Hash, new StackItem[] { "Transfer", StackItem.Null, account.ToArray(), amount }); } - internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, BigInteger amount) + /// + /// Burn token, when the account balance less than amount, it will burn all the balance of the account + /// + /// The application engine + /// The burning account + /// The amount to be burned + /// The actual amount of burned + internal protected virtual BigInteger Burn(ApplicationEngine engine, UInt160 account, BigInteger amount) { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); - if (amount.IsZero) return; + if (amount.IsZero) return amount; StorageKey key = CreateAccountKey(account); StorageItem storage = engine.Snapshot.Storages.GetAndChange(key); TState state = new TState(); state.FromByteArray(storage.Value); - if (state.Balance < amount) throw new InvalidOperationException(); + if (state.Balance < amount) + { + amount = state.Balance; + } OnBalanceChanging(engine, account, state, -amount); if (state.Balance == amount) { @@ -111,6 +121,7 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, totalSupply -= amount; storage.Value = totalSupply.ToByteArray(); engine.SendNotification(Hash, new StackItem[] { "Transfer", account.ToArray(), StackItem.Null, amount }); + return amount; } [ContractMethod(0, ContractParameterType.String, Name = "name", SafeMethod = true)] From bb9a379aa97f568a74350ae957833518b4599405 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 15 Nov 2019 19:08:56 +0800 Subject: [PATCH 04/11] format --- neo/SmartContract/Native/Tokens/GasToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs index 0485e6ebf6..33b7dcd230 100644 --- a/neo/SmartContract/Native/Tokens/GasToken.cs +++ b/neo/SmartContract/Native/Tokens/GasToken.cs @@ -52,7 +52,7 @@ protected override bool OnPersist(ApplicationEngine engine) totalNetworkFee += burned; } } - + ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.Snapshot.PersistingBlock.ConsensusData.PrimaryIndex]).ToScriptHash(); Mint(engine, primary, totalNetworkFee); From 43985bd7865ce256e09160e7ff9e4a80310fc7a7 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 15 Nov 2019 19:17:56 +0800 Subject: [PATCH 05/11] format --- neo/SmartContract/Native/Tokens/GasToken.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs index 33b7dcd230..11dcfee9a9 100644 --- a/neo/SmartContract/Native/Tokens/GasToken.cs +++ b/neo/SmartContract/Native/Tokens/GasToken.cs @@ -52,7 +52,6 @@ protected override bool OnPersist(ApplicationEngine engine) totalNetworkFee += burned; } } - ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.Snapshot.PersistingBlock.ConsensusData.PrimaryIndex]).ToScriptHash(); Mint(engine, primary, totalNetworkFee); From c18c09d91b7fe9d12144fc342f6856c296947996 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Mon, 18 Nov 2019 15:16:59 +0800 Subject: [PATCH 06/11] reset and fix memorypool.ReverifyTransactions --- neo/Ledger/MemoryPool.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs index 8f37855a5c..32d287bc2a 100644 --- a/neo/Ledger/MemoryPool.cs +++ b/neo/Ledger/MemoryPool.cs @@ -418,7 +418,10 @@ internal void InvalidateAllTransactions() foreach (PoolItem item in unverifiedSortedTxPool.Reverse().Take(count)) { if (item.Tx.Reverify(snapshot, SendersFeeMonitor.GetSenderFee(item.Tx.Sender))) + { reverifiedItems.Add(item); + SendersFeeMonitor.AddSenderFee(item.Tx); + } else // Transaction no longer valid -- it will be removed from unverifiedTxPool. invalidItems.Add(item); @@ -440,7 +443,7 @@ internal void InvalidateAllTransactions() { if (_unsortedTransactions.TryAdd(item.Tx.Hash, item)) { - SendersFeeMonitor.AddSenderFee(item.Tx); + verifiedSortedTxPool.Add(item); if (item.LastBroadcastTimestamp < rebroadcastCutOffTime) @@ -449,6 +452,8 @@ internal void InvalidateAllTransactions() item.LastBroadcastTimestamp = DateTime.UtcNow; } } + else + SendersFeeMonitor.RemoveSenderFee(item.Tx); _unverifiedTransactions.Remove(item.Tx.Hash); unverifiedSortedTxPool.Remove(item); From 922c7a49d6f183e7038efaa7cecb69c598976605 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Mon, 18 Nov 2019 15:30:37 +0800 Subject: [PATCH 07/11] reset and fix ReverifyTransactions --- .../Native/Tokens/UT_GasToken.cs | 15 ++++++++++++--- neo/Ledger/MemoryPool.cs | 1 - neo/SmartContract/Native/Tokens/GasToken.cs | 19 +++---------------- neo/SmartContract/Native/Tokens/Nep5Token.cs | 17 +++-------------- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index d14285e67e..7e811d3eda 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -104,13 +104,22 @@ public void Check_BalanceOfTransferAndBurn() Assert.ThrowsException(() => NativeContract.GAS.Burn(engine, new UInt160(to), BigInteger.MinusOne)); + // Burn more than expected + + Assert.ThrowsException(() => + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000600000000001))); + // Real burn - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1)).Should().Be(1); + + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1)); NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000599999999999); - // Burn more than expected - NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000600000000000)).Should().Be(3000599999999999); + keyCount.Should().Be(snapshot.Storages.GetChangeSet().Count()); + + // Burn all + + NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000599999999999)); (keyCount - 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs index 65f4054956..78df9b97f6 100644 --- a/neo/Ledger/MemoryPool.cs +++ b/neo/Ledger/MemoryPool.cs @@ -441,7 +441,6 @@ internal void InvalidateAllTransactions() { if (_unsortedTransactions.TryAdd(item.Tx.Hash, item)) { - verifiedSortedTxPool.Add(item); if (item.LastBroadcastTimestamp < rebroadcastCutOffTime) diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs index 11dcfee9a9..7ef522dab7 100644 --- a/neo/SmartContract/Native/Tokens/GasToken.cs +++ b/neo/SmartContract/Native/Tokens/GasToken.cs @@ -37,25 +37,12 @@ internal override bool Initialize(ApplicationEngine engine) protected override bool OnPersist(ApplicationEngine engine) { if (!base.OnPersist(engine)) return false; - BigInteger totalNetworkFee = 0; - BigInteger totalSysFee = 0; foreach (Transaction tx in engine.Snapshot.PersistingBlock.Transactions) - { - BigInteger burned = Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); - if (burned >= tx.NetworkFee) - { - totalNetworkFee += tx.NetworkFee; - totalSysFee += burned - tx.NetworkFee; - } - else - { - totalNetworkFee += burned; - } - } + Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.Snapshot.PersistingBlock.ConsensusData.PrimaryIndex]).ToScriptHash(); - Mint(engine, primary, totalNetworkFee); - BigInteger sys_fee = GetSysFeeAmount(engine.Snapshot, engine.Snapshot.PersistingBlock.Index - 1) + totalSysFee; + Mint(engine, primary, engine.Snapshot.PersistingBlock.Transactions.Sum(p => p.NetworkFee)); + BigInteger sys_fee = GetSysFeeAmount(engine.Snapshot, engine.Snapshot.PersistingBlock.Index - 1) + engine.Snapshot.PersistingBlock.Transactions.Sum(p => p.SystemFee); StorageKey key = CreateStorageKey(Prefix_SystemFeeAmount, BitConverter.GetBytes(engine.Snapshot.PersistingBlock.Index)); engine.Snapshot.Storages.Add(key, new StorageItem { diff --git a/neo/SmartContract/Native/Tokens/Nep5Token.cs b/neo/SmartContract/Native/Tokens/Nep5Token.cs index 5a506e50e8..a95885a665 100644 --- a/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -87,25 +87,15 @@ internal protected virtual void Mint(ApplicationEngine engine, UInt160 account, engine.SendNotification(Hash, new StackItem[] { "Transfer", StackItem.Null, account.ToArray(), amount }); } - /// - /// Burn token, when the account balance less than amount, it will burn all the balance of the account - /// - /// The application engine - /// The burning account - /// The amount to be burned - /// The actual amount of burned - internal protected virtual BigInteger Burn(ApplicationEngine engine, UInt160 account, BigInteger amount) + internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, BigInteger amount) { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); - if (amount.IsZero) return amount; + if (amount.IsZero) return; StorageKey key = CreateAccountKey(account); StorageItem storage = engine.Snapshot.Storages.GetAndChange(key); TState state = new TState(); state.FromByteArray(storage.Value); - if (state.Balance < amount) - { - amount = state.Balance; - } + if (state.Balance < amount) throw new InvalidOperationException(); OnBalanceChanging(engine, account, state, -amount); if (state.Balance == amount) { @@ -121,7 +111,6 @@ internal protected virtual BigInteger Burn(ApplicationEngine engine, UInt160 acc totalSupply -= amount; storage.Value = totalSupply.ToByteArray(); engine.SendNotification(Hash, new StackItem[] { "Transfer", account.ToArray(), StackItem.Null, amount }); - return amount; } [ContractMethod(0, ContractParameterType.String, Name = "name", SafeMethod = true)] From 6b9b8498749d88f965cfcbd9a739d914097f8461 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Tue, 19 Nov 2019 17:07:57 +0800 Subject: [PATCH 08/11] add ut --- neo.UnitTests/Ledger/UT_MemoryPool.cs | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index 6f9022bef1..33ee665eed 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -8,6 +8,7 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.Plugins; +using Neo.SmartContract; using Neo.SmartContract.Native; using System; using System.Collections; @@ -92,6 +93,31 @@ private Transaction CreateTransactionWithFee(long fee) return mock.Object; } + private Transaction CreateTransactionWithFeeAndBalanceVerify(long fee) + { + Random random = new Random(); + var randomBytes = new byte[16]; + random.NextBytes(randomBytes); + Mock mock = new Mock(); + UInt160 sender = UInt160.Zero; + mock.Setup(p => p.Reverify(It.IsAny(), It.IsAny())).Returns(((Snapshot snapshot, BigInteger amount) => NativeContract.GAS.BalanceOf(snapshot, sender) >= amount + fee)); + mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(true); + mock.Object.Script = randomBytes; + mock.Object.Sender = sender; + mock.Object.NetworkFee = fee; + mock.Object.Attributes = new TransactionAttribute[0]; + mock.Object.Cosigners = new Cosigner[0]; + mock.Object.Witnesses = new[] + { + new Witness + { + InvocationScript = new byte[0], + VerificationScript = new byte[0] + } + }; + return mock.Object; + } + private Transaction CreateTransaction(long fee = -1) { if (fee != -1) @@ -115,6 +141,17 @@ private void AddTransaction(Transaction txToAdd) _unit.TryAdd(txToAdd.Hash, txToAdd); } + private void AddTransactionsWithBalanceVerify(int count, long fee) + { + for (int i = 0; i < count; i++) + { + var txToAdd = CreateTransactionWithFeeAndBalanceVerify(fee); + _unit.TryAdd(txToAdd.Hash, txToAdd); + } + + Console.WriteLine($"created {count} tx"); + } + [TestMethod] public void CapacityTest() { @@ -171,6 +208,36 @@ public void BlockPersistMovesTxToUnverifiedAndReverification() _unit.UnverifiedSortedTxCount.Should().Be(0); } + [TestMethod] + public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() + { + AddTransactionsWithBalanceVerify(70, 1); + + _unit.SortedTxCount.Should().Be(70); + + var block = new Block + { + Transactions = _unit.GetSortedVerifiedTransactions().Take(10).ToArray() + }; + + // Simulate the transfer process in tx by burning the balance + UInt160 sender = block.Transactions[0].Sender; + Snapshot snapshot = Blockchain.Singleton.GetSnapshot(); + BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, sender); + ApplicationEngine applicationEngine = new ApplicationEngine(TriggerType.All, block, snapshot, (long)balance); + NativeContract.GAS.Burn(applicationEngine, sender, balance); + snapshot.Commit(); + + // Persist block and reverify all the txs in mempool, but all the txs will be discarded + _unit.UpdatePoolForBlockPersisted(block, snapshot); + _unit.SortedTxCount.Should().Be(0); + _unit.UnverifiedSortedTxCount.Should().Be(0); + + // Withdraw the GAS by minting gas to the sender + NativeContract.GAS.Mint(applicationEngine, sender, balance); + snapshot.Commit(); + } + private void VerifyTransactionsSortedDescending(IEnumerable transactions) { Transaction lastTransaction = null; From c1bec9e826a2a455108632f8365473b995cc54e4 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Tue, 19 Nov 2019 18:00:49 +0800 Subject: [PATCH 09/11] remove commit --- neo.UnitTests/Ledger/UT_MemoryPool.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index 33ee665eed..b48209210c 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -226,7 +226,6 @@ public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, sender); ApplicationEngine applicationEngine = new ApplicationEngine(TriggerType.All, block, snapshot, (long)balance); NativeContract.GAS.Burn(applicationEngine, sender, balance); - snapshot.Commit(); // Persist block and reverify all the txs in mempool, but all the txs will be discarded _unit.UpdatePoolForBlockPersisted(block, snapshot); @@ -235,7 +234,6 @@ public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() // Withdraw the GAS by minting gas to the sender NativeContract.GAS.Mint(applicationEngine, sender, balance); - snapshot.Commit(); } private void VerifyTransactionsSortedDescending(IEnumerable transactions) From 6b30c05b63c9dbf0f1cacbf041cd06413a127fc9 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Wed, 20 Nov 2019 10:04:47 +0800 Subject: [PATCH 10/11] fix BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered.balance --- neo.UnitTests/Ledger/UT_MemoryPool.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index b48209210c..d13bc09723 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -211,7 +211,8 @@ public void BlockPersistMovesTxToUnverifiedAndReverification() [TestMethod] public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() { - AddTransactionsWithBalanceVerify(70, 1); + long txFee = 1; + AddTransactionsWithBalanceVerify(70, txFee); _unit.SortedTxCount.Should().Be(70); @@ -224,15 +225,18 @@ public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() UInt160 sender = block.Transactions[0].Sender; Snapshot snapshot = Blockchain.Singleton.GetSnapshot(); BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, sender); + ApplicationEngine applicationEngine = new ApplicationEngine(TriggerType.All, block, snapshot, (long)balance); NativeContract.GAS.Burn(applicationEngine, sender, balance); + NativeContract.GAS.Mint(applicationEngine, sender, txFee * 30); // Set the balance to meet 30 txs only // Persist block and reverify all the txs in mempool, but all the txs will be discarded _unit.UpdatePoolForBlockPersisted(block, snapshot); - _unit.SortedTxCount.Should().Be(0); + _unit.SortedTxCount.Should().Be(30); _unit.UnverifiedSortedTxCount.Should().Be(0); - // Withdraw the GAS by minting gas to the sender + // Revert the balance + NativeContract.GAS.Burn(applicationEngine, sender, txFee * 30); NativeContract.GAS.Mint(applicationEngine, sender, balance); } From e8fd7b9dc96c9540ec911d1c946141e3abf4f6d2 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Wed, 20 Nov 2019 10:05:39 +0800 Subject: [PATCH 11/11] update comments --- neo.UnitTests/Ledger/UT_MemoryPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index d13bc09723..631ae06dbc 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -230,7 +230,7 @@ public void BlockPersistAndReverificationWillAbandonTxAsBalanceTransfered() NativeContract.GAS.Burn(applicationEngine, sender, balance); NativeContract.GAS.Mint(applicationEngine, sender, txFee * 30); // Set the balance to meet 30 txs only - // Persist block and reverify all the txs in mempool, but all the txs will be discarded + // Persist block and reverify all the txs in mempool, but half of the txs will be discarded _unit.UpdatePoolForBlockPersisted(block, snapshot); _unit.SortedTxCount.Should().Be(30); _unit.UnverifiedSortedTxCount.Should().Be(0);