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

completion of the interfaces of AElf #1

Merged
merged 28 commits into from
Dec 16, 2017
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
4 changes: 4 additions & 0 deletions AElf.Kernel.Tests/AElf.Kernel.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
<PackageReference Include="Shouldly" Version="2.8.3" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AElf.Kernel\AElf.Kernel.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="TransactionTests.cs" />
</ItemGroup>
</Project>
39 changes: 39 additions & 0 deletions AElf.Kernel.Tests/PipelineTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using Moq;
using Shouldly;
using Xunit;

namespace AElf.Kernel.Tests
{
public class PipelineTest
{
[Fact]
public void BasicPipeline()
{
var blkheader = new Mock<IBlockHeader>();
var blk = new Mock<IBlock>();
blk.Setup(b => b.AddTransaction(It.IsAny<ITransaction>())).Returns(true);
blk.Setup(b => b.GetHeader()).Returns(blkheader.Object);

var hash = new Mock<IHash>();
hash.Setup(p => p.GetHashBytes()).Returns(new byte[] { 1, 2, 3 });

var merkletree = new Mock<IMerkleTree<ITransaction>>();
merkletree.Setup(m => m.AddNode(It.IsAny<IHash<ITransaction>>()));

var miner = new Mock<IMiner>();
miner.Setup(m => m.Mine(It.IsAny<IBlockHeader>())).Returns(new byte[] {4,5,6});

var chainmgr = new Mock<IChainManager>();
chainmgr.Setup(c => c.AddBlockAsync(It.IsAny<IChain>(), It.IsAny<IBlock>()));

var chain = new Mock<IChain>();

// basic pipeline
var tx = new Mock<ITransaction>();
blk.Object.AddTransaction(tx.Object);
miner.Object.Mine(blk.Object.GetHeader());
chainmgr.Object.AddBlockAsync(chain.Object,blk.Object);
}
}
}
16 changes: 16 additions & 0 deletions AElf.Kernel.Tests/TransactionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using Moq;
using Shouldly;
using Xunit;

namespace AElf.Kernel.Tests
{
public class TransactionTests
{
[Fact]
public void TransactionTests()
{
var tx = new Mock<ITransaction>();
}
}
}
7 changes: 7 additions & 0 deletions AElf.Kernel/AElf.Kernel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Account.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="LiteDB" Version="4.0.0" />
<PackageReference Include="QuickGraph" Version="3.6.61119.7" />
</ItemGroup>
</Project>
21 changes: 21 additions & 0 deletions AElf.Kernel/Account.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
<<<<<<< HEAD
using System;

namespace AElf.Kernel
{
/// <summary>
/// Account.
/// </summary>
public class Account : IAccount
{
private Address m_address;

Account(Address address) {
this.m_address = address;
}

IHash<IAccount> IAccount.GetAddress()
{
return this.m_address;
=======
namespace AElf.Kernel
{
public class Account : IAccount
{
public IHash<IAccount> GetAddress()
{
throw new System.NotImplementedException();
>>>>>>> a07f680fb13afbf511802b20cb65014b9ac9481d
}
}
}
8 changes: 7 additions & 1 deletion AElf.Kernel/IAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ public interface IAccount
/// <returns></returns>
IHash<IAccount> GetAddress();


/// <summary>
/// Invoke the specified methodName and values.
/// </summary>
/// <returns>The invoke.</returns>
/// <param name="methodName">Method name.</param>
/// <param name="values">Values.</param>
void Invoke(string methodName, params string[] values);
}
}
20 changes: 11 additions & 9 deletions AElf.Kernel/IAccountDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,38 @@

namespace AElf.Kernel
{

public interface ISerializable
{
byte[] Serialize();
}

/// <summary>
/// Data is stored associated with Account
/// </summary>
public interface IAccountDataProvider
{
/// <summary>
/// The merkle tree root of one account's data
/// Gets the data merkle tree root.
/// </summary>
/// <returns></returns>
Task<IHash<IMerkleTree<object>>> GetDataMerkleTreeRootAsync();

Task<IHash<IMerkleTree<ISerializable>>> GetDataMerkleTreeRootAsync();

/// <summary>
///
/// Gets the async.
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
Task<object> GetAsync(IHash address);
Task<ISerializable> GetAsync(IHash address);

/// <summary>
/// </summary>
/// <param name="address"></param>
/// <param name="obj"></param>
/// <returns></returns>
Task SetAsync(IHash address,object obj);
Task SetAsync(IHash address,ISerializable obj);

object Context { get; set; }

}



}
1 change: 0 additions & 1 deletion AElf.Kernel/IAccountManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ public interface IAccountManager
/// <param name="tx"></param>
/// <returns></returns>
Task ExecuteTransactionAsync(IAccount fromAccount,IAccount toAccount, ITransaction tx);

}
}
2 changes: 1 addition & 1 deletion AElf.Kernel/IBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public interface IBlock
IHash GetHash();
IBlockHeader GetHeader();
IBlockBody GetBody();
void AddTransaction(ITransaction tx);
bool AddTransaction(ITransaction tx);
}
}
1 change: 0 additions & 1 deletion AElf.Kernel/IMerkleTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ public interface IMerkleTree<T>
{
IHash<IMerkleTree<T>> ComputeRootHash();
void AddNode(IHash<T> hash);

}
}
8 changes: 8 additions & 0 deletions AElf.Kernel/IMiner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;
namespace AElf.Kernel
{
public interface IMiner
{
byte[] Mine(IBlockHeader blockheader);
}
}
53 changes: 53 additions & 0 deletions AElf.Kernel/LiteDBDataProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Threading.Tasks;
using LiteDB;

