Skip to content
This repository has been archived by the owner on Aug 16, 2021. It is now read-only.

Commit

Permalink
merge from master (#30)
Browse files Browse the repository at this point in the history
* Block repository to commit in batches

* BlockStore

* AsyncLoop, and small midifications to BlockStoreLoop
  • Loading branch information
dangershony authored Mar 6, 2017
1 parent 60b6e67 commit 37a6c23
Show file tree
Hide file tree
Showing 21 changed files with 1,052 additions and 128 deletions.
104 changes: 90 additions & 14 deletions Stratis.Bitcoin.Tests/BlockStoreTests.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,76 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using NBitcoin;
using NBitcoin.BitcoinCore;
using NBitcoin.Protocol;
using Stratis.Bitcoin.BlockStore;
using Stratis.Bitcoin.Connection;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.MemoryPool;
using Xunit;

namespace Stratis.Bitcoin.Tests
{
public class BlockStoreTests
{

//[Fact]
public void BlockRepositoryBench()
{
using (var dir = TestDirectory.Create())
{
using (var blockRepo = new BlockStore.BlockRepository(Network.Main, dir.FolderName))
{
var lst = new List<Block>();
for (int i = 0; i < 30; i++)
{
// roughly 1mb blocks
var block = new Block();
for (int j = 0; j < 3000; j++)
{
var trx = new Transaction();
block.AddTransaction(new Transaction());
trx.AddInput(new TxIn(Script.Empty));
trx.AddOutput(Money.COIN + j + i, new Script(Guid.NewGuid().ToByteArray()
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())));
trx.AddInput(new TxIn(Script.Empty));
trx.AddOutput(Money.COIN + j + i + 1, new Script(Guid.NewGuid().ToByteArray()
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())
.Concat(Guid.NewGuid().ToByteArray())));
block.AddTransaction(trx);
}
block.UpdateMerkleRoot();
block.Header.HashPrevBlock = lst.Any() ? lst.Last().GetHash() : Network.Main.GenesisHash;
lst.Add(block);
}

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
blockRepo.PutAsync(lst, true).GetAwaiter().GetResult();
var first = stopwatch.ElapsedMilliseconds;
blockRepo.PutAsync(lst, true).GetAwaiter().GetResult();
var second = stopwatch.ElapsedMilliseconds;

}
}
}

[Fact]
public void BlockRepositoryPutGetDeleteBlock()
public void BlockRepositoryPutBatch()
{
using (var dir = TestDirectory.Create())
{
using (var blockRepo = new BlockStore.BlockRepository(dir.FolderName))
using (var blockRepo = new BlockStore.BlockRepository(Network.Main, dir.FolderName))
{
var lst = new List<Block>();
for (int i = 0; i < 5; i++)
Expand All @@ -28,22 +79,28 @@ public void BlockRepositoryPutGetDeleteBlock()
var block = new Block();
block.AddTransaction(new Transaction());
block.AddTransaction(new Transaction());
block.Transactions[0].AddInput(new TxIn(Script.Empty));
block.Transactions[0].AddOutput(Money.COIN + i * 2, Script.Empty);
block.Transactions[1].AddInput(new TxIn(Script.Empty));
block.Transactions[1].AddOutput(Money.COIN + i * 2 + 1, Script.Empty);
block.UpdateMerkleRoot();
block.Header.HashPrevBlock = lst.Any() ? lst.Last().GetHash() : Network.Main.GenesisHash;
blockRepo.PutAsync(block).GetAwaiter().GetResult();

// get
var received = blockRepo.GetAsync(block.GetHash()).GetAwaiter().GetResult();
Assert.True(block.ToBytes().SequenceEqual(received.ToBytes()));

lst.Add(block);
}

blockRepo.PutAsync(lst, true).GetAwaiter().GetResult();

// check each block
foreach (var block in lst)
{
var received = blockRepo.GetAsync(block.GetHash()).GetAwaiter().GetResult();
Assert.True(block.ToBytes().SequenceEqual(received.ToBytes()));

foreach (var transaction in block.Transactions)
{
var trx = blockRepo.GetTrxAsync(transaction.GetHash()).GetAwaiter().GetResult();
Assert.True(trx.ToBytes().SequenceEqual(transaction.ToBytes()));
}
}

// delete
Expand All @@ -54,6 +111,21 @@ public void BlockRepositoryPutGetDeleteBlock()
}
}

[Fact]
public void BlockRepositoryBlockHash()
{
using (var dir = TestDirectory.Create())
{
using (var blockRepo = new BlockStore.BlockRepository(Network.Main, dir.FolderName))
{
Assert.Equal(Network.Main.GenesisHash, blockRepo.BlockHash);
var hash = new Block().GetHash();
blockRepo.SethBlockHash(hash).GetAwaiter().GetResult();
Assert.Equal(hash, blockRepo.BlockHash);
}
}
}

[Fact]
public void BlockBroadcastInv()
{
Expand All @@ -63,16 +135,20 @@ public void BlockBroadcastInv()
var stratisNode1 = builder.CreateStratisNode();
var stratisNode2 = builder.CreateStratisNode();
builder.StartAll();
stratisNodeSync.NotInIBD();
stratisNode1.NotInIBD();
stratisNode2.NotInIBD();

// generate blocks and wait for the downloader to pickup
stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
// generate blocks and wait for the downloader to pickup
stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(10); // coinbase maturity = 10
// wait for block repo for block sync to work
Class1.Eventually(() => stratisNodeSync.FullNode.Chain.Tip.HashBlock == stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.CreateRPCClient().GetBestBlockHash()).Result != null);
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestValidatedPoW.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

// sync both nodes
stratisNode1.CreateRPCClient().AddNode(stratisNodeSync.Endpoint, true);
// sync both nodes
stratisNode1.CreateRPCClient().AddNode(stratisNodeSync.Endpoint, true);
stratisNode2.CreateRPCClient().AddNode(stratisNodeSync.Endpoint, true);
Class1.Eventually(() => stratisNode1.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
Class1.Eventually(() => stratisNode2.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
Expand Down
2 changes: 2 additions & 0 deletions Stratis.Bitcoin.Tests/Class1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ public void CanCoreSyncFromStratis()
var tip = coreCreateNode.FindBlock(5).Last();
stratisNode.CreateRPCClient().AddNode(coreCreateNode.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreCreateNode.CreateRPCClient().GetBestBlockHash());
Class1.Eventually(() => stratisNode.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNode.FullNode.Chain.Tip.HashBlock);

var bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);

Expand Down
13 changes: 13 additions & 0 deletions Stratis.Bitcoin.Tests/MemoryPoolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ public void AddToMempool()
stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(105); // coinbase maturity = 100
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

var block = stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(4).HashBlock).Result;
var prevTrx = block.Transactions.First();
Expand All @@ -590,10 +591,12 @@ public void AddToMempoolTrxSpendingTwoOutputFromSameTrx()
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
stratisNodeSync.NotInIBD();

stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(105); // coinbase maturity = 100
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

var block = stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(4).HashBlock).Result;
var prevTrx = block.Transactions.First();
Expand Down Expand Up @@ -631,10 +634,12 @@ public void MempoolReceiveFromManyNodes()
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
stratisNodeSync.NotInIBD();

stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(201); // coinbase maturity = 100
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

var trxs = new List<Transaction>();
foreach (var index in Enumerable.Range(1, 100))
Expand Down Expand Up @@ -667,11 +672,13 @@ public void TxMempoolBlockDoublespend()
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
stratisNodeSync.NotInIBD();
stratisNodeSync.FullNode.Args.RequireStandard = true; // make sure to test standard tx

stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(100); // coinbase maturity = 100
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

// Make sure skipping validation of transctions that were
// validated going into the memory pool does not allow
Expand Down Expand Up @@ -807,10 +814,13 @@ public void MempoolAddNodeWithOrphans()
{
var stratisNodeSync = builder.CreateStratisNode();
builder.StartAll();
stratisNodeSync.NotInIBD();

stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
stratisNodeSync.GenerateStratis(101); // coinbase maturity = 100
Class1.Eventually(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestValidatedPoW.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

var block = stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(1).HashBlock).Result;
var prevTrx = block.Transactions.First();
Expand Down Expand Up @@ -859,6 +869,9 @@ public void MempoolSyncTransactions()
stratisNodeSync.GenerateStratis(105); // coinbase maturity = 100
// wait for block repo for block sync to work
Class1.Eventually(() => stratisNodeSync.FullNode.Chain.Tip.HashBlock == stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestValidatedPoW.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
Class1.Eventually(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

Class1.Eventually(() => stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.CreateRPCClient().GetBestBlockHash()).Result != null);

// sync both nodes
Expand Down
6 changes: 6 additions & 0 deletions Stratis.Bitcoin.Tests/NodeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ public int ProtocolPort
get { return ports[0]; }
}

public void NotInIBD()
{
// not in IBD
this.FullNode.ChainBehaviorState.SetIsInitialBlockDownload(false, DateTime.UtcNow.AddMinutes(5));
}

public void Start()
{
StartAsync().Wait();
Expand Down
26 changes: 25 additions & 1 deletion Stratis.Bitcoin.Tests/UtilTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand Down Expand Up @@ -49,5 +50,28 @@ await await session.DoExclusive(async () =>

Assert.True(IsSequential(collector.ToArray()));
}
}

[Fact]
public void AsyncDictionaryTest()
{
var dic = new AsyncDictionary<int, int>();
var tasks = new ConcurrentBag<Task>();
var task = Task.Run(() =>
{
Parallel.ForEach(Enumerable.Range(0, 1000), index =>
{
tasks.Add(dic.Add(index, Thread.CurrentThread.ManagedThreadId));
tasks.Add(dic.Values);
tasks.Add(dic.Count);
tasks.Add(dic.TryGetValue(index));
});

return Task.WhenAll(tasks);
});

task.Wait();

Assert.Equal(1000, dic.Count.Result);
}
}
}
2 changes: 1 addition & 1 deletion Stratis.Bitcoin.Tests/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"xunit": "2.2.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025",

// xuint hack https://github.com/xunit/xunit/issues/1015
// xunit hack https://github.com/xunit/xunit/issues/1015
"Microsoft.DotNet.InternalAbstractions": "1.0.0"

},
Expand Down
Loading

0 comments on commit 37a6c23

Please sign in to comment.