Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public CoinviewTests()
this.nodeStats = new NodeStats(this.dateTimeProvider, NodeSettings.Default(this.network), new Mock<IVersionProvider>().Object);

this.coindb = new DBreezeCoindb(this.network, this.dataFolder, this.dateTimeProvider, this.loggerFactory, this.nodeStats, new DBreezeSerializer(this.network.Consensus.ConsensusFactory));
this.coindb.Initialize(new ChainedHeader(this.network.GetGenesis().Header, this.network.GenesisHash, 0));
this.coindb.Initialize();

this.chainIndexer = new ChainIndexer(this.network);
this.stakeChainStore = new StakeChainStore(this.network, this.chainIndexer, (IStakedb)this.coindb, this.loggerFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void Sync(ChainIndexer chainIndexer)

public void Initialize(ChainedHeader chainTip, ChainIndexer chainIndexer, IConsensusRuleEngine consensusRuleEngine)
{
this.coindb.Initialize(chainTip);
this.coindb.Initialize();

Sync(chainIndexer);

Expand Down
64 changes: 28 additions & 36 deletions src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/Coindb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Stratis.Bitcoin.Features.Consensus.CoinViews

private BackendPerformanceSnapshot latestPerformanceSnapShot;

/// <summary>Access to dBreeze database.</summary>
/// <summary>Access to database.</summary>
private IDb coinDb;

private readonly DBreezeSerializer dBreezeSerializer;
Expand Down Expand Up @@ -70,12 +70,32 @@ public Coindb(Network network, string dataFolder, IDateTimeProvider dateTimeProv
nodeStats.RegisterStats(this.AddBenchStats, StatsType.Benchmark, this.GetType().Name, 400);
}

public void Initialize(ChainedHeader chainTip)
public void Initialize()
{
// Open a connection to a new DB and create if not found
this.coinDb = new T();
this.coinDb.Open(this.dataFolder);

EndiannessFix();

EnsureCoinDatabaseIntegrity();

Block genesis = this.network.GetGenesis();

if (this.GetTipHash() == null)
{
using (var batch = this.coinDb.GetWriteBatch())
{
this.SetBlockHash(batch, new HashHeightPair(genesis.GetHash(), 0));
batch.Write();
}
}

this.logger.LogInformation("Coin database initialized with tip '{0}'.", this.persistedCoinviewTip);
}

private void EndiannessFix()
{
// Check if key bytes are in the wrong endian order.
HashHeightPair current = this.GetTipHash();

Expand Down Expand Up @@ -129,46 +149,18 @@ public void Initialize(ChainedHeader chainTip)
}
}
}

EnsureCoinDatabaseIntegrity(chainTip);

Block genesis = this.network.GetGenesis();

if (this.GetTipHash() == null)
{
using (var batch = this.coinDb.GetWriteBatch())
{
this.SetBlockHash(batch, new HashHeightPair(genesis.GetHash(), 0));
batch.Write();
}
}

this.logger.LogInformation("Coinview initialized with tip '{0}'.", this.persistedCoinviewTip);
}

private void EnsureCoinDatabaseIntegrity(ChainedHeader chainTip)
/// <summary>Just check the integrity. Coin view performs the sync with the chain tip.</summary>
private void EnsureCoinDatabaseIntegrity()
{
this.logger.LogInformation("Checking coin database integrity...");

var heightToCheck = chainTip.Height;

// Find the height up to where rewind data is stored above chain tip.
do
{
heightToCheck += 1;

byte[] row = this.coinDb.Get(rewindTable, BitConverter.GetBytes(heightToCheck).Reverse().ToArray());
if (row == null)
break;

} while (true);

for (int height = heightToCheck - 1; height > chainTip.Height;)
if (this.GetTipHash() == null)
{
this.logger.LogInformation($"Fixing coin database, deleting rewind data at height {height} above tip '{chainTip}'.");

// Do a batch of rewinding.
height = RewindInternal(height, new HashHeightPair(chainTip)).Height;
this.logger.LogInformation($"Rebuilding coin database that has no tip information.");
this.coinDb.Clear();
return;
}

this.logger.LogInformation("Coin database integrity good.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public DBreezeCoindb(Network network, string folder, IDateTimeProvider dateTimeP
nodeStats.RegisterStats(this.AddBenchStats, StatsType.Benchmark, this.GetType().Name, 300);
}

public void Initialize(ChainedHeader chainTip)
public void Initialize()
{
Block genesis = this.network.GetGenesis();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ namespace Stratis.Bitcoin.Features.Consensus.CoinViews
public interface ICoindb
{
/// <summary> Initialize the coin database.</summary>
/// <param name="chainTip">The current chain's tip.</param>
void Initialize(ChainedHeader chainTip);
void Initialize();

/// <summary>
/// Retrieves the block hash of the current tip of the coinview.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public RewindData GetRewindData(int height)
throw new NotImplementedException();
}

public void Initialize(ChainedHeader chainTip = null)
public void Initialize()
{
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Stratis.Bitcoin.IntegrationTests/CoinViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void TestDBreezeSerialization()
chained = this.MakeNext(this.MakeNext(genesisChainedHeader, ctx.Network), ctx.Network);
ctx.Coindb.SaveChanges(new List<UnspentOutput>(), new HashHeightPair(previous), new HashHeightPair(chained));
Assert.Equal(chained.HashBlock, ctx.Coindb.GetTipHash().Hash);
ctx.ReloadPersistentCoinView(chained);
ctx.ReloadPersistentCoinView();
Assert.Equal(chained.HashBlock, ctx.Coindb.GetTipHash().Hash);
Assert.NotNull(ctx.Coindb.FetchCoins(new[] { new OutPoint(genesis.Transactions[0], 0) }).UnspentOutputs.Values.FirstOrDefault().Coins);
Assert.Null(ctx.Coindb.FetchCoins(new[] { new OutPoint() }).UnspentOutputs.Values.FirstOrDefault().Coins);
Expand Down
6 changes: 3 additions & 3 deletions src/Stratis.Bitcoin.IntegrationTests/NodeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public NodeContext(object caller, string name, Network network)
var dateTimeProvider = new DateTimeProvider();
var serializer = new DBreezeSerializer(this.Network.Consensus.ConsensusFactory);
this.Coindb = new Coindb<LevelDb>(network, this.FolderName, dateTimeProvider, new NodeStats(dateTimeProvider, NodeSettings.Default(network), new Mock<IVersionProvider>().Object), serializer);
this.Coindb.Initialize(new ChainedHeader(network.GetGenesis().Header, network.GenesisHash, 0));
this.Coindb.Initialize();
this.cleanList = new List<IDisposable> { (IDisposable)this.Coindb };
}

Expand Down Expand Up @@ -60,15 +60,15 @@ public void Dispose()
item.Dispose();
}

public void ReloadPersistentCoinView(ChainedHeader chainTip)
public void ReloadPersistentCoinView()
{
((IDisposable)this.Coindb).Dispose();
this.cleanList.Remove((IDisposable)this.Coindb);
var dateTimeProvider = new DateTimeProvider();
var serializer = new DBreezeSerializer(this.Network.Consensus.ConsensusFactory);
this.Coindb = new Coindb<LevelDb>(this.Network, this.FolderName, dateTimeProvider, new NodeStats(dateTimeProvider, NodeSettings.Default(this.Network), new Mock<IVersionProvider>().Object), serializer);

this.Coindb.Initialize(chainTip);
this.Coindb.Initialize();
this.cleanList.Add((IDisposable)this.Coindb);
}
}
Expand Down