Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase block height in the TestEngine #9

Merged
merged 1 commit into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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