diff --git a/src/Nethermind/Nethermind.Mev/Data/MegabundleEventArgs.cs b/src/Nethermind/Nethermind.Mev/Data/MegabundleEventArgs.cs
deleted file mode 100644
index 0b294c8b71e..00000000000
--- a/src/Nethermind/Nethermind.Mev/Data/MegabundleEventArgs.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2021 Demerzel Solutions Limited
-// This file is part of the Nethermind library.
-//
-// The Nethermind library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Nethermind library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Nethermind. If not, see .
-//
-
-using System;
-using Nethermind.Core;
-
-namespace Nethermind.Mev.Data
-{
- public class MegabundleEventArgs : BundleEventArgs
- {
- public Address RelayAddress { get; }
-
- public MegabundleEventArgs(MevBundle mevBundle, Address relayAddress): base(mevBundle)
- {
- RelayAddress = relayAddress;
- }
- }
-}
diff --git a/src/Nethermind/Nethermind.Mev/Data/MevMegabundle.cs b/src/Nethermind/Nethermind.Mev/Data/MevMegabundle.cs
index 1ec26c93fbb..2bb260c80f2 100644
--- a/src/Nethermind/Nethermind.Mev/Data/MevMegabundle.cs
+++ b/src/Nethermind/Nethermind.Mev/Data/MevMegabundle.cs
@@ -16,27 +16,30 @@
//
using System;
+using System.Collections.Generic;
using Nethermind.Core.Crypto;
+using Nethermind.Int256;
namespace Nethermind.Mev.Data
{
- public class MevMegabundle: IEquatable
+ public class MevMegabundle: MevBundle, IEquatable
{
- public MevMegabundle(MevBundle bundle, Signature relaySignature)
+ public MevMegabundle(Signature relaySignature, long blockNumber, IReadOnlyList transactions, UInt256? minTimestamp = null, UInt256? maxTimestamp = null)
+ : base(blockNumber, transactions, minTimestamp, maxTimestamp)
{
- Bundle = bundle;
RelaySignature = relaySignature;
}
- public MevBundle Bundle { get; }
public Signature RelaySignature { get; }
-
+
public bool Equals(MevMegabundle? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
- return Equals(Bundle, other.Bundle)
+ return Equals(Hash, other.Hash)
&& Equals(RelaySignature, other.RelaySignature);
}
+
+ public override string ToString() => $"Hash:{Hash}; Block:{BlockNumber}; Min:{MinTimestamp}; Max:{MaxTimestamp}; TxCount:{Transactions.Count}; RelaySignature:{RelaySignature};";
}
}
diff --git a/src/Nethermind/Nethermind.Mev/MevPlugin.cs b/src/Nethermind/Nethermind.Mev/MevPlugin.cs
index 4e628dff3e1..3da55fabe77 100644
--- a/src/Nethermind/Nethermind.Mev/MevPlugin.cs
+++ b/src/Nethermind/Nethermind.Mev/MevPlugin.cs
@@ -156,9 +156,10 @@ public async Task InitBlockProducer(IConsensusPlugin consensusPl
}
_nethermindApi.BlockProducerEnvFactory.TransactionsExecutorFactory = new MevBlockProducerTransactionsExecutorFactory(_nethermindApi.SpecProvider!, _nethermindApi.LogManager);
-
+
+ int megabundleProducerCount = _mevConfig.GetTrustedRelayAddresses().Any() ? 1 : 0;
List blockProducers =
- new(_mevConfig.MaxMergedBundles + _mevConfig.GetTrustedRelayAddresses().Count() + 1);
+ new(_mevConfig.MaxMergedBundles + megabundleProducerCount + 1);
// Add non-mev block
MevBlockProducer.MevBlockProducerInfo standardProducer = await CreateProducer(consensusPlugin);
@@ -172,10 +173,10 @@ public async Task InitBlockProducer(IConsensusPlugin consensusPl
blockProducers.Add(bundleProducer);
}
- foreach (Address address in _mevConfig.GetTrustedRelayAddresses())
+ if (megabundleProducerCount > 0)
{
- MegabundleSelector megabundleSelector = new(BundlePool, address);
- MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, address, new BundleTxSource(megabundleSelector, _nethermindApi.Timestamper));
+ MegabundleSelector megabundleSelector = new(BundlePool);
+ MevBlockProducer.MevBlockProducerInfo bundleProducer = await CreateProducer(consensusPlugin, 0, new BundleTxSource(megabundleSelector, _nethermindApi.Timestamper));
blockProducers.Add(bundleProducer);
}
@@ -210,30 +211,6 @@ bool BundleLimitTriggerCondition(BlockProductionEventArgs e)
return new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer());
}
- private async Task CreateProducer(
- IConsensusPlugin consensusPlugin,
- Address relayAddress,
- ITxSource? additionalTxSource = null)
- {
- bool MegabundleTriggerCondition(BlockProductionEventArgs e)
- {
- BlockHeader? parent = _nethermindApi.BlockTree!.GetProducedBlockParent(e.ParentHeader);
- if (parent is not null)
- {
- MevBundle? bundle = BundlePool.GetMegabundle(parent, _nethermindApi.Timestamper, relayAddress);
- return bundle is not null;
- }
-
- return false;
- }
-
- IManualBlockProductionTrigger manualTrigger = new BuildBlocksWhenRequested();
- IBlockProductionTrigger trigger = new TriggerWithCondition(manualTrigger, MegabundleTriggerCondition);
-
- IBlockProducer producer = await consensusPlugin.InitBlockProducer(trigger, additionalTxSource);
- return new MevBlockProducer.MevBlockProducerInfo(producer, manualTrigger, new BeneficiaryTracer());
- }
-
public bool Enabled => _mevConfig.Enabled;
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
diff --git a/src/Nethermind/Nethermind.Mev/MevRpcModule.cs b/src/Nethermind/Nethermind.Mev/MevRpcModule.cs
index db7ec56624d..696c8f28b7e 100644
--- a/src/Nethermind/Nethermind.Mev/MevRpcModule.cs
+++ b/src/Nethermind/Nethermind.Mev/MevRpcModule.cs
@@ -79,8 +79,7 @@ public ResultWrapper eth_sendBundle(MevBundleRpc mevBundleRpc)
public ResultWrapper eth_sendMegabundle(MevMegabundleRpc mevMegabundleRpc)
{
BundleTransaction[] txs = Decode(mevMegabundleRpc.Txs, mevMegabundleRpc.RevertingTxHashes?.ToHashSet());
- MevBundle bundle = new(mevMegabundleRpc.BlockNumber, txs, mevMegabundleRpc.MinTimestamp, mevMegabundleRpc.MaxTimestamp);
- MevMegabundle megabundle = new(bundle, mevMegabundleRpc.RelaySignature!);
+ MevMegabundle megabundle = new(mevMegabundleRpc.RelaySignature!, mevMegabundleRpc.BlockNumber, txs, mevMegabundleRpc.MinTimestamp, mevMegabundleRpc.MaxTimestamp);
bool result = _bundlePool.AddMegabundle(megabundle);
return ResultWrapper.Success(result);
}
diff --git a/src/Nethermind/Nethermind.Mev/Source/BundlePool.cs b/src/Nethermind/Nethermind.Mev/Source/BundlePool.cs
index fd10c13474b..44ecb1f95dc 100644
--- a/src/Nethermind/Nethermind.Mev/Source/BundlePool.cs
+++ b/src/Nethermind/Nethermind.Mev/Source/BundlePool.cs
@@ -55,8 +55,6 @@ public class BundlePool : IBundlePool, ISimulatedBundleSource, IDisposable
public event EventHandler? NewReceivedBundle;
public event EventHandler? NewPendingBundle;
- public event EventHandler? NewReceivedMegabundle;
- public event EventHandler? NewPendingMegabundle;
public BundlePool(
IBlockTree blockTree,
@@ -85,7 +83,6 @@ public BundlePool(
_bundles.Removed += OnBundleRemoved;
_blockTree.NewHeadBlock += OnNewBlock;
- NewPendingMegabundle += OnNewPendingMegabundle;
}
public Task> GetBundles(BlockHeader parent, UInt256 timestamp, long gasLimit, CancellationToken token = default) =>
@@ -104,10 +101,8 @@ private IEnumerable GetBundles(long blockNumber, UInt256 minTimestamp
{
break;
}
-
- bool bundleIsInFuture = mevBundle.MinTimestamp != UInt256.Zero && minTimestamp < mevBundle.MinTimestamp;
- bool bundleIsTooOld = mevBundle.MaxTimestamp != UInt256.Zero && maxTimestamp > mevBundle.MaxTimestamp;
- if (!bundleIsInFuture && !bundleIsTooOld)
+
+ if (BundleInTimestampRange(mevBundle, minTimestamp, maxTimestamp))
{
yield return mevBundle;
}
@@ -115,33 +110,28 @@ private IEnumerable GetBundles(long blockNumber, UInt256 minTimestamp
}
}
- public Task GetMegabundle(BlockHeader parent, UInt256 timestamp, long gasLimit,
- Address relayAddress, CancellationToken token = default) =>
- Task.FromResult(GetMegabundle(parent.Number + 1, timestamp, relayAddress, token));
+ public Task> GetMegabundles(BlockHeader parent, UInt256 timestamp, long gasLimit, CancellationToken token = default) =>
+ Task.FromResult(GetMegabundles(parent.Number + 1, timestamp, token));
- public MevBundle? GetMegabundle(long blockNumber, UInt256 timestamp, Address relayAddress, CancellationToken token = default) =>
- GetMegabundle(blockNumber, timestamp, timestamp, relayAddress, token);
+ public IEnumerable GetMegabundles(long blockNumber, UInt256 timestamp, CancellationToken token = default) =>
+ GetMegabundles(blockNumber, timestamp, timestamp, token);
- private MevBundle? GetMegabundle(long blockNumber, UInt256 minTimestamp, UInt256 maxTimestamp, Address relayAddress,
+ private IEnumerable GetMegabundles(long blockNumber, UInt256 minTimestamp, UInt256 maxTimestamp,
CancellationToken token = default)
{
- if (_megabundles.TryGetValue(relayAddress, out MevBundle? bundle))
+ foreach (var bundle in _megabundles.Values)
{
if (token.IsCancellationRequested)
{
- return null;
+ break;
}
- bool bundleIsInFuture = bundle.MinTimestamp != UInt256.Zero && minTimestamp < bundle.MinTimestamp;
- bool bundleIsTooOld = bundle.MaxTimestamp != UInt256.Zero && maxTimestamp > bundle.MaxTimestamp;
bool bundleIsInCurrentBlock = bundle.BlockNumber == blockNumber;
- if (!bundleIsInFuture && !bundleIsTooOld && bundleIsInCurrentBlock)
+ if (BundleInTimestampRange(bundle, minTimestamp, maxTimestamp) && bundleIsInCurrentBlock)
{
- return bundle;
+ yield return bundle;
}
}
-
- return null;
}
public bool AddBundle(MevBundle bundle)
@@ -173,28 +163,42 @@ public bool AddBundle(MevBundle bundle)
public bool AddMegabundle(MevMegabundle megabundle)
{
Metrics.MegabundlesReceived++;
- Address relayAddress = _ecdsa.RecoverAddress(megabundle.RelaySignature, megabundle.Bundle.Hash)!;
- MegabundleEventArgs megabundleEventArgs = new(megabundle.Bundle, relayAddress);
- NewReceivedMegabundle?.Invoke(this, megabundleEventArgs);
+ BundleEventArgs bundleEventArgs = new(megabundle);
+ NewReceivedBundle?.Invoke(this, bundleEventArgs);
- if (ValidateBundle(megabundle.Bundle) && IsTrustedRelay(relayAddress))
+ if (ValidateBundle(megabundle))
{
- _megabundles.AddOrUpdate(relayAddress,
- _ => megabundle.Bundle,
- (_, _) => megabundle.Bundle);
- Metrics.ValidMegabundlesReceived++;
- NewPendingMegabundle?.Invoke(this, megabundleEventArgs);
-
- if (megabundle.Bundle.BlockNumber == HeadNumber + 1)
- {
- TrySimulateBundle(megabundle.Bundle);
+ Address relayAddress = _ecdsa.RecoverAddress(megabundle.RelaySignature, megabundle.Hash)!;
+ if (IsTrustedRelay(relayAddress))
+ {
+ Metrics.ValidMegabundlesReceived++;
+ NewPendingBundle?.Invoke(this, bundleEventArgs);
+
+ _megabundles.AddOrUpdate(relayAddress,
+ _ => megabundle,
+ (_, _) =>
+ {
+ RemoveSimulation(megabundle);
+ return megabundle;
+ });
+
+ if (megabundle.BlockNumber == HeadNumber + 1)
+ {
+ TrySimulateBundle(megabundle);
+ }
}
-
return true;
}
return false;
}
+
+ private bool BundleInTimestampRange(MevBundle bundle, UInt256 minTimestamp, UInt256 maxTimestamp)
+ {
+ bool bundleIsInFuture = bundle.MinTimestamp != UInt256.Zero && minTimestamp < bundle.MinTimestamp;
+ bool bundleIsTooOld = bundle.MaxTimestamp != UInt256.Zero && maxTimestamp > bundle.MaxTimestamp;
+ return !bundleIsInFuture && !bundleIsTooOld;
+ }
private bool IsTrustedRelay(Address relayAddress)
{
@@ -391,16 +395,8 @@ private void StopSimulation(SimulatedMevBundleContext simulation)
}
}
- private void OnNewPendingMegabundle(object? sender, MegabundleEventArgs e)
- {
- _megabundles.TryRemove(e.RelayAddress, out _);
- RemoveSimulation(e.MevBundle);
- }
-
- async Task> ISimulatedBundleSource.GetBundles(BlockHeader parent, UInt256 timestamp, long gasLimit, CancellationToken token)
+ private async Task> GetSimulatedBundles(HashSet bundles, BlockHeader parent, UInt256 timestamp, long gasLimit, CancellationToken token)
{
- HashSet bundles = (await GetBundles(parent, timestamp, gasLimit, token)).ToHashSet();
-
if (_simulatedBundles.TryGetValue(parent.Number, out ConcurrentDictionary<(MevBundle Bundle, Keccak BlockHash), SimulatedMevBundleContext>? simulatedBundlesForBlock))
{
IEnumerable> resultTasks = simulatedBundlesForBlock
@@ -421,36 +417,24 @@ async Task> ISimulatedBundleSource.GetBundles(Bl
}
return (Enumerable.Empty());
}
-
- async Task ISimulatedBundleSource.GetMegabundle(BlockHeader parent, UInt256 timestamp,
- long gasLimit, Address relayAddress, CancellationToken token)
+
+ async Task> ISimulatedBundleSource.GetBundles(BlockHeader parent, UInt256 timestamp, long gasLimit, CancellationToken token)
{
- MevBundle? bundle = await GetMegabundle(parent, timestamp, gasLimit, relayAddress, token);
-
- if (bundle is not null && _simulatedBundles.TryGetValue(parent.Number, out ConcurrentDictionary<(MevBundle Bundle, Keccak BlockHash), SimulatedMevBundleContext>? simulatedBundlesForBlock))
- {
- if (simulatedBundlesForBlock.TryGetValue((bundle, parent.Hash!),
- out SimulatedMevBundleContext? simulatedBundle))
- {
- Task resultTask = simulatedBundle.Task;
- await Task.WhenAny(resultTask, token.AsTask());
+ HashSet bundles = (await GetBundles(parent, timestamp, gasLimit, token)).ToHashSet();
+ return await GetSimulatedBundles(bundles, parent, timestamp, gasLimit, token);
+ }
- bool success = resultTask.IsCompletedSuccessfully && resultTask.Result.Success;
- bool withinGasLimit = resultTask.Result.GasUsed <= gasLimit;
- if (success && withinGasLimit)
- {
- return resultTask.Result;
- }
- }
- }
- return null;
+ async Task> ISimulatedBundleSource.GetMegabundles(BlockHeader parent, UInt256 timestamp,
+ long gasLimit, CancellationToken token)
+ {
+ HashSet bundles = (await GetMegabundles(parent, timestamp, gasLimit, token)).ToHashSet();
+ return await GetSimulatedBundles(bundles, parent, timestamp, gasLimit, token);
}
public void Dispose()
{
_blockTree.NewHeadBlock -= OnNewBlock;
_bundles.Removed -= OnBundleRemoved;
- NewPendingMegabundle -= OnNewPendingMegabundle;
}
protected class SimulatedMevBundleContext : IDisposable
diff --git a/src/Nethermind/Nethermind.Mev/Source/IBundlePool.cs b/src/Nethermind/Nethermind.Mev/Source/IBundlePool.cs
index 78ea0e4da1b..e4aff0e1685 100644
--- a/src/Nethermind/Nethermind.Mev/Source/IBundlePool.cs
+++ b/src/Nethermind/Nethermind.Mev/Source/IBundlePool.cs
@@ -28,12 +28,10 @@ public interface IBundlePool : IBundleSource
{
event EventHandler NewReceivedBundle;
event EventHandler NewPendingBundle;
- event EventHandler NewReceivedMegabundle;
- event EventHandler NewPendingMegabundle;
bool AddBundle(MevBundle bundle);
bool AddMegabundle(MevMegabundle megabundle);
IEnumerable GetBundles(long block, UInt256 timestamp, CancellationToken token = default);
- MevBundle? GetMegabundle(long block, UInt256 timestamp, Address relayAddress, CancellationToken token = default);
+ IEnumerable GetMegabundles(long block, UInt256 timestamp, CancellationToken token = default);
}
public static class BundlePoolExtensions
@@ -41,7 +39,7 @@ public static class BundlePoolExtensions
public static IEnumerable GetBundles(this IBundlePool bundleSource, BlockHeader parent, ITimestamper timestamper, CancellationToken token = default) =>
bundleSource.GetBundles(parent.Number + 1, timestamper.UnixTime.Seconds, token);
- public static MevBundle? GetMegabundle(this IBundlePool bundleSource, BlockHeader parent, ITimestamper timestamper, Address relayAddress, CancellationToken token = default) =>
- bundleSource.GetMegabundle(parent.Number + 1, timestamper.UnixTime.Seconds, relayAddress, token);
+ public static IEnumerable GetMegabundles(this IBundlePool bundleSource, BlockHeader parent, ITimestamper timestamper, CancellationToken token = default) =>
+ bundleSource.GetMegabundles(parent.Number + 1, timestamper.UnixTime.Seconds, token);
}
}
diff --git a/src/Nethermind/Nethermind.Mev/Source/ISimulatedBundleSource.cs b/src/Nethermind/Nethermind.Mev/Source/ISimulatedBundleSource.cs
index ffa26538061..6e30768accf 100644
--- a/src/Nethermind/Nethermind.Mev/Source/ISimulatedBundleSource.cs
+++ b/src/Nethermind/Nethermind.Mev/Source/ISimulatedBundleSource.cs
@@ -29,7 +29,7 @@ public interface ISimulatedBundleSource
Task> GetBundles(BlockHeader parent, UInt256 timestamp, long gasLimit,
CancellationToken token = default);
- Task GetMegabundle(BlockHeader parent, UInt256 timestamp, long gasLimit, Address relayAddress,
+ Task> GetMegabundles(BlockHeader parent, UInt256 timestamp, long gasLimit,
CancellationToken token = default);
}
}
diff --git a/src/Nethermind/Nethermind.Mev/Source/MegabundleSelector.cs b/src/Nethermind/Nethermind.Mev/Source/MegabundleSelector.cs
index f5dd4e039fe..c235b06c292 100644
--- a/src/Nethermind/Nethermind.Mev/Source/MegabundleSelector.cs
+++ b/src/Nethermind/Nethermind.Mev/Source/MegabundleSelector.cs
@@ -28,19 +28,21 @@ namespace Nethermind.Mev.Source
public class MegabundleSelector : IBundleSource
{
private readonly ISimulatedBundleSource _simulatedBundleSource;
- private readonly Address _relayAddress;
- public MegabundleSelector(ISimulatedBundleSource simulatedBundleSource, Address relayAddress)
+ public MegabundleSelector(ISimulatedBundleSource simulatedBundleSource)
{
_simulatedBundleSource = simulatedBundleSource;
- _relayAddress = relayAddress;
}
public async Task> GetBundles(BlockHeader parent, UInt256 timestamp, long gasLimit,
CancellationToken token = default)
{
- SimulatedMevBundle? simulatedBundle = await _simulatedBundleSource.GetMegabundle(parent, timestamp, gasLimit, _relayAddress, token);
- return simulatedBundle is null ? Enumerable.Empty() : new [] {simulatedBundle.Bundle};
+ IEnumerable simulatedBundles = await _simulatedBundleSource.GetMegabundles(parent, timestamp, gasLimit, token);
+ return simulatedBundles
+ .OrderByDescending(bundle => bundle.BundleAdjustedGasPrice)
+ .ThenBy(bundle => bundle.Bundle.SequenceNumber)
+ .Take(1)
+ .Select(s => s.Bundle);
}
}
}