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 Nethereum.Web3;
using Utils; using Utils;
@ -16,30 +17,48 @@ namespace NethereumWorkflow
public ulong BlockNumber { get; } public ulong BlockNumber { get; }
public DateTime Utc { get; } public DateTime Utc { get; }
public override string ToString()
{
return $"[{BlockNumber}] @ {Utc.ToString("o")}";
}
} }
private const ulong FetchRange = 6; private const ulong FetchRange = 6;
private const int MaxEntries = 1024; private const int MaxEntries = 1024;
private readonly Web3 web3; private readonly Web3 web3;
private readonly ILog log;
private static readonly Dictionary<ulong, BlockTimeEntry> entries = new Dictionary<ulong, BlockTimeEntry>(); 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.web3 = web3;
this.log = log;
} }
public ulong GetHighestBlockNumberBefore(DateTime moment) public ulong GetHighestBlockNumberBefore(DateTime moment)
{ {
log.Log("Looking for highest block before " + moment.ToString("o"));
AssertMomentIsInPast(moment); AssertMomentIsInPast(moment);
Initialize(); Initialize();
var closestBefore = FindClosestBeforeEntry(moment); var closestBefore = FindClosestBeforeEntry(moment);
var closestAfter = FindClosestAfterEntry(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 && if (closestBefore.Utc < moment &&
closestAfter.Utc > moment && closestAfter.Utc > moment &&
closestBefore.BlockNumber + 1 == closestAfter.BlockNumber) closestBefore.BlockNumber + 1 == closestAfter.BlockNumber)
{ {
log.Log("Found highest-Before: " + closestBefore);
return closestBefore.BlockNumber; return closestBefore.BlockNumber;
} }
@ -49,16 +68,27 @@ namespace NethereumWorkflow
public ulong GetLowestBlockNumberAfter(DateTime moment) public ulong GetLowestBlockNumberAfter(DateTime moment)
{ {
log.Log("Looking for lowest block after " + moment.ToString("o"));
AssertMomentIsInPast(moment); AssertMomentIsInPast(moment);
Initialize(); Initialize();
var closestBefore = FindClosestBeforeEntry(moment); var closestBefore = FindClosestBeforeEntry(moment);
var closestAfter = FindClosestAfterEntry(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 && if (closestBefore.Utc < moment &&
closestAfter.Utc > moment && closestAfter.Utc > moment &&
closestBefore.BlockNumber + 1 == closestAfter.BlockNumber) closestBefore.BlockNumber + 1 == closestAfter.BlockNumber)
{ {
log.Log("Found lowest-after: " + closestAfter);
return closestAfter.BlockNumber; return closestAfter.BlockNumber;
} }
@ -68,6 +98,8 @@ namespace NethereumWorkflow
private void FetchBlocksAround(DateTime moment) private void FetchBlocksAround(DateTime moment)
{ {
log.Log("Fetching...");
var timePerBlock = EstimateTimePerBlock(); var timePerBlock = EstimateTimePerBlock();
EnsureRecentBlockIfNecessary(moment, timePerBlock); EnsureRecentBlockIfNecessary(moment, timePerBlock);
@ -79,11 +111,36 @@ namespace NethereumWorkflow
double numberOfBlocksDifference = secondsDifference / secondsPerBlock; double numberOfBlocksDifference = secondsDifference / secondsPerBlock;
var blockDifference = Convert.ToUInt64(numberOfBlocksDifference); var blockDifference = Convert.ToUInt64(numberOfBlocksDifference);
if (blockDifference < 1) blockDifference = 1;
var fetchStart = (max - blockDifference) - (FetchRange / 2); var fetchUp = FetchRange;
for (ulong i = 0; i < FetchRange; i++) 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) while (moment > latest.Utc)
{ {
var newBlock = AddCurrentBlock(); var newBlock = AddCurrentBlock();
if (newBlock.BlockNumber == latest.BlockNumber) if (newBlock == null || newBlock.BlockNumber == latest.BlockNumber)
{ {
maxRetry--; maxRetry--;
if (maxRetry == 0) throw new Exception("Unable to fetch recent block after 10x tries."); 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)); return AddBlockNumber(Convert.ToUInt64(blockNumber));
} }
private BlockTimeEntry AddBlockNumber(ulong blockNumber) private BlockTimeEntry? AddBlockNumber(ulong blockNumber)
{ {
if (entries.ContainsKey(blockNumber)) if (entries.ContainsKey(blockNumber))
{ {
@ -123,7 +180,9 @@ namespace NethereumWorkflow
} }
var time = GetTimestampFromBlock(blockNumber); 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); entries.Add(blockNumber, entry);
return 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."); 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 number = Time.Wait(web3.Eth.Blocks.GetBlockNumber.SendRequestAsync());
var blockNumber = number.ToDecimal(); var blockNumber = number.ToDecimal();
return AddBlockNumber(blockNumber); 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))); 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; return DateTimeOffset.FromUnixTimeSeconds(Convert.ToInt64(block.Timestamp.ToDecimal())).UtcDateTime;
} }
private BlockTimeEntry FindClosestBeforeEntry(DateTime moment) private BlockTimeEntry? FindClosestBeforeEntry(DateTime moment)
{ {
var result = entries.Values.First(); BlockTimeEntry? result = null;
var highestTime = result.Utc;
foreach (var entry in entries.Values) foreach (var entry in entries.Values)
{ {
if (entry.Utc > highestTime && entry.Utc < moment) if (result == null)
{ {
highestTime = entry.Utc; if (entry.Utc < moment) result = entry;
result = entry; }
else
{
if (entry.Utc > result.Utc && entry.Utc < moment) result = entry;
} }
} }
return result; return result;
} }
private BlockTimeEntry FindClosestAfterEntry(DateTime moment) private BlockTimeEntry? FindClosestAfterEntry(DateTime moment)
{ {
var result = entries.Values.First(); BlockTimeEntry? result = null;
var lowestTime = result.Utc;
foreach (var entry in entries.Values) foreach (var entry in entries.Values)
{ {
if (entry.Utc < lowestTime && entry.Utc > moment) if (result == null)
{ {
lowestTime = entry.Utc; if (entry.Utc > moment) result = entry;
result = entry; }
else
{
if (entry.Utc < result.Utc && entry.Utc > moment) result = entry;
} }
} }
return result; 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(timeRange.From);
var toBlock = blockTimeFinder.GetHighestBlockNumberBefore(timeRange.To);
var fromBlock = blockTimeFinder.GetLowestBlockNumberAfter(from);
var toBlock = blockTimeFinder.GetHighestBlockNumberBefore(to);
return GetEvents<TEvent>(address, fromBlock, toBlock); 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 GethPlugin;
using Logging; using Logging;
using Utils;
namespace CodexContractsPlugin namespace CodexContractsPlugin
{ {
@ -12,6 +13,8 @@ namespace CodexContractsPlugin
string MintTestTokens(EthAddress ethAddress, TestToken testTokens); string MintTestTokens(EthAddress ethAddress, TestToken testTokens);
TestToken GetTestTokenBalance(IHasEthAddress owner); TestToken GetTestTokenBalance(IHasEthAddress owner);
TestToken GetTestTokenBalance(EthAddress ethAddress); TestToken GetTestTokenBalance(EthAddress ethAddress);
void GetStorageRequests(TimeRange range);
} }
public class CodexContractsAccess : ICodexContracts public class CodexContractsAccess : ICodexContracts
@ -30,8 +33,7 @@ namespace CodexContractsPlugin
public bool IsDeployed() public bool IsDeployed()
{ {
var interaction = new ContractInteractions(log, gethNode); return !string.IsNullOrEmpty(StartInteraction().GetTokenName(Deployment.TokenAddress));
return !string.IsNullOrEmpty(interaction.GetTokenName(Deployment.TokenAddress));
} }
public string MintTestTokens(IHasEthAddress owner, TestToken testTokens) public string MintTestTokens(IHasEthAddress owner, TestToken testTokens)
@ -41,8 +43,7 @@ namespace CodexContractsPlugin
public string MintTestTokens(EthAddress ethAddress, TestToken testTokens) public string MintTestTokens(EthAddress ethAddress, TestToken testTokens)
{ {
var interaction = new ContractInteractions(log, gethNode); return StartInteraction().MintTestTokens(ethAddress, testTokens.Amount, Deployment.TokenAddress);
return interaction.MintTestTokens(ethAddress, testTokens.Amount, Deployment.TokenAddress);
} }
public TestToken GetTestTokenBalance(IHasEthAddress owner) public TestToken GetTestTokenBalance(IHasEthAddress owner)
@ -52,9 +53,19 @@ namespace CodexContractsPlugin
public TestToken GetTestTokenBalance(EthAddress ethAddress) public TestToken GetTestTokenBalance(EthAddress ethAddress)
{ {
var interaction = new ContractInteractions(log, gethNode); var balance = StartInteraction().GetBalance(Deployment.TokenAddress, ethAddress.Address);
var balance = interaction.GetBalance(Deployment.TokenAddress, ethAddress.Address);
return balance.TestTokens(); 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.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts; using Nethereum.Contracts;
using NethereumWorkflow; using NethereumWorkflow;
using Utils;
namespace GethPlugin namespace GethPlugin
{ {
@ -22,7 +23,7 @@ namespace GethPlugin
bool IsContractAvailable(string abi, string contractAddress); bool IsContractAvailable(string abi, string contractAddress);
GethBootstrapNode GetBootstrapRecord(); GethBootstrapNode GetBootstrapRecord();
List<EventLog<TEvent>> GetEvents<TEvent>(string address, ulong fromBlockNumber, ulong toBlockNumber) where TEvent : IEventDTO, new(); 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 public class DeploymentGethNode : BaseGethNode, IGethNode
@ -141,9 +142,9 @@ namespace GethPlugin
return StartInteraction().GetEvents<TEvent>(address, fromBlockNumber, toBlockNumber); 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(); 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, seller, Is.GreaterThan(sellerInitialBalance), "Seller was not paid for storage.");
AssertBalance(contracts, buyer, Is.LessThan(buyerInitialBalance), "Buyer was not charged 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] [Test]

View File

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