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

Commit

Permalink
Merge pull request #162 from stratisproject/light-wallet-reorg
Browse files Browse the repository at this point in the history
Light wallet reorg
  • Loading branch information
bokobza authored Jun 15, 2017
2 parents 4dd674d + 845b6f4 commit 7e8a242
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 388 deletions.
36 changes: 18 additions & 18 deletions Stratis.Bitcoin.IntegrationTests/BlockStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,28 +147,28 @@ public void BlockBroadcastInv()
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.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);
TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestValidatedPoW.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

// 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());
TestHelper.WaitLoop(() => stratisNode1.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode2.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());

// set node2 to use inv (not headers)
stratisNode2.FullNode.ConnectionManager.ConnectedNodes.First().Behavior<BlockStoreBehavior>().PreferHeaders = false;

// generate two new blocks
stratisNodeSync.GenerateStratis(2);
// 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);
TestHelper.WaitLoop(() => stratisNodeSync.FullNode.Chain.Tip.HashBlock == stratisNodeSync.FullNode.ConsensusLoop.Tip.HashBlock);
TestHelper.WaitLoop(() => stratisNodeSync.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNodeSync.CreateRPCClient().GetBestBlockHash()).Result != null);

// wait for the other nodes to pick up the newly generated blocks
Class1.Eventually(() => stratisNode1.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
Class1.Eventually(() => stratisNode2.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode1.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode2.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
}
}

Expand All @@ -193,10 +193,10 @@ public void BlockStoreCanReorg()
stratisNodeSync.CreateRPCClient().AddNode(stratisNode2.Endpoint, true);

stratisNode1.GenerateStratis(10);
Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 10);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 10);

Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
Class1.Eventually(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
TestHelper.WaitLoop(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);

// remove node 2
stratisNodeSync.CreateRPCClient().RemoveNode(stratisNode2.Endpoint);
Expand All @@ -205,21 +205,21 @@ public void BlockStoreCanReorg()
stratisNode1.GenerateStratis(10);

// wait for node 1 to sync
Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 20);
Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 20);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);

// remove node 1
stratisNodeSync.CreateRPCClient().RemoveNode(stratisNode1.Endpoint);

// mine a higher chain with node2
stratisNode2.GenerateStratis(20);
Class1.Eventually(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 30);
TestHelper.WaitLoop(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 30);

// add node2
stratisNodeSync.CreateRPCClient().AddNode(stratisNode2.Endpoint, true);

// node2 should be synced
Class1.Eventually(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
TestHelper.WaitLoop(() => stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNodeSync.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
}
}

Expand All @@ -240,8 +240,8 @@ public void BlockStoreIndexTx()
// sync both nodes
stratisNode1.CreateRPCClient().AddNode(stratisNode2.Endpoint, true);
stratisNode1.GenerateStratis(10);
Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 10);
Class1.Eventually(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.Height == 10);
TestHelper.WaitLoop(() => stratisNode1.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock == stratisNode2.FullNode.ChainBehaviorState.HighestPersistedBlock.HashBlock);

