public ChainState(Chain chain, IStorageManager storageManager)
{
CursorCount = Environment.ProcessorCount;
Chain = chain;
// create a cache of cursors that are in an open snapshot transaction with the current chain state
var success = false;
this.cursorCache = new DisposableCache<DisposeHandle<IChainStateCursor>>(CursorCount);
try
{
for (var i = 0; i < this.cursorCache.Capacity; i++)
{
// open the cursor
var handle = storageManager.OpenChainStateCursor();
var cursor = handle.Item;
// cache the cursor
// this must be done before beginning the transaction as caching will rollback any transactions
this.cursorCache.CacheItem(handle);
// begin transaction to take the snapshot
cursor.BeginTransaction(readOnly: true);
// verify the chain state matches the expected chain
var chainTip = cursor.ChainTip;
if (chainTip?.Hash != chain.LastBlock?.Hash)
throw new ChainStateOutOfSyncException(chain.LastBlock, chainTip);
}
success = true;
}
finally
{
// ensure any opened cursors are cleaned up on an error
if (!success)
this.cursorCache.Dispose();
}
}