namespace AElf.Kernel
{
public class LiteDBDataProvider:IAccountDataProvider
{
struct Record:ISerializable
{
public IHash Key { get; set; }
public byte[] Value { get; set; }

public byte[] Serialize()
{
return Value;
}
}

private LiteDatabase db;

object IAccountDataProvider.Context { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

public LiteDBDataProvider(string path)
{
this.db = new LiteDatabase(@"path");
}

async Task<ISerializable> IAccountDataProvider.GetAsync(IHash key)
{
var c = this.db.GetCollection<Record>("data");
Task<ISerializable> task = new Task<ISerializable>(() => c.FindOne(x => x.Key.Equals(key)));
task.Start();
return await task;
}

async Task IAccountDataProvider.SetAsync(IHash key, ISerializable obj)
{
var c = this.db.GetCollection<Record>("data");
Task<bool> task = new Task<bool>(() => c.Upsert(new Record(){Key = key, Value = obj.Serialize()}));
task.Start();
await task;
return;
}

Task<IHash<IMerkleTree<ISerializable>>> IAccountDataProvider.GetDataMerkleTreeRootAsync()
{
var c = this.db.GetCollection<Record>("merkleroot");
// return c.FindOne(x => x.Key.Equals("root"));
throw new NotImplementedException();
}
}
}
111 changes: 111 additions & 0 deletions AElf.Kernel/TransactionExecutingManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics.Contracts;
using QuickGraph;

namespace AElf.Kernel
{
public class TransactionExecutingManager : ITransactionExecutingManager
{
private Mutex mut = new Mutex();
private Dictionary<IHash, List<ITransaction>> pending = new Dictionary<IHash, List<ITransaction>>();

public TransactionExecutingManager()
{
}

/// <summary>
/// AEs the lf. kernel. IT ransaction executing manager. execute async.
/// </summary>
/// <returns>The lf. kernel. IT ransaction executing manager. execute async.</returns>
/// <param name="tx">Tx.</param>
async Task ITransactionExecutingManager.ExecuteAsync(ITransaction tx)
{
Task task = new Task(() =>
{
// group transactions by resource type
var conflicts = tx.GetParallelMetaData().GetDataConflict();
this.mut.WaitOne();
foreach (var res in conflicts)
{
if (pending[res] != null)
{
pending[res] = new List<ITransaction>();

}
pending[res].Add(tx);

}
this.mut.ReleaseMutex();
});
task.Start();

await task;
}

/// <summary>
/// Schedule execution of transaction
/// </summary>
void Scheduler()
{
// How to improve this loop?
// https://github.com/ethereum/go-ethereum/blob/master/core/state_processor.go#L58
//
// Execution strategy(experimental)
// 1. tranform the dependency of Resource(R) into graph of related Transactions(T)
// 2. find the T(ransaction) which connects to the most neightbours
// 3. execute the T(ransaction), and removes this node from the graph
// 4. check to see if this removal leads to graph split
// 5. if YES, we can parallel execute the transactions from the splitted graph
// 6 if NO, goto step 2

// build the graph
UndirectedGraph<IHash, Edge<IHash>> graph = new UndirectedGraph<IHash, Edge<IHash>>(false);
this.mut.WaitOne();
foreach (var grp in pending)
{
foreach (var tx in grp.Value)
{
if (!graph.ContainsVertex(tx.GetHash())) {

}
graph.AddVertex(tx.GetHash());
}

foreach (var tx in grp.Value)
{
foreach (var neighbour in grp.Value)
{
if (!tx.Equals(neighbour))
{
graph.AddEdge(new Edge<IHash>(tx.GetHash(), neighbour.GetHash()));
}
}
}
}


// TODO : maintain a heap for tracking the most connected vertex
// execute the transaction, and remove it from the graph

// reset
pending = new Dictionary<IHash, List<ITransaction>>();
this.mut.ReleaseMutex();

// TODO: parallel execution on root nodes;
}


/// <summary>
/// Parallel Executes the graph
/// </summary>
/// <param name="n">N.</param>
void ExecuteGraph(UndirectedGraph<IHash, Edge<IHash>> n)
{
// TODO : check graph connectivity
// TODO: recursively execute transactions on the subgraph
}
}
}