diff --git a/src/neo/Consensus/ConsensusContext.cs b/src/neo/Consensus/ConsensusContext.cs
index 3d3a4fcb5d..7b1cc8b3d0 100644
--- a/src/neo/Consensus/ConsensusContext.cs
+++ b/src/neo/Consensus/ConsensusContext.cs
@@ -40,7 +40,7 @@ internal class ConsensusContext : IDisposable, ISerializable
///
/// Store all verified unsorted transactions' senders' fee currently in the consensus context.
///
- public SendersFeeMonitor SendersFeeMonitor = new SendersFeeMonitor();
+ public TransactionVerificationContext VerificationContext = new TransactionVerificationContext();
public SnapshotView Snapshot { get; private set; }
private KeyPair keyPair;
@@ -116,11 +116,11 @@ public void Deserialize(BinaryReader reader)
if (TransactionHashes.Length == 0 && !RequestSentOrReceived)
TransactionHashes = null;
Transactions = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash);
- SendersFeeMonitor = new SendersFeeMonitor();
+ VerificationContext = new TransactionVerificationContext();
if (Transactions != null)
{
foreach (Transaction tx in Transactions.Values)
- SendersFeeMonitor.AddSenderFee(tx);
+ VerificationContext.AddTransaction(tx);
}
}
@@ -266,7 +266,7 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs)
txs = txs.Take((int)maxTransactionsPerBlock);
List hashes = new List();
Transactions = new Dictionary();
- SendersFeeMonitor = new SendersFeeMonitor();
+ VerificationContext = new TransactionVerificationContext();
// Expected block size
var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count());
@@ -285,7 +285,7 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs)
hashes.Add(tx.Hash);
Transactions.Add(tx.Hash, tx);
- SendersFeeMonitor.AddSenderFee(tx);
+ VerificationContext.AddTransaction(tx);
}
TransactionHashes = hashes.ToArray();
diff --git a/src/neo/Consensus/ConsensusService.cs b/src/neo/Consensus/ConsensusService.cs
index 26648c4429..9caca4b651 100644
--- a/src/neo/Consensus/ConsensusService.cs
+++ b/src/neo/Consensus/ConsensusService.cs
@@ -64,20 +64,24 @@ internal ConsensusService(IActorRef localNode, IActorRef taskManager, IActorRef
private bool AddTransaction(Transaction tx, bool verify)
{
- if (verify && tx.Verify(context.Snapshot, context.SendersFeeMonitor.GetSenderFee(tx.Sender)) != VerifyResult.Succeed)
+ if (verify)
{
- Log($"Invalid transaction: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
- RequestChangeView(ChangeViewReason.TxInvalid);
- return false;
- }
- if (!NativeContract.Policy.CheckPolicy(tx, context.Snapshot))
- {
- Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
- RequestChangeView(ChangeViewReason.TxRejectedByPolicy);
- return false;
+ VerifyResult result = tx.Verify(context.Snapshot, context.VerificationContext);
+ if (result == VerifyResult.PolicyFail)
+ {
+ Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
+ RequestChangeView(ChangeViewReason.TxRejectedByPolicy);
+ return false;
+ }
+ else if (result != VerifyResult.Succeed)
+ {
+ Log($"Invalid transaction: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
+ RequestChangeView(ChangeViewReason.TxInvalid);
+ return false;
+ }
}
context.Transactions[tx.Hash] = tx;
- context.SendersFeeMonitor.AddSenderFee(tx);
+ context.VerificationContext.AddTransaction(tx);
return CheckPrepareResponse();
}
@@ -433,7 +437,7 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m
context.Block.ConsensusData.Nonce = message.Nonce;
context.TransactionHashes = message.TransactionHashes;
context.Transactions = new Dictionary();
- context.SendersFeeMonitor = new SendersFeeMonitor();
+ context.VerificationContext = new TransactionVerificationContext();
for (int i = 0; i < context.PreparationPayloads.Length; i++)
if (context.PreparationPayloads[i] != null)
if (!context.PreparationPayloads[i].GetDeserializedMessage().PreparationHash.Equals(payload.Hash))
diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs
index 142180932a..f4f0c6879e 100644
--- a/src/neo/Ledger/Blockchain.cs
+++ b/src/neo/Ledger/Blockchain.cs
@@ -290,15 +290,10 @@ private void OnFillMemoryPool(IEnumerable transactions)
{
if (View.ContainsTransaction(tx.Hash))
continue;
- if (!NativeContract.Policy.CheckPolicy(tx, currentSnapshot))
- continue;
// First remove the tx if it is unverified in the pool.
MemPool.TryRemoveUnVerified(tx.Hash, out _);
- // Verify the the transaction
- if (tx.Verify(currentSnapshot, MemPool.SendersFeeMonitor.GetSenderFee(tx.Sender)) != VerifyResult.Succeed)
- continue;
// Add to the memory pool
- MemPool.TryAdd(tx.Hash, tx);
+ MemPool.TryAdd(tx, currentSnapshot);
}
// Transactions originally in the pool will automatically be reverified based on their priority.
@@ -362,11 +357,7 @@ private VerifyResult OnNewInventory(IInventory inventory)
private VerifyResult OnNewTransaction(Transaction transaction)
{
if (ContainsTransaction(transaction.Hash)) return VerifyResult.AlreadyExists;
- if (!MemPool.CanTransactionFitInPool(transaction)) return VerifyResult.OutOfMemory;
- VerifyResult reason = transaction.Verify(currentSnapshot, MemPool.SendersFeeMonitor.GetSenderFee(transaction.Sender));
- if (reason != VerifyResult.Succeed) return reason;
- if (!MemPool.TryAdd(transaction.Hash, transaction)) return VerifyResult.OutOfMemory;
- return VerifyResult.Succeed;
+ return MemPool.TryAdd(transaction, currentSnapshot);
}
protected override void OnReceive(object message)
diff --git a/src/neo/Ledger/MemoryPool.cs b/src/neo/Ledger/MemoryPool.cs
index 62466d65e8..9a8b42b6e6 100644
--- a/src/neo/Ledger/MemoryPool.cs
+++ b/src/neo/Ledger/MemoryPool.cs
@@ -71,7 +71,7 @@ public class MemoryPool : IReadOnlyCollection
///
/// Store all verified unsorted transactions' senders' fee currently in the memory pool.
///
- public SendersFeeMonitor SendersFeeMonitor = new SendersFeeMonitor();
+ private TransactionVerificationContext VerificationContext = new TransactionVerificationContext();
///
/// Total count of transactions in the pool.
@@ -261,18 +261,21 @@ internal bool CanTransactionFitInPool(Transaction tx)
///
///
///
- internal bool TryAdd(UInt256 hash, Transaction tx)
+ internal VerifyResult TryAdd(Transaction tx, StoreView snapshot)
{
var poolItem = new PoolItem(tx);
- if (_unsortedTransactions.ContainsKey(hash)) return false;
+ if (_unsortedTransactions.ContainsKey(tx.Hash)) return VerifyResult.AlreadyExists;
List removedTransactions = null;
_txRwLock.EnterWriteLock();
try
{
- _unsortedTransactions.Add(hash, poolItem);
- SendersFeeMonitor.AddSenderFee(tx);
+ VerifyResult result = tx.Verify(snapshot, VerificationContext);
+ if (result != VerifyResult.Succeed) return result;
+
+ _unsortedTransactions.Add(tx.Hash, poolItem);
+ VerificationContext.AddTransaction(tx);
_sortedTransactions.Add(poolItem);
if (Count > Capacity)
@@ -290,7 +293,8 @@ internal bool TryAdd(UInt256 hash, Transaction tx)
plugin.TransactionsRemoved(MemoryPoolTxRemovalReason.CapacityExceeded, removedTransactions);
}
- return _unsortedTransactions.ContainsKey(hash);
+ if (!_unsortedTransactions.ContainsKey(tx.Hash)) return VerifyResult.OutOfMemory;
+ return VerifyResult.Succeed;
}
private List RemoveOverCapacity()
@@ -303,6 +307,9 @@ private List RemoveOverCapacity()
unsortedPool.Remove(minItem.Tx.Hash);
sortedPool.Remove(minItem);
removedTransactions.Add(minItem.Tx);
+
+ if (ReferenceEquals(sortedPool, _sortedTransactions))
+ VerificationContext.RemoveTransaction(minItem.Tx);
} while (Count > Capacity);
return removedTransactions;
@@ -315,7 +322,6 @@ private bool TryRemoveVerified(UInt256 hash, out PoolItem item)
return false;
_unsortedTransactions.Remove(hash);
- SendersFeeMonitor.RemoveSenderFee(item.Tx);
_sortedTransactions.Remove(item);
return true;
@@ -343,7 +349,7 @@ internal void InvalidateVerifiedTransactions()
// Clear the verified transactions now, since they all must be reverified.
_unsortedTransactions.Clear();
- SendersFeeMonitor = new SendersFeeMonitor();
+ VerificationContext = new TransactionVerificationContext();
_sortedTransactions.Clear();
}
@@ -413,23 +419,23 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool,
List reverifiedItems = new List(count);
List invalidItems = new List();
- // Since unverifiedSortedTxPool is ordered in an ascending manner, we take from the end.
- foreach (PoolItem item in unverifiedSortedTxPool.Reverse().Take(count))
+ _txRwLock.EnterWriteLock();
+ try
{
- if (item.Tx.VerifyForEachBlock(snapshot, SendersFeeMonitor.GetSenderFee(item.Tx.Sender)) == VerifyResult.Succeed)
+ // Since unverifiedSortedTxPool is ordered in an ascending manner, we take from the end.
+ foreach (PoolItem item in unverifiedSortedTxPool.Reverse().Take(count))
{
- reverifiedItems.Add(item);
- SendersFeeMonitor.AddSenderFee(item.Tx);
- }
- else // Transaction no longer valid -- it will be removed from unverifiedTxPool.
- invalidItems.Add(item);
+ if (item.Tx.VerifyForEachBlock(snapshot, VerificationContext) == VerifyResult.Succeed)
+ {
+ reverifiedItems.Add(item);
+ VerificationContext.AddTransaction(item.Tx);
+ }
+ else // Transaction no longer valid -- it will be removed from unverifiedTxPool.
+ invalidItems.Add(item);
- if (DateTime.UtcNow > reverifyCutOffTimeStamp) break;
- }
+ if (DateTime.UtcNow > reverifyCutOffTimeStamp) break;
+ }
- _txRwLock.EnterWriteLock();
- try
- {
int blocksTillRebroadcast = BlocksTillRebroadcast;
// Increases, proportionally, blocksTillRebroadcast if mempool has more items than threshold bigger RebroadcastMultiplierThreshold
if (Count > RebroadcastMultiplierThreshold)
@@ -450,7 +456,7 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool,
}
}
else
- SendersFeeMonitor.RemoveSenderFee(item.Tx);
+ VerificationContext.RemoveTransaction(item.Tx);
_unverifiedTransactions.Remove(item.Tx.Hash);
unverifiedSortedTxPool.Remove(item);
diff --git a/src/neo/Ledger/SendersFeeMonitor.cs b/src/neo/Ledger/SendersFeeMonitor.cs
deleted file mode 100644
index efe3ac6ebe..0000000000
--- a/src/neo/Ledger/SendersFeeMonitor.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Neo.Network.P2P.Payloads;
-using System.Collections.Generic;
-using System.Numerics;
-using System.Threading;
-
-namespace Neo.Ledger
-{
- public class SendersFeeMonitor
- {
- private readonly ReaderWriterLockSlim _senderFeeRwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-
- ///
- /// Store all verified unsorted transactions' senders' fee currently in the memory pool.
- ///
- private readonly Dictionary _senderFee = new Dictionary();
-
- public BigInteger GetSenderFee(UInt160 sender)
- {
- _senderFeeRwLock.EnterReadLock();
- if (!_senderFee.TryGetValue(sender, out var value))
- value = BigInteger.Zero;
- _senderFeeRwLock.ExitReadLock();
- return value;
- }
-
- public void AddSenderFee(Transaction tx)
- {
- _senderFeeRwLock.EnterWriteLock();
- if (_senderFee.TryGetValue(tx.Sender, out var value))
- _senderFee[tx.Sender] = value + tx.SystemFee + tx.NetworkFee;
- else
- _senderFee.Add(tx.Sender, tx.SystemFee + tx.NetworkFee);
- _senderFeeRwLock.ExitWriteLock();
- }
-
- public void RemoveSenderFee(Transaction tx)
- {
- _senderFeeRwLock.EnterWriteLock();
- if ((_senderFee[tx.Sender] -= tx.SystemFee + tx.NetworkFee) == 0) _senderFee.Remove(tx.Sender);
- _senderFeeRwLock.ExitWriteLock();
- }
- }
-}
diff --git a/src/neo/Ledger/TransactionVerificationContext.cs b/src/neo/Ledger/TransactionVerificationContext.cs
new file mode 100644
index 0000000000..a2bae45b0b
--- /dev/null
+++ b/src/neo/Ledger/TransactionVerificationContext.cs
@@ -0,0 +1,37 @@
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
+using Neo.SmartContract.Native;
+using System.Collections.Generic;
+using System.Numerics;
+
+namespace Neo.Ledger
+{
+ public class TransactionVerificationContext
+ {
+ ///
+ /// Store all verified unsorted transactions' senders' fee currently in the memory pool.
+ ///
+ private readonly Dictionary senderFee = new Dictionary();
+
+ public void AddTransaction(Transaction tx)
+ {
+ if (senderFee.TryGetValue(tx.Sender, out var value))
+ senderFee[tx.Sender] = value + tx.SystemFee + tx.NetworkFee;
+ else
+ senderFee.Add(tx.Sender, tx.SystemFee + tx.NetworkFee);
+ }
+
+ public bool CheckTransaction(Transaction tx, StoreView snapshot)
+ {
+ BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, tx.Sender);
+ senderFee.TryGetValue(tx.Sender, out var totalSenderFeeFromPool);
+ BigInteger fee = tx.SystemFee + tx.NetworkFee + totalSenderFeeFromPool;
+ return balance >= fee;
+ }
+
+ public void RemoveTransaction(Transaction tx)
+ {
+ if ((senderFee[tx.Sender] -= tx.SystemFee + tx.NetworkFee) == 0) senderFee.Remove(tx.Sender);
+ }
+ }
+}
diff --git a/src/neo/Network/P2P/Payloads/Transaction.cs b/src/neo/Network/P2P/Payloads/Transaction.cs
index 5aab07af65..8c4071379c 100644
--- a/src/neo/Network/P2P/Payloads/Transaction.cs
+++ b/src/neo/Network/P2P/Payloads/Transaction.cs
@@ -12,7 +12,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Numerics;
using Array = Neo.VM.Types.Array;
namespace Neo.Network.P2P.Payloads
@@ -268,10 +267,10 @@ public JObject ToJson()
bool IInventory.Verify(StoreView snapshot)
{
- return Verify(snapshot, BigInteger.Zero) == VerifyResult.Succeed;
+ return Verify(snapshot, null) == VerifyResult.Succeed;
}
- public virtual VerifyResult VerifyForEachBlock(StoreView snapshot, BigInteger totalSenderFeeFromPool)
+ public virtual VerifyResult VerifyForEachBlock(StoreView snapshot, TransactionVerificationContext context)
{
if (ValidUntilBlock <= snapshot.Height || ValidUntilBlock > snapshot.Height + MaxValidUntilBlockIncrement)
return VerifyResult.Expired;
@@ -280,9 +279,7 @@ public virtual VerifyResult VerifyForEachBlock(StoreView snapshot, BigInteger to
return VerifyResult.PolicyFail;
if (NativeContract.Policy.GetMaxBlockSystemFee(snapshot) < SystemFee)
return VerifyResult.PolicyFail;
- BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, Sender);
- BigInteger fee = SystemFee + NetworkFee + totalSenderFeeFromPool;
- if (balance < fee) return VerifyResult.InsufficientFunds;
+ if (!(context?.CheckTransaction(this, snapshot) ?? true)) return VerifyResult.InsufficientFunds;
if (hashes.Length != Witnesses.Length) return VerifyResult.Invalid;
for (int i = 0; i < hashes.Length; i++)
{
@@ -292,9 +289,9 @@ public virtual VerifyResult VerifyForEachBlock(StoreView snapshot, BigInteger to
return VerifyResult.Succeed;
}
- public virtual VerifyResult Verify(StoreView snapshot, BigInteger totalSenderFeeFromPool)
+ public virtual VerifyResult Verify(StoreView snapshot, TransactionVerificationContext context)
{
- VerifyResult result = VerifyForEachBlock(snapshot, totalSenderFeeFromPool);
+ VerifyResult result = VerifyForEachBlock(snapshot, context);
if (result != VerifyResult.Succeed) return result;
int size = Size;
if (size > MaxTransactionSize) return VerifyResult.Invalid;
diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs
index 6fd173b409..65c690424e 100644
--- a/src/neo/SmartContract/Native/PolicyContract.cs
+++ b/src/neo/SmartContract/Native/PolicyContract.cs
@@ -2,12 +2,10 @@
using Neo.IO;
using Neo.Ledger;
-using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract.Manifest;
using System;
using System.Collections.Generic;
-using System.Linq;
namespace Neo.SmartContract.Native
{
@@ -27,14 +25,6 @@ public PolicyContract()
Manifest.Features = ContractFeatures.HasStorage;
}
- internal bool CheckPolicy(Transaction tx, StoreView snapshot)
- {
- UInt160[] blockedAccounts = GetBlockedAccounts(snapshot);
- if (blockedAccounts.Intersect(tx.GetScriptHashesForVerifying(snapshot)).Any())
- return false;
- return true;
- }
-
private bool CheckCommittees(ApplicationEngine engine)
{
UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.Snapshot);
diff --git a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs
index a94bd98984..e4bf204d47 100644
--- a/tests/neo.UnitTests/Ledger/UT_Blockchain.cs
+++ b/tests/neo.UnitTests/Ledger/UT_Blockchain.cs
@@ -54,7 +54,7 @@ public class UT_Blockchain : TestKit
public void Initialize()
{
system = TestBlockchain.TheNeoSystem;
- Blockchain.Singleton.MemPool.TryAdd(txSample.Hash, txSample);
+ Blockchain.Singleton.MemPool.TryAdd(txSample, Blockchain.Singleton.GetSnapshot());
}
[TestMethod]
diff --git a/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs b/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs
index e2bb92836e..106e60adc5 100644
--- a/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs
+++ b/tests/neo.UnitTests/Ledger/UT_MemoryPool.cs
@@ -27,12 +27,20 @@ public void TransactionsRemoved(MemoryPoolTxRemovalReason reason, IEnumerable mock = new Mock();
- mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
- mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
+ mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
+ mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
mock.Object.Script = randomBytes;
mock.Object.NetworkFee = fee;
mock.Object.Attributes = Array.Empty();
@@ -97,9 +105,8 @@ private Transaction CreateTransactionWithFeeAndBalanceVerify(long fee)
var randomBytes = new byte[16];
random.NextBytes(randomBytes);
Mock mock = new Mock();
- mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns((StoreView snapshot, BigInteger amount) =>
- NativeContract.GAS.BalanceOf(snapshot, UInt160.Zero) >= amount + fee ? VerifyResult.Succeed : VerifyResult.InsufficientFunds);
- mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
+ mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns((StoreView snapshot, TransactionVerificationContext context) => context.CheckTransaction(mock.Object, snapshot) ? VerifyResult.Succeed : VerifyResult.InsufficientFunds);
+ mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
mock.Object.Script = randomBytes;
mock.Object.NetworkFee = fee;
mock.Object.Attributes = Array.Empty();
@@ -124,10 +131,11 @@ private Transaction CreateTransaction(long fee = -1)
private void AddTransactions(int count)
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
for (int i = 0; i < count; i++)
{
var txToAdd = CreateTransaction();
- _unit.TryAdd(txToAdd.Hash, txToAdd);
+ _unit.TryAdd(txToAdd, snapshot);
}
Console.WriteLine($"created {count} tx");
@@ -135,15 +143,17 @@ private void AddTransactions(int count)
private void AddTransaction(Transaction txToAdd)
{
- _unit.TryAdd(txToAdd.Hash, txToAdd);
+ var snapshot = Blockchain.Singleton.GetSnapshot();
+ _unit.TryAdd(txToAdd, snapshot);
}
private void AddTransactionsWithBalanceVerify(int count, long fee)
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
for (int i = 0; i < count; i++)
{
var txToAdd = CreateTransactionWithFeeAndBalanceVerify(fee);
- _unit.TryAdd(txToAdd.Hash, txToAdd);
+ _unit.TryAdd(txToAdd, snapshot);
}
Console.WriteLine($"created {count} tx");
@@ -355,10 +365,11 @@ public void TestInvalidateAll()
[TestMethod]
public void TestContainsKey()
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
AddTransactions(10);
var txToAdd = CreateTransaction();
- _unit.TryAdd(txToAdd.Hash, txToAdd);
+ _unit.TryAdd(txToAdd, snapshot);
_unit.ContainsKey(txToAdd.Hash).Should().BeTrue();
_unit.InvalidateVerifiedTransactions();
_unit.ContainsKey(txToAdd.Hash).Should().BeTrue();
@@ -394,11 +405,12 @@ public void TestIEnumerableGetEnumerator()
[TestMethod]
public void TestGetVerifiedTransactions()
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
var tx1 = CreateTransaction();
var tx2 = CreateTransaction();
- _unit.TryAdd(tx1.Hash, tx1);
+ _unit.TryAdd(tx1, snapshot);
_unit.InvalidateVerifiedTransactions();
- _unit.TryAdd(tx2.Hash, tx2);
+ _unit.TryAdd(tx2, snapshot);
IEnumerable enumerable = _unit.GetVerifiedTransactions();
enumerable.Count().Should().Be(1);
var enumerator = enumerable.GetEnumerator();
@@ -445,17 +457,19 @@ public void TestReVerifyTopUnverifiedTransactionsIfNeeded()
[TestMethod]
public void TestTryAdd()
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
var tx1 = CreateTransaction();
- _unit.TryAdd(tx1.Hash, tx1).Should().BeTrue();
- _unit.TryAdd(tx1.Hash, tx1).Should().BeFalse();
- _unit2.TryAdd(tx1.Hash, tx1).Should().BeFalse();
+ _unit.TryAdd(tx1, snapshot).Should().Be(VerifyResult.Succeed);
+ _unit.TryAdd(tx1, snapshot).Should().NotBe(VerifyResult.Succeed);
+ _unit2.TryAdd(tx1, snapshot).Should().NotBe(VerifyResult.Succeed);
}
[TestMethod]
public void TestTryGetValue()
{
+ var snapshot = Blockchain.Singleton.GetSnapshot();
var tx1 = CreateTransaction();
- _unit.TryAdd(tx1.Hash, tx1);
+ _unit.TryAdd(tx1, snapshot);
_unit.TryGetValue(tx1.Hash, out Transaction tx).Should().BeTrue();
tx.Should().BeEquivalentTo(tx1);
@@ -491,7 +505,7 @@ public void TestUpdatePoolForBlockPersisted()
var tx1 = CreateTransaction();
var tx2 = CreateTransaction();
Transaction[] transactions = { tx1, tx2 };
- _unit.TryAdd(tx1.Hash, tx1);
+ _unit.TryAdd(tx1, snapshot);
var block = new Block { Transactions = transactions };
diff --git a/tests/neo.UnitTests/Ledger/UT_SendersFeeMonitor.cs b/tests/neo.UnitTests/Ledger/UT_SendersFeeMonitor.cs
deleted file mode 100644
index 4c9e2fa333..0000000000
--- a/tests/neo.UnitTests/Ledger/UT_SendersFeeMonitor.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using Neo.Ledger;
-using Neo.Network.P2P.Payloads;
-using Neo.Persistence;
-using System;
-using System.Numerics;
-
-namespace Neo.UnitTests.Ledger
-{
- [TestClass]
- public class UT_SendersFeeMonitor
- {
- private Transaction CreateTransactionWithFee(long networkFee, long systemFee)
- {
- Random random = new Random();
- var randomBytes = new byte[16];
- random.NextBytes(randomBytes);
- Mock mock = new Mock();
- mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
- mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
- mock.Object.Script = randomBytes;
- mock.Object.NetworkFee = networkFee;
- mock.Object.SystemFee = systemFee;
- mock.Object.Attributes = Array.Empty();
- mock.Object.Signers = new Signer[] { new Signer() { Account = UInt160.Zero, Scopes = WitnessScope.FeeOnly } };
- mock.Object.Witnesses = new[]
- {
- new Witness
- {
- InvocationScript = new byte[0],
- VerificationScript = new byte[0]
- }
- };
- return mock.Object;
- }
-
- [TestMethod]
- public void TestMemPoolSenderFee()
- {
- Transaction transaction = CreateTransactionWithFee(1, 2);
- SendersFeeMonitor sendersFeeMonitor = new SendersFeeMonitor();
- sendersFeeMonitor.GetSenderFee(transaction.Sender).Should().Be(0);
- sendersFeeMonitor.AddSenderFee(transaction);
- sendersFeeMonitor.GetSenderFee(transaction.Sender).Should().Be(3);
- sendersFeeMonitor.AddSenderFee(transaction);
- sendersFeeMonitor.GetSenderFee(transaction.Sender).Should().Be(6);
- sendersFeeMonitor.RemoveSenderFee(transaction);
- sendersFeeMonitor.GetSenderFee(transaction.Sender).Should().Be(3);
- sendersFeeMonitor.RemoveSenderFee(transaction);
- sendersFeeMonitor.GetSenderFee(transaction.Sender).Should().Be(0);
- }
- }
-}
diff --git a/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs b/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs
new file mode 100644
index 0000000000..a3636a4c91
--- /dev/null
+++ b/tests/neo.UnitTests/Ledger/UT_TransactionVerificationContext.cs
@@ -0,0 +1,71 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
+using Neo.Persistence;
+using Neo.SmartContract;
+using Neo.SmartContract.Native;
+using System;
+using System.Numerics;
+
+namespace Neo.UnitTests.Ledger
+{
+ [TestClass]
+ public class UT_TransactionVerificationContext
+ {
+ private static NeoSystem testBlockchain;
+
+ [ClassInitialize]
+ public static void TestSetup(TestContext ctx)
+ {
+ testBlockchain = TestBlockchain.TheNeoSystem;
+ }
+
+ private Transaction CreateTransactionWithFee(long networkFee, long systemFee)
+ {
+ Random random = new Random();
+ var randomBytes = new byte[16];
+ random.NextBytes(randomBytes);
+ Mock mock = new Mock();
+ mock.Setup(p => p.VerifyForEachBlock(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
+ mock.Setup(p => p.Verify(It.IsAny(), It.IsAny())).Returns(VerifyResult.Succeed);
+ mock.Object.Script = randomBytes;
+ mock.Object.NetworkFee = networkFee;
+ mock.Object.SystemFee = systemFee;
+ mock.Object.Signers = new[] { new Signer { Account = UInt160.Zero } };
+ mock.Object.Attributes = Array.Empty();
+ mock.Object.Witnesses = new[]
+ {
+ new Witness
+ {
+ InvocationScript = new byte[0],
+ VerificationScript = new byte[0]
+ }
+ };
+ return mock.Object;
+ }
+
+ [TestMethod]
+ public void TestTransactionSenderFee()
+ {
+ var snapshot = Blockchain.Singleton.GetSnapshot();
+ ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, long.MaxValue);
+ BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, UInt160.Zero);
+ NativeContract.GAS.Burn(engine, UInt160.Zero, balance);
+ NativeContract.GAS.Mint(engine, UInt160.Zero, 8);
+
+ TransactionVerificationContext verificationContext = new TransactionVerificationContext();
+ var tx = CreateTransactionWithFee(1, 2);
+ verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
+ verificationContext.AddTransaction(tx);
+ verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
+ verificationContext.AddTransaction(tx);
+ verificationContext.CheckTransaction(tx, snapshot).Should().BeFalse();
+ verificationContext.RemoveTransaction(tx);
+ verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
+ verificationContext.AddTransaction(tx);
+ verificationContext.CheckTransaction(tx, snapshot).Should().BeFalse();
+ }
+ }
+}
diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
index de5079a46d..e6f7c3414a 100644
--- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
+++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
@@ -754,7 +754,7 @@ public void Transaction_Reverify_Hashes_Length_Unequal_To_Witnesses_Length()
};
UInt160[] hashes = txSimple.GetScriptHashesForVerifying(snapshot);
Assert.AreEqual(1, hashes.Length);
- Assert.AreNotEqual(VerifyResult.Succeed, txSimple.VerifyForEachBlock(snapshot, BigInteger.Zero));
+ Assert.AreNotEqual(VerifyResult.Succeed, txSimple.VerifyForEachBlock(snapshot, new TransactionVerificationContext()));
}
[TestMethod]
diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
index d464f45ea8..8eba15bf5c 100644
--- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
+++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
@@ -276,28 +276,5 @@ public void Check_Block_UnblockAccount()
ret.Should().BeOfType();
((VM.Types.Array)ret).Count.Should().Be(0);
}
-
- [TestMethod]
- public void TestCheckPolicy()
- {
- Transaction tx = Blockchain.GenesisBlock.Transactions[0];
- var snapshot = Blockchain.Singleton.GetSnapshot();
-
- StorageKey storageKey = new StorageKey
- {
- Id = NativeContract.Policy.Id,
- Key = new byte[sizeof(byte)]
- };
- storageKey.Key[0] = 15;
- snapshot.Storages.Add(storageKey, new StorageItem
- {
- Value = new UInt160[] { tx.Sender }.ToByteArray(),
- });
-
- NativeContract.Policy.CheckPolicy(tx, snapshot).Should().BeFalse();
-
- snapshot = Blockchain.Singleton.GetSnapshot();
- NativeContract.Policy.CheckPolicy(tx, snapshot).Should().BeTrue();
- }
}
}