Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public FilterBuilder WithAddress(Address address)

public FilterBuilder WithAddresses(params Address[] addresses)
{
_address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a)).ToHashSet());
_address = new AddressFilter(addresses.Select(static a => new AddressAsKey(a)).ToArray());

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void Accepts_any_address_by_ref()
[Test]
public void Accepts_any_address_when_set_is_empty()
{
HashSet<AddressAsKey> addresses = new();
AddressAsKey[] addresses = [];
AddressFilter filter = new AddressFilter(addresses);

filter.Accepts(TestItem.AddressA).Should().BeTrue();
Expand All @@ -84,7 +84,7 @@ public void Accepts_any_address_when_set_is_empty()
[Test]
public void Accepts_any_address_when_set_is_empty_by_ref()
{
HashSet<AddressAsKey> addresses = new();
AddressAsKey[] addresses = [];
AddressFilter filter = new AddressFilter(addresses);

AddressStructRef addressARef = TestItem.AddressA.ToStructRef();
Expand All @@ -98,10 +98,10 @@ public void Accepts_any_address_when_set_is_empty_by_ref()
[Test]
public void Accepts_only_addresses_in_a_set()
{
HashSet<AddressAsKey> addresses = new()
{
AddressAsKey[] addresses =
[
TestItem.AddressA, TestItem.AddressC
};
];
AddressFilter filter = new AddressFilter(addresses);

filter.Accepts(TestItem.AddressA).Should().BeTrue();
Expand All @@ -112,10 +112,10 @@ public void Accepts_only_addresses_in_a_set()
[Test]
public void Accepts_only_addresses_in_a_set_by_ref()
{
HashSet<AddressAsKey> addresses = new()
{
AddressAsKey[] addresses =
[
TestItem.AddressA, TestItem.AddressC
};
];
AddressFilter filter = new AddressFilter(addresses);

AddressStructRef addressARef = TestItem.AddressA.ToStructRef();
Expand Down Expand Up @@ -187,7 +187,7 @@ public void Matches_bloom_using_any_address_by_ref()
[Test]
public void Matches_any_bloom_when_set_is_empty()
{
HashSet<AddressAsKey> addresses = new();
AddressAsKey[] addresses = [];
AddressFilter filter = new AddressFilter(addresses);

filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue();
Expand All @@ -198,7 +198,7 @@ public void Matches_any_bloom_when_set_is_empty()
[Test]
public void Matches_any_bloom_when_set_is_empty_by_ref()
{
HashSet<AddressAsKey> addresses = new();
AddressAsKey[] addresses = [];
AddressFilter filter = new AddressFilter(addresses);

BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef();
Expand All @@ -212,7 +212,7 @@ public void Matches_any_bloom_when_set_is_empty_by_ref()
[Test]
public void Matches_any_bloom_when_set_is_forced_null()
{
AddressFilter filter = new AddressFilter(addresses: null!);
AddressFilter filter = new AddressFilter([]);

filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue();
filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue();
Expand All @@ -222,7 +222,7 @@ public void Matches_any_bloom_when_set_is_forced_null()
[Test]
public void Matches_any_bloom_when_set_is_forced_null_by_ref()
{
AddressFilter filter = new AddressFilter(addresses: null!);
AddressFilter filter = new AddressFilter([]);

BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef();
BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef();
Expand All @@ -235,10 +235,10 @@ public void Matches_any_bloom_when_set_is_forced_null_by_ref()
[Test]
public void Matches_any_bloom_using_addresses_set()
{
HashSet<AddressAsKey> addresses = new()
{
AddressAsKey[] addresses =
[
TestItem.AddressA, TestItem.AddressC
};
];
AddressFilter filter = new AddressFilter(addresses);

filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue();
Expand All @@ -249,10 +249,10 @@ public void Matches_any_bloom_using_addresses_set()
[Test]
public void Matches_any_bloom_using_addresses_set_by_ref()
{
HashSet<AddressAsKey> addresses = new()
{
AddressAsKey[] addresses =
[
TestItem.AddressA, TestItem.AddressC
};
];
AddressFilter filter = new AddressFilter(addresses);

BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Nethermind.Blockchain.Filters.Topics;
using Nethermind.Blockchain.Find;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Core.Test.Builders;
using Nethermind.Core.Timers;
using NSubstitute;
Expand Down Expand Up @@ -102,14 +103,14 @@ public static IEnumerable CorrectlyCreatesAddressFilterTestCases
get
{
yield return new TestCaseData(null, AddressFilter.AnyAddress);
yield return new TestCaseData(TestItem.AddressA.ToString(), new AddressFilter(TestItem.AddressA));
yield return new TestCaseData(new[] { TestItem.AddressA.ToString(), TestItem.AddressB.ToString() },
new AddressFilter(new HashSet<AddressAsKey>() { TestItem.AddressA, TestItem.AddressB }));
yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA) }, new AddressFilter(TestItem.AddressA));
yield return new TestCaseData(new[] { new AddressAsKey(TestItem.AddressA), new AddressAsKey(TestItem.AddressB) },
new AddressFilter([TestItem.AddressA, TestItem.AddressB]));
}
}

[TestCaseSource(nameof(CorrectlyCreatesAddressFilterTestCases))]
public void Correctly_creates_address_filter(object address, AddressFilter expected)
public void Correctly_creates_address_filter(AddressAsKey[] address, AddressFilter expected)
{
BlockParameter from = new(100);
BlockParameter to = new(BlockParameterType.Latest);
Expand All @@ -124,22 +125,25 @@ public static IEnumerable CorrectlyCreatesTopicsFilterTestCases
{
yield return new TestCaseData(null, SequenceTopicsFilter.AnyTopic);

yield return new TestCaseData(new[] { TestItem.KeccakA.ToString() },
yield return new TestCaseData(new[] { new[] { TestItem.KeccakA } },
new SequenceTopicsFilter(new SpecificTopic(TestItem.KeccakA)));

yield return new TestCaseData(new[] { TestItem.KeccakA.ToString(), TestItem.KeccakB.ToString() },
yield return new TestCaseData(new[] { new[] { TestItem.KeccakA }, new[] { TestItem.KeccakB } },
new SequenceTopicsFilter(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB)));

yield return new TestCaseData(new[] { null, TestItem.KeccakB.ToString() },
yield return new TestCaseData(new[] { null, new[] { TestItem.KeccakB } },
new SequenceTopicsFilter(AnyTopic.Instance, new SpecificTopic(TestItem.KeccakB)));

yield return new TestCaseData(new object[] { new[] { TestItem.KeccakA.ToString(), TestItem.KeccakB.ToString(), TestItem.KeccakC.ToString() }, TestItem.KeccakD.ToString() },
new SequenceTopicsFilter(new OrExpression(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB), new SpecificTopic(TestItem.KeccakC)), new SpecificTopic(TestItem.KeccakD)));
yield return new TestCaseData(
new[] { new[] { TestItem.KeccakA, TestItem.KeccakB, TestItem.KeccakC }, new[] { TestItem.KeccakD } },
new SequenceTopicsFilter(
new OrExpression(new SpecificTopic(TestItem.KeccakA), new SpecificTopic(TestItem.KeccakB),
new SpecificTopic(TestItem.KeccakC)), new SpecificTopic(TestItem.KeccakD)));
}
}

[TestCaseSource(nameof(CorrectlyCreatesTopicsFilterTestCases))]
public void Correctly_creates_topics_filter(IEnumerable<object> topics, TopicsFilter expected)
public void Correctly_creates_topics_filter(Hash256[]?[]? topics, TopicsFilter expected)
{
BlockParameter from = new(100);
BlockParameter to = new(BlockParameterType.Latest);
Expand Down
14 changes: 7 additions & 7 deletions src/Nethermind/Nethermind.Facade/BlockchainBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ public ulong GetChainId()
public IEnumerable<FilterLog> GetLogs(
BlockParameter fromBlock,
BlockParameter toBlock,
object? address = null,
IEnumerable<object>? topics = null,
AddressAsKey[]? address = null,
IEnumerable<Hash256[]?>? topics = null,
CancellationToken cancellationToken = default)
{
LogFilter filter = GetFilter(fromBlock, toBlock, address, topics);
Expand All @@ -300,8 +300,8 @@ public IEnumerable<FilterLog> GetLogs(
public LogFilter GetFilter(
BlockParameter fromBlock,
BlockParameter toBlock,
object? address = null,
IEnumerable<object>? topics = null)
AddressAsKey[]? address = null,
IEnumerable<Hash256[]?>? topics = null)
{
return filterStore.CreateLogFilter(fromBlock, toBlock, address, topics, false);
}
Expand All @@ -325,10 +325,10 @@ public bool TryGetLogs(int filterId, out IEnumerable<FilterLog> filterLogs, Canc
return filter is not null;
}

public int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock,
object? address = null, IEnumerable<object>? topics = null)
public int NewFilter(BlockParameter fromBlock, BlockParameter toBlock,
AddressAsKey[]? address = null, IEnumerable<Hash256[]?>? topics = null)
{
LogFilter filter = filterStore.CreateLogFilter(fromBlock ?? BlockParameter.Latest, toBlock ?? BlockParameter.Latest, address, topics);
LogFilter filter = filterStore.CreateLogFilter(fromBlock, toBlock, address, topics);
filterStore.SaveFilter(filter);
return filter.Id;
}
Expand Down
13 changes: 10 additions & 3 deletions src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Nethermind.Blockchain.Filters
{
public class AddressFilter
{
public static readonly AddressFilter AnyAddress = new(addresses: new HashSet<AddressAsKey>());
public static readonly AddressFilter AnyAddress = new([]);

private Bloom.BloomExtract[]? _addressesBloomIndexes;
private Bloom.BloomExtract? _addressBloomExtract;
Expand All @@ -19,9 +19,16 @@ public AddressFilter(Address address)
Address = address;
}

public AddressFilter(HashSet<AddressAsKey> addresses)
public AddressFilter(AddressAsKey[] addresses)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason behind replacing HashSet with an array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think AddressFilter should decide how addresses are stored inside

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about accepting IEnumerable instead? I see in some places we are calling ToArray to immediately follow with ToHashSet after.

{
Addresses = addresses;
if (addresses.Length == 1)
{
Address = addresses[0];
}
else
{
Addresses = addresses.ToHashSet();
}
}

public Address? Address { get; }
Expand Down
52 changes: 22 additions & 30 deletions src/Nethermind/Nethermind.Facade/Filters/FilterStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public PendingTransactionFilter CreatePendingTransactionFilter(bool setId = true
new(GetFilterId(setId));

public LogFilter CreateLogFilter(BlockParameter fromBlock, BlockParameter toBlock,
object? address = null, IEnumerable<object?>? topics = null, bool setId = true) =>
AddressAsKey[]? address = null, IEnumerable<Hash256[]?>? topics = null, bool setId = true) =>
new(GetFilterId(setId),
fromBlock,
toBlock,
Expand Down Expand Up @@ -165,7 +165,7 @@ private int GetFilterId(bool generateId)
return 0;
}

private static TopicsFilter GetTopicsFilter(IEnumerable<object?>? topics = null)
private static TopicsFilter GetTopicsFilter(IEnumerable<Hash256[]?>? topics = null)
{
if (topics is null)
{
Expand Down Expand Up @@ -202,48 +202,40 @@ private static TopicExpression GetTopicExpression(FilterTopic? filterTopic)
return AnyTopic.Instance;
}

private static AddressFilter GetAddress(object? address) =>
address switch
private static AddressFilter GetAddress(AddressAsKey[]? address)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter should probably be named addresses, just to avoid confusion.

{
if (address is null)
{
null => AddressFilter.AnyAddress,
string s => new AddressFilter(new Address(s)),
IEnumerable<string> e => new AddressFilter(e.Select(static a => new AddressAsKey(new Address(a))).ToHashSet()),
_ => throw new InvalidDataException("Invalid address filter format")
};
return AddressFilter.AnyAddress;
}

private static FilterTopic?[]? GetFilterTopics(IEnumerable<object>? topics) => topics?.Select(GetTopic).ToArray();
return new AddressFilter(address);
}

private static FilterTopic?[]? GetFilterTopics(IEnumerable<Hash256[]?>? topics) => topics?.Select(GetTopic).ToArray();

private static FilterTopic? GetTopic(object? obj)
private static FilterTopic? GetTopic(Hash256[]? topics)
{
switch (obj)
if (topics?.Length == 1)
{
case null:
return null;
case string topic:
return new FilterTopic
{
Topic = new Hash256(topic)
};
case Hash256 keccak:
return new FilterTopic
{
Topic = keccak
};
return new FilterTopic
{
Topic = topics[0]
};
}

return obj is not IEnumerable<string> topics
? null
: new FilterTopic
else
{
return new FilterTopic()
{
Topics = topics.Select(static t => new Hash256(t)).ToArray()
Topics = topics
};
}
}

private class FilterTopic
{
public Hash256? Topic { get; init; }
public Hash256[]? Topics { get; init; }

}

public void Dispose()
Expand Down
6 changes: 3 additions & 3 deletions src/Nethermind/Nethermind.Facade/IBlockchainBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public interface IBlockchainBridge : ILogFinder

int NewBlockFilter();
int NewPendingTransactionFilter();
int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, object? address = null, IEnumerable<object>? topics = null);
int NewFilter(BlockParameter? fromBlock, BlockParameter? toBlock, AddressAsKey[]? address = null, IEnumerable<Hash256[]?>? topics = null);
void UninstallFilter(int filterId);
bool FilterExists(int filterId);
Hash256[] GetBlockFilterChanges(int filterId);
Hash256[] GetPendingTransactionFilterChanges(int filterId);
FilterLog[] GetLogFilterChanges(int filterId);
FilterType GetFilterType(int filterId);
LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable<object>? topics = null);
LogFilter GetFilter(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? address = null, IEnumerable<Hash256[]?>? topics = null);
IEnumerable<FilterLog> GetLogs(LogFilter filter, BlockHeader fromBlock, BlockHeader toBlock, CancellationToken cancellationToken = default);
IEnumerable<FilterLog> GetLogs(BlockParameter fromBlock, BlockParameter toBlock, object? address = null, IEnumerable<object>? topics = null, CancellationToken cancellationToken = default);
IEnumerable<FilterLog> GetLogs(BlockParameter fromBlock, BlockParameter toBlock, AddressAsKey[]? address = null, IEnumerable<Hash256[]?>? topics = null, CancellationToken cancellationToken = default);

bool TryGetLogs(int filterId, out IEnumerable<FilterLog> filterLogs, CancellationToken cancellationToken = default);
void RunTreeVisitor<TCtx>(ITreeVisitor<TCtx> treeVisitor, Hash256 stateRoot) where TCtx : struct, INodeContext<TCtx>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ public void GetNewFilterTest()
var parameters = new
{
fromBlock = "0x1",
toBlock = "latest",
address = "0x1f88f1f195afa192cfee860698584c030f4c9db2",
topics = new List<object>
{
Expand Down
Loading