Skip to content

Commit

Permalink
Increase block height in the TestEngine
Browse files Browse the repository at this point in the history
  • Loading branch information
meevee98 committed Nov 16, 2020
1 parent 4229595 commit 9c1e083
Show file tree
Hide file tree
Showing 12 changed files with 324 additions and 21 deletions.
2 changes: 1 addition & 1 deletion neo-devpack-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Template.NEP5.UnitTests", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEngine", "src\TestEngine\TestEngine.csproj", "{39347E90-FC12-4018-8F22-828F0F1B2F7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestEngine.UnitTests", "tests\TestEngine.UnitTests\TestEngine.UnitTests.csproj", "{FFDC189F-2F72-4542-B28B-8EFA0F28E3CF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEngine.UnitTests", "tests\TestEngine.UnitTests\TestEngine.UnitTests.csproj", "{FFDC189F-2F72-4542-B28B-8EFA0F28E3CF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
84 changes: 69 additions & 15 deletions src/TestEngine/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Neo.SmartContract.Manifest;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;

namespace Neo.TestingEngine
Expand Down Expand Up @@ -33,6 +34,8 @@ private Engine()
Reset();
}

public int BlockCount => ((TestDataCache<UInt256, TrimmedBlock>)engine.Snapshot.Blocks).Count();

public void Reset()
{
engine = SetupNativeContracts();
Expand Down Expand Up @@ -63,6 +66,34 @@ public void AddSmartContract(string path)
}
}

public void IncreaseBlockCount(uint newHeight)
{
var snapshot = (TestSnapshot)engine.Snapshot;
var blocks = (TestDataCache<UInt256, TrimmedBlock>)snapshot.Blocks;
Block newBlock;
Block lastBlock = null;
if (blocks.Count() == 0)
{
newBlock = Blockchain.GenesisBlock;
}
else
{
newBlock = CreateBlock();
}

while (blocks.Count() < newHeight)
{
var hash = newBlock.Hash;
var trim = newBlock.Trim();
blocks.AddForTest(hash, trim);
lastBlock = newBlock;
newBlock = CreateBlock();
}

var index = (uint)(blocks.Count() - 1);
snapshot.SetCurrentBlockHash(index, lastBlock.Hash);
}

public void SetStorage(Dictionary<PrimitiveType, StackItem> storage)
{
foreach (var data in storage)
Expand All @@ -87,21 +118,8 @@ public JObject Run(string method, StackItem[] args)

private TestEngine SetupNativeContracts()
{
var block = new Block()
{
Index = 0,
ConsensusData = new ConsensusData(),
Transactions = new Transaction[0],
Witness = new Witness()
{
InvocationScript = new byte[0],
VerificationScript = Contract.CreateSignatureRedeemScript(ECPoint.FromBytes(PubKey, ECCurve.Secp256k1))
},
NextConsensus = UInt160.Zero,
MerkleRoot = UInt256.Zero,
PrevHash = UInt256.Zero
};

SetConsensus();
var block = Blockchain.GenesisBlock;
TestEngine engine = new TestEngine(TriggerType.Application, block);
((TestSnapshot)engine.Snapshot).SetPersistingBlock(block);

Expand All @@ -117,6 +135,42 @@ private TestEngine SetupNativeContracts()
return engine;
}

private void SetConsensus()
{
var _ = TestBlockchain.TheNeoSystem;
var store = Blockchain.Singleton.Store;
var block = Blockchain.GenesisBlock;
}

private Block CreateBlock()
{
var blocks = engine.Snapshot.Blocks.Seek().GetEnumerator();
while (blocks.MoveNext())
{ }

var (blockHash, trimmedBlock) = blocks.Current;
if (blockHash == null)
{
(blockHash, trimmedBlock) = (Blockchain.GenesisBlock.Hash, Blockchain.GenesisBlock.Trim());
}

return new Block()
{
Index = trimmedBlock.Index + 1,
Timestamp = trimmedBlock.Timestamp + Blockchain.MillisecondsPerBlock,
ConsensusData = new ConsensusData(),
Transactions = new Transaction[0],
Witness = new Witness()
{
InvocationScript = new byte[0],
VerificationScript = Contract.CreateSignatureRedeemScript(ECPoint.FromBytes(PubKey, ECCurve.Secp256k1))
},
NextConsensus = trimmedBlock.NextConsensus,
MerkleRoot = trimmedBlock.MerkleRoot,
PrevHash = blockHash
};
}

private static byte[] HexString2Bytes(string str)
{
if (str.IndexOf("0x") == 0)
Expand Down
15 changes: 12 additions & 3 deletions src/TestEngine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ public static JObject RunWithJson(JObject json)
{
smartContractTestCase.contracts = GetContractsFromJson(json["contracts"]);
}

if (json.ContainsProperty("height"))
{
smartContractTestCase.currentHeight = uint.Parse(json["height"].AsString());
}
return Run(smartContractTestCase);
}
catch (Exception e)
Expand All @@ -149,9 +154,7 @@ public static JObject RunWithJson(JObject json)
/// <summary>
/// Runs the given method from a nef script
/// </summary>
/// <param name="path">Absolute path of the script</param>
/// <param name="method">The name of the targeted method</param>
/// <param name="parameters">Arguments of the method</param>
/// <param name="smartContractTest">Object with the informations about the test case</param>
/// <returns>Returns a json with the engine state after executing the script</returns>
public static JObject Run(SmartContractTest smartContractTest)
{
Expand All @@ -165,11 +168,17 @@ public static JObject Run(SmartContractTest smartContractTest)
{
Engine.Instance.SetStorage(smartContractTest.storage);
}

foreach (var contract in smartContractTest.contracts)
{
Engine.Instance.AddSmartContract(contract.nefPath);
}

if (smartContractTest.currentHeight > 0)
{
Engine.Instance.IncreaseBlockCount(smartContractTest.currentHeight);
}

var stackParams = GetStackItemParameters(smartContractTest.methodParameters);
return Engine.Instance.Run(smartContractTest.methodName, stackParams);
}
Expand Down
1 change: 1 addition & 0 deletions src/TestEngine/SmartContractTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class SmartContractTest
public JArray methodParameters;
public Dictionary<PrimitiveType, StackItem> storage = new Dictionary<PrimitiveType, StackItem>();
public List<TestContract> contracts = new List<TestContract>();
public uint currentHeight = 0;

public SmartContractTest(string path, string method, JArray parameters)
{
Expand Down
33 changes: 33 additions & 0 deletions src/TestEngine/TestUtils/TestAccount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Neo.Wallets;

namespace Neo.TestingEngine
{
class TestAccount : WalletAccount
{
public override bool HasKey => this.key != null;

private byte[] privateKey;
private UInt160 scriptHash;
private KeyPair key = null;

public TestAccount(UInt160 scriptHash, byte[] privKey = null) : base(scriptHash)
{
if (privKey != null)
{
this.privateKey = privKey;
}
else
{
this.privateKey = new byte[32];
}

this.scriptHash = scriptHash;
this.key = new KeyPair(this.privateKey);
}

public override KeyPair GetKey()
{
return this.key;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Neo.Ledger;

namespace Neo.SmartContract.Framework.UnitTests
namespace Neo.TestingEngine
{
public static class TestBlockchain
{
Expand Down
40 changes: 40 additions & 0 deletions src/TestEngine/TestUtils/TestConsensusContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Neo.Consensus;
using Neo.Cryptography.ECC;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.Wallets;
using System.Collections.Generic;
using System.Linq;

namespace Neo.TestingEngine
{
public class TestConsensusContext : ConsensusContext
{
public TestConsensusContext(ECPoint[] validators, Wallet wallet, IStore store) : base(wallet, store)
{
this.Validators = validators;
this.CommitPayloads = new ConsensusPayload[validators.Length];
}

public void SetBlock(Block block)
{
this.Block = block;
}

public Block CreateBlock()
{
EnsureHeader();
Contract contract = Contract.CreateMultiSigContract(M, Validators);
ContractParametersContext sc = new ContractParametersContext(Block);

var witness = new Witness();
witness.InvocationScript = contract.Script;
witness.VerificationScript = new byte[0];
Block.Witness = witness;
Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray();
return Block;
}

}
}
8 changes: 8 additions & 0 deletions src/TestEngine/TestUtils/TestDataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ public void Clear()
dic.Clear();
}

/// <summary>
/// Gets the size of the storage for unit test
/// </summary>
public int Count()
{
return dic.Count;
}

/// <summary>
/// Include a new value to the storage for unit test
/// </summary>
Expand Down
9 changes: 8 additions & 1 deletion src/TestEngine/TestUtils/TestMetaDataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Neo.TestingEngine
{
public class TestMetaDataCache<T> : MetaDataCache<T> where T : class, ICloneable<T>, ISerializable, new()
{
private T metadata = null;
public TestMetaDataCache()
: base(null)
{
Expand All @@ -16,11 +17,17 @@ protected override void AddInternal(T item)

protected override T TryGetInternal()
{
return null;
return metadata;
}

protected override void UpdateInternal(T item)
{
metadata = item;
}

public void Update(T item)
{
UpdateInternal(item);
}
}
}
20 changes: 20 additions & 0 deletions src/TestEngine/TestUtils/TestSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,25 @@ public void ClearStorage()
{
((TestDataCache<StorageKey, StorageItem>)this._Storages).Clear();
}

public void SetCurrentBlockHash(uint index, UInt256 hash)
{
if (hash != null && Blocks is TestDataCache<UInt256, TrimmedBlock> blocks)
{
var blocksCount = blocks.Count();

if (index > blocksCount)
{
index = (uint)blocksCount;
}

var hashIndex = new HashIndexState()
{
Hash = hash,
Index = index
};
((TestMetaDataCache<HashIndexState>)BlockHashIndex).Update(hashIndex);
}
}
}
}
Loading

0 comments on commit 9c1e083

Please sign in to comment.