107 lines
3.0 KiB
C#
107 lines
3.0 KiB
C#
|
namespace NethereumWorkflow.BlockUtils
|
|||
|
{
|
|||
|
public class BlockchainBounds
|
|||
|
{
|
|||
|
private readonly BlockCache cache;
|
|||
|
private readonly IWeb3Blocks web3;
|
|||
|
|
|||
|
public BlockTimeEntry Genesis { get; private set; } = null!;
|
|||
|
public BlockTimeEntry Current { get; private set; } = null!;
|
|||
|
|
|||
|
public BlockchainBounds(BlockCache cache, IWeb3Blocks web3)
|
|||
|
{
|
|||
|
this.cache = cache;
|
|||
|
this.web3 = web3;
|
|||
|
|
|||
|
cache.OnCacheCleared += Initialize;
|
|||
|
}
|
|||
|
|
|||
|
public void Initialize()
|
|||
|
{
|
|||
|
AddCurrentBlock();
|
|||
|
LookForGenesisBlock();
|
|||
|
|
|||
|
if (Current.BlockNumber == Genesis.BlockNumber)
|
|||
|
{
|
|||
|
throw new Exception("Unsupported condition: Current block is genesis block.");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void LookForGenesisBlock()
|
|||
|
{
|
|||
|
if (Genesis != null)
|
|||
|
{
|
|||
|
cache.Add(Genesis);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var blockTime = web3.GetTimestampForBlock(0);
|
|||
|
if (blockTime != null)
|
|||
|
{
|
|||
|
AddGenesisBlock(0, blockTime.Value);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
LookForGenesisBlock(0, Current);
|
|||
|
}
|
|||
|
|
|||
|
private void LookForGenesisBlock(ulong lower, BlockTimeEntry upper)
|
|||
|
{
|
|||
|
if (Genesis != null) return;
|
|||
|
|
|||
|
var range = upper.BlockNumber - lower;
|
|||
|
if (range == 1)
|
|||
|
{
|
|||
|
var lowTime = web3.GetTimestampForBlock(lower);
|
|||
|
if (lowTime != null)
|
|||
|
{
|
|||
|
AddGenesisBlock(lower, lowTime.Value);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
AddGenesisBlock(upper);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var current = lower + range / 2;
|
|||
|
|
|||
|
var blockTime = web3.GetTimestampForBlock(current);
|
|||
|
if (blockTime != null)
|
|||
|
{
|
|||
|
var newUpper = cache.Add(current, blockTime.Value);
|
|||
|
LookForGenesisBlock(lower, newUpper);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
LookForGenesisBlock(current, upper);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void AddCurrentBlock()
|
|||
|
{
|
|||
|
var currentBlockNumber = web3.GetCurrentBlockNumber();
|
|||
|
var blockTime = web3.GetTimestampForBlock(currentBlockNumber);
|
|||
|
if (blockTime == null) throw new Exception("Unable to get dateTime for current block.");
|
|||
|
AddCurrentBlock(currentBlockNumber, blockTime.Value);
|
|||
|
}
|
|||
|
|
|||
|
private void AddCurrentBlock(ulong currentBlockNumber, DateTime dateTime)
|
|||
|
{
|
|||
|
Current = new BlockTimeEntry(currentBlockNumber, dateTime);
|
|||
|
cache.Add(Current);
|
|||
|
}
|
|||
|
|
|||
|
private void AddGenesisBlock(ulong number, DateTime dateTime)
|
|||
|
{
|
|||
|
AddGenesisBlock(new BlockTimeEntry(number, dateTime));
|
|||
|
}
|
|||
|
|
|||
|
private void AddGenesisBlock(BlockTimeEntry entry)
|
|||
|
{
|
|||
|
Genesis = entry;
|
|||
|
cache.Add(Genesis);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|