Skip to content

Commit

Permalink
Create only one snapshot for persist (#1602)
Browse files Browse the repository at this point in the history
  • Loading branch information
Qiao-Jin committed May 16, 2020
1 parent b8fcb94 commit fb52579
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ private void Persist(Block block)
}
}
snapshot.Blocks.Add(block.Hash, block.Trim());
StoreView clonedSnapshot = snapshot.Clone();
// 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
Expand All @@ -493,15 +495,20 @@ 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, snapshot.Clone(), tx.SystemFee))
using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, tx, clonedSnapshot, tx.SystemFee))
{
engine.LoadScript(tx.Script);
state.VMState = engine.Execute();
if (state.VMState == VMState.HALT)
{
engine.Snapshot.Commit();
clonedSnapshot.Commit();
}
else
{
clonedSnapshot = snapshot.Clone();
}
ApplicationExecuted application_executed = new ApplicationExecuted(engine);
Context.System.EventStream.Publish(application_executed);
Expand Down
43 changes: 43 additions & 0 deletions tests/neo.UnitTests/Ledger/UT_Blockchain.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Akka.Actor;
using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand All @@ -8,8 +9,10 @@
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.SmartContract.Native.Tokens;
using Neo.VM;
using Neo.Wallets;
using Neo.Wallets.NEP6;
using System;
using System.Linq;
using System.Reflection;

Expand Down Expand Up @@ -135,6 +138,46 @@ public void TestValidTransaction()
}
}

[TestMethod]
public void TestInvalidTransactionInPersist()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
var tx = new Transaction()
{
Attributes = Array.Empty<TransactionAttribute>(),
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],
};
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);
}

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[]
Expand Down

0 comments on commit fb52579

Please sign in to comment.