2
0
mirror of synced 2025-02-02 11:47:18 +00:00

working block time finder

This commit is contained in:
benbierens 2023-12-20 09:48:22 +01:00
parent 4f2539c59f
commit 4b74a9d5fe
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
7 changed files with 143 additions and 45 deletions

View File

@ -1,4 +1,5 @@
using Nethereum.RPC.Eth.DTOs;
using Logging;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Web3;
using Utils;
@ -16,30 +17,48 @@ namespace NethereumWorkflow
public ulong BlockNumber { get; }
public DateTime Utc { get; }
public override string ToString()
{
return $"[{BlockNumber}] @ {Utc.ToString("o")}";
}
}
private const ulong FetchRange = 6;
private const int MaxEntries = 1024;
private readonly Web3 web3;
private readonly ILog log;
private static readonly Dictionary<ulong, BlockTimeEntry> entries = new Dictionary<ulong, BlockTimeEntry>();
public BlockTimeFinder(Web3 web3)
public BlockTimeFinder(Web3 web3, ILog log)
{
this.web3 = web3;
this.log = log;
}
public ulong GetHighestBlockNumberBefore(DateTime moment)
{
log.Log("Looking for highest block before " + moment.ToString("o"));
AssertMomentIsInPast(moment);
Initialize();
var closestBefore = FindClosestBeforeEntry(moment);
var closestAfter = FindClosestAfterEntry(moment);
if (closestBefore == null || closestAfter == null)
{
FetchBlocksAround(moment);
return GetHighestBlockNumberBefore(moment);
}
log.Log("Closest before: " + closestBefore);
log.Log("Closest after: " + closestAfter);
if (closestBefore.Utc < moment &&
closestAfter.Utc > moment &&
closestBefore.BlockNumber + 1 == closestAfter.BlockNumber)
{
log.Log("Found highest-Before: " + closestBefore);
return closestBefore.BlockNumber;
}
@ -49,16 +68,27 @@ namespace NethereumWorkflow
public ulong GetLowestBlockNumberAfter(DateTime moment)
{
log.Log("Looking for lowest block after " + moment.ToString("o"));
AssertMomentIsInPast(moment);
Initialize();
var closestBefore = FindClosestBeforeEntry(moment);
var closestAfter = FindClosestAfterEntry(moment);
if (closestBefore == null || closestAfter == null)
{
FetchBlocksAround(moment);
return GetLowestBlockNumberAfter(moment);
}
log.Log("Closest before: " + closestBefore);
log.Log("Closest after: " + closestAfter);
if (closestBefore.Utc < moment &&
closestAfter.Utc > moment &&
closestBefore.BlockNumber + 1 == closestAfter.BlockNumber)
{
log.Log("Found lowest-after: " + closestAfter);
return closestAfter.BlockNumber;
}
@ -68,6 +98,8 @@ namespace NethereumWorkflow
private void FetchBlocksAround(DateTime moment)
{
log.Log("Fetching...");
var timePerBlock = EstimateTimePerBlock();
EnsureRecentBlockIfNecessary(moment, timePerBlock);
@ -79,11 +111,36 @@ namespace NethereumWorkflow
double numberOfBlocksDifference = secondsDifference / secondsPerBlock;
var blockDifference = Convert.ToUInt64(numberOfBlocksDifference);
if (blockDifference < 1) blockDifference = 1;
var fetchStart = (max - blockDifference) - (FetchRange / 2);
for (ulong i = 0; i < FetchRange; i++)
var fetchUp = FetchRange;
var fetchDown = FetchRange;
var target = max - blockDifference;
log.Log("up - target: " + target);
while (fetchUp > 0)
{
AddBlockNumber(fetchStart + i);
if (!entries.ContainsKey(target))
{
var newBlock = AddBlockNumber(target);
if (newBlock != null) fetchUp--;
else fetchUp = 0;
}
target++;
//if (target >= max) fetchUp = 0;
}
target = max - blockDifference - 1;
log.Log("down - target: " + target);
while (fetchDown > 0)
{
if (!entries.ContainsKey(target))
{
var newBlock = AddBlockNumber(target);
if (newBlock != null) fetchDown--;
else fetchDown = 0;
}
target--;
//if (target <= 0) fetchDown = 0;
}
}
@ -95,7 +152,7 @@ namespace NethereumWorkflow
while (moment > latest.Utc)
{
var newBlock = AddCurrentBlock();
if (newBlock.BlockNumber == latest.BlockNumber)
if (newBlock == null || newBlock.BlockNumber == latest.BlockNumber)
{
maxRetry--;
if (maxRetry == 0) throw new Exception("Unable to fetch recent block after 10x tries.");
@ -104,12 +161,12 @@ namespace NethereumWorkflow
}
}
private BlockTimeEntry AddBlockNumber(decimal blockNumber)
private BlockTimeEntry? AddBlockNumber(decimal blockNumber)
{
return AddBlockNumber(Convert.ToUInt64(blockNumber));
}
private BlockTimeEntry AddBlockNumber(ulong blockNumber)
private BlockTimeEntry? AddBlockNumber(ulong blockNumber)
{
if (entries.ContainsKey(blockNumber))
{
@ -123,7 +180,9 @@ namespace NethereumWorkflow
}
var time = GetTimestampFromBlock(blockNumber);
var entry = new BlockTimeEntry(blockNumber, time);
if (time == null) return null;
var entry = new BlockTimeEntry(blockNumber, time.Value);
log.Log("Found block " + entry.BlockNumber + " at " + entry.Utc.ToString("o"));
entries.Add(blockNumber, entry);
return entry;
}
@ -157,46 +216,49 @@ namespace NethereumWorkflow
if (moment > DateTime.UtcNow) throw new Exception("Moment must be UTC and must be in the past.");
}
private BlockTimeEntry AddCurrentBlock()
private BlockTimeEntry? AddCurrentBlock()
{
var number = Time.Wait(web3.Eth.Blocks.GetBlockNumber.SendRequestAsync());
var blockNumber = number.ToDecimal();
return AddBlockNumber(blockNumber);
}
private DateTime GetTimestampFromBlock(ulong blockNumber)
private DateTime? GetTimestampFromBlock(ulong blockNumber)
{
var block = Time.Wait(web3.Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(new BlockParameter(blockNumber)));
if (block == null) return null;
return DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(block.Timestamp.ToDecimal())).UtcDateTime;
}
private BlockTimeEntry FindClosestBeforeEntry(DateTime moment)
private BlockTimeEntry? FindClosestBeforeEntry(DateTime moment)
{
var result = entries.Values.First();
var highestTime = result.Utc;
BlockTimeEntry? result = null;
foreach (var entry in entries.Values)
{
if (entry.Utc > highestTime && entry.Utc < moment)
if (result == null)
{
highestTime = entry.Utc;
result = entry;
if (entry.Utc < moment) result = entry;
}
else
{
if (entry.Utc > result.Utc && entry.Utc < moment) result = entry;
}
}
return result;
}
private BlockTimeEntry FindClosestAfterEntry(DateTime moment)
private BlockTimeEntry? FindClosestAfterEntry(DateTime moment)
{
var result = entries.Values.First();
var lowestTime = result.Utc;
BlockTimeEntry? result = null;
foreach (var entry in entries.Values)
{
if (entry.Utc < lowestTime && entry.Utc > moment)
if (result == null)
{
lowestTime = entry.Utc;
result = entry;
if (entry.Utc > moment) result = entry;
}
else
{
if (entry.Utc < result.Utc && entry.Utc > moment) result = entry;
}
}
return result;

View File

@ -79,14 +79,12 @@ namespace NethereumWorkflow
}
}
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, DateTime from, DateTime to) where TEvent : IEventDTO, new()
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new()
{
if (from >= to) throw new Exception("Time range is invalid.");
var blockTimeFinder = new BlockTimeFinder(web3, log);
var blockTimeFinder = new BlockTimeFinder(web3);
var fromBlock = blockTimeFinder.GetLowestBlockNumberAfter(from);
var toBlock = blockTimeFinder.GetHighestBlockNumberBefore(to);
var fromBlock = blockTimeFinder.GetLowestBlockNumberAfter(timeRange.From);
var toBlock = blockTimeFinder.GetHighestBlockNumberBefore(timeRange.To);
return GetEvents<TEvent>(address, fromBlock, toBlock);
}

View File

@ -0,0 +1,24 @@
namespace Utils
{
public class TimeRange
{
public TimeRange(DateTime from, DateTime to)
{
if (from < to)
{
From = from;
To = to;
}
else
{
From = to;
To = from;
}
Duration = To - From;
}
public DateTime From { get; }
public DateTime To { get; }
public TimeSpan Duration { get; }
}
}

View File

@ -1,5 +1,6 @@
using GethPlugin;
using Logging;
using Utils;
namespace CodexContractsPlugin
{
@ -12,6 +13,8 @@ namespace CodexContractsPlugin
string MintTestTokens(EthAddress ethAddress, TestToken testTokens);
TestToken GetTestTokenBalance(IHasEthAddress owner);
TestToken GetTestTokenBalance(EthAddress ethAddress);
void GetStorageRequests(TimeRange range);
}
public class CodexContractsAccess : ICodexContracts
@ -30,8 +33,7 @@ namespace CodexContractsPlugin
public bool IsDeployed()
{
var interaction = new ContractInteractions(log, gethNode);
return !string.IsNullOrEmpty(interaction.GetTokenName(Deployment.TokenAddress));
return !string.IsNullOrEmpty(StartInteraction().GetTokenName(Deployment.TokenAddress));
}
public string MintTestTokens(IHasEthAddress owner, TestToken testTokens)
@ -41,8 +43,7 @@ namespace CodexContractsPlugin
public string MintTestTokens(EthAddress ethAddress, TestToken testTokens)
{
var interaction = new ContractInteractions(log, gethNode);
return interaction.MintTestTokens(ethAddress, testTokens.Amount, Deployment.TokenAddress);
return StartInteraction().MintTestTokens(ethAddress, testTokens.Amount, Deployment.TokenAddress);
}
public TestToken GetTestTokenBalance(IHasEthAddress owner)
@ -52,9 +53,19 @@ namespace CodexContractsPlugin
public TestToken GetTestTokenBalance(EthAddress ethAddress)
{
var interaction = new ContractInteractions(log, gethNode);
var balance = interaction.GetBalance(Deployment.TokenAddress, ethAddress.Address);
var balance = StartInteraction().GetBalance(Deployment.TokenAddress, ethAddress.Address);
return balance.TestTokens();
}
public void GetStorageRequests(TimeRange timeRange)
{
var events = gethNode.GetEvents<Marketplace.StorageRequestedEventDTO>(Deployment.MarketplaceAddress, timeRange);
var iii = 0;
}
private ContractInteractions StartInteraction()
{
return new ContractInteractions(log, gethNode);
}
}
}

View File

@ -4,6 +4,7 @@ using Logging;
using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts;
using NethereumWorkflow;
using Utils;
namespace GethPlugin
{
@ -22,7 +23,7 @@ namespace GethPlugin
bool IsContractAvailable(string abi, string contractAddress);
GethBootstrapNode GetBootstrapRecord();
List<EventLog<TEvent>> GetEvents<TEvent>(string address, ulong fromBlockNumber, ulong toBlockNumber) where TEvent : IEventDTO, new();
List<EventLog<TEvent>> GetEvents<TEvent>(string address, DateTime from, DateTime to) where TEvent : IEventDTO, new();
List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new();
}
public class DeploymentGethNode : BaseGethNode, IGethNode
@ -141,9 +142,9 @@ namespace GethPlugin
return StartInteraction().GetEvents<TEvent>(address, fromBlockNumber, toBlockNumber);
}
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, DateTime from, DateTime to) where TEvent : IEventDTO, new()
public List<EventLog<TEvent>> GetEvents<TEvent>(string address, TimeRange timeRange) where TEvent : IEventDTO, new()
{
return StartInteraction().GetEvents<TEvent>(address, from, to);
return StartInteraction().GetEvents<TEvent>(address, timeRange);
}
protected abstract NethereumInteraction StartInteraction();

View File

@ -95,7 +95,9 @@ namespace CodexTests.BasicTests
AssertBalance(contracts, seller, Is.GreaterThan(sellerInitialBalance), "Seller was not paid for storage.");
AssertBalance(contracts, buyer, Is.LessThan(buyerInitialBalance), "Buyer was not charged for storage.");
CheckLogForErrors(seller, buyer);
//CheckLogForErrors(seller, buyer);
contracts.GetStorageRequests(new TimeRange(Get().TestStart, DateTime.UtcNow));
}
[Test]

View File

@ -11,7 +11,6 @@ namespace DistTestCore
public class TestLifecycle : IK8sHooks
{
private const string TestsType = "dist-tests";
private readonly DateTime testStart;
private readonly EntryPoint entryPoint;
private readonly Dictionary<string, string> metadata;
private readonly List<RunningContainers> runningContainers = new List<RunningContainers>();
@ -21,7 +20,7 @@ namespace DistTestCore
Log = log;
Configuration = configuration;
TimeSet = timeSet;
testStart = DateTime.UtcNow;
TestStart = DateTime.UtcNow;
entryPoint = new EntryPoint(log, configuration.GetK8sConfiguration(timeSet, this, testNamespace), configuration.GetFileManagerFolder(), timeSet);
metadata = entryPoint.GetPluginMetadata();
@ -30,6 +29,7 @@ namespace DistTestCore
log.WriteLogTag();
}
public DateTime TestStart { get; }
public TestLog Log { get; }
public Configuration Configuration { get; }
public ITimeSet TimeSet { get; }
@ -60,7 +60,7 @@ namespace DistTestCore
public TimeSpan GetTestDuration()
{
return DateTime.UtcNow - testStart;
return DateTime.UtcNow - TestStart;
}
public void OnContainersStarted(RunningContainers rc)