var bestBlock1 = stratisNode1.FullNode.BlockStoreManager.BlockRepository.GetAsync(stratisNode1.FullNode.Chain.Tip.HashBlock).Result;
Assert.NotNull(bestBlock1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

namespace Stratis.Bitcoin.IntegrationTests
{
public class Class1
public class CoinViewTests
{
[Fact]
public void TestDBreezeSerialization()
Expand Down Expand Up @@ -164,35 +164,6 @@ public void CanRewind()
}
}




[Fact]
public void NodesCanConnectToEachOthers()
{
using(NodeBuilder builder = NodeBuilder.Create())
{
var node1 = builder.CreateStratisNode();
var node2 = builder.CreateStratisNode();
builder.StartAll();
Assert.Equal(0, node1.FullNode.ConnectionManager.ConnectedNodes.Count());
Assert.Equal(0, node2.FullNode.ConnectionManager.ConnectedNodes.Count());
var rpc1 = node1.CreateRPCClient();
var rpc2 = node2.CreateRPCClient();
rpc1.AddNode(node2.Endpoint, true);
Assert.Equal(1, node1.FullNode.ConnectionManager.ConnectedNodes.Count());
Assert.Equal(1, node2.FullNode.ConnectionManager.ConnectedNodes.Count());

var behavior = node1.FullNode.ConnectionManager.ConnectedNodes.First().Behaviors.Find<ConnectionManagerBehavior>();
Assert.False(behavior.Inbound);
Assert.True(behavior.OneTry);
behavior = node2.FullNode.ConnectionManager.ConnectedNodes.First().Behaviors.Find<ConnectionManagerBehavior>();
Assert.True(behavior.Inbound);
Assert.False(behavior.OneTry);
}
}


[Fact]
public void CanHandleReorgs()
{
Expand All @@ -206,184 +177,32 @@ public void CanHandleReorgs()
//Core1 discovers 10 blocks, sends to stratis
var tip = coreNode1.FindBlock(10).Last();
stratisNode.CreateRPCClient().AddNode(coreNode1.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
stratisNode.CreateRPCClient().RemoveNode(coreNode1.Endpoint);

//Core2 discovers 20 blocks, sends to stratis
tip = coreNode2.FindBlock(20).Last();
stratisNode.CreateRPCClient().AddNode(coreNode2.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
stratisNode.CreateRPCClient().RemoveNode(coreNode2.Endpoint);
((CachedCoinView)stratisNode.FullNode.CoinView).FlushAsync().Wait();

//Core1 discovers 30 blocks, sends to stratis
tip = coreNode1.FindBlock(30).Last();
stratisNode.CreateRPCClient().AddNode(coreNode1.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
stratisNode.CreateRPCClient().RemoveNode(coreNode1.Endpoint);

//Core2 discovers 50 blocks, sends to stratis
tip = coreNode2.FindBlock(50).Last();
stratisNode.CreateRPCClient().AddNode(coreNode2.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
stratisNode.CreateRPCClient().RemoveNode(coreNode2.Endpoint);
((CachedCoinView)stratisNode.FullNode.CoinView).FlushAsync().Wait();
}
}

[Fact]
public void CanStratisSyncFromCore()
{
using(NodeBuilder builder = NodeBuilder.Create())
{
var stratisNode = builder.CreateStratisNode();
var coreNode = builder.CreateNode();
builder.StartAll();

// not in IBD
stratisNode.FullNode.ChainBehaviorState.SetIsInitialBlockDownload(false, DateTime.UtcNow.AddMinutes(5));

var tip = coreNode.FindBlock(10).Last();
stratisNode.CreateRPCClient().AddNode(coreNode.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode.CreateRPCClient().GetBestBlockHash());
var bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);

//Now check if Core connect to stratis
stratisNode.CreateRPCClient().RemoveNode(coreNode.Endpoint);
tip = coreNode.FindBlock(10).Last();
coreNode.CreateRPCClient().AddNode(stratisNode.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode.CreateRPCClient().GetBestBlockHash());
bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);


//For Core synching from Stratis, need to save blocks in stratis
}
}

[Fact]
public void CanStratisSyncFromStratis()
{
using (NodeBuilder builder = NodeBuilder.Create())
{
var stratisNode = builder.CreateStratisNode();
var stratisNodeSync = builder.CreateStratisNode();
var coreCreateNode = builder.CreateNode();
builder.StartAll();

// not in IBD
stratisNode.FullNode.ChainBehaviorState.SetIsInitialBlockDownload(false, DateTime.UtcNow.AddMinutes(5));
stratisNodeSync.FullNode.ChainBehaviorState.SetIsInitialBlockDownload(false, DateTime.UtcNow.AddMinutes(5));

// first seed a core node with blocks and sync them to a stratis node
// and wait till the stratis node is fully synced
var tip = coreCreateNode.FindBlock(5).Last();
stratisNode.CreateRPCClient().AddNode(coreCreateNode.Endpoint, true);
Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreCreateNode.CreateRPCClient().GetBestBlockHash());
var bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);

// add a new stratis node which will download
// the blocks using the GetData payload
stratisNodeSync.CreateRPCClient().AddNode(stratisNode.Endpoint, true);

// wait for download and assert
Class1.Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
bestBlockHash = stratisNodeSync.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);

}
}

[Fact]
public void CanCoreSyncFromStratis()
{
using (NodeBuilder builder = NodeBuilder.Create())
{
var stratisNode = builder.CreateStratisNode();
var coreNodeSync = builder.CreateNode();
var coreCreateNode = builder.CreateNode();
builder.StartAll();

// not in IBD
stratisNode.FullNode.ChainBehaviorState.SetIsInitialBlockDownload(false, DateTime.UtcNow.AddMinutes(5));

// first seed a core node with blocks and sync them to a stratis node
// and wait till the stratis node is fully synced
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);

// add a new stratis node which will download
// the blocks using the GetData payload
coreNodeSync.CreateRPCClient().AddNode(stratisNode.Endpoint, true);

// wait for download and assert
Class1.Eventually(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNodeSync.CreateRPCClient().GetBestBlockHash());
bestBlockHash = coreNodeSync.CreateRPCClient().GetBestBlockHash();
Assert.Equal(tip.GetHash(), bestBlockHash);
TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
}
}

public static void Eventually(Func<bool> act)
{
var cancel = new CancellationTokenSource(Debugger.IsAttached ? 15 * 60 * 1000 : 30 * 1000);
while(!act())
{
cancel.Token.ThrowIfCancellationRequested();
Thread.Sleep(50);
}
}

[Fact]
public void CheckRPCFailures()
{
using(NodeBuilder builder = NodeBuilder.Create())
{
var node = builder.CreateStratisNode();
builder.StartAll();
var client = node.CreateRPCClient();
var hash = client.GetBestBlockHash();
try
{
client.SendCommand("lol");
Assert.True(false, "should throw");
}
catch(RPCException ex)
{
Assert.Equal(RPCErrorCode.RPC_METHOD_NOT_FOUND, ex.RPCCode);
}
Assert.Equal(hash, Network.RegTest.GetGenesis().GetHash());
var oldClient = client;
client = new NBitcoin.RPC.RPCClient("abc:def", client.Address, client.Network);
try
{
client.GetBestBlockHash();
Assert.True(false, "should throw");
}
catch(Exception ex)
{
Assert.True(ex.Message.Contains("401"));
}
client = oldClient;

try
{
client.SendCommand("addnode", "regreg", "addr");
Assert.True(false, "should throw");
}
catch(RPCException ex)
{
Assert.Equal(RPCErrorCode.RPC_MISC_ERROR, ex.RPCCode);
}

}
}
}

[Fact]
public void TestDBreezeInsertOrder()
Expand Down
Loading

0 comments on commit 7e8a242

Please sign in to comment.