LogTopic - empty list is wildcard log topic (#8420)

* empty list is wildcard log topic

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
Sally MacFarlane
2025-03-18 14:33:28 +10:00
committed by GitHub
parent c924e7686f
commit c99bdbd533
5 changed files with 40 additions and 25 deletions

View File

@@ -59,6 +59,7 @@ have support in besu-native can run mainnet ethereum configurations. Windows su
- Add a fallback pivot strategy when the safe block does not change for a long time, to make possible to complete the initial sync in case the chain is not finalizing [#8395](https://github.com/hyperledger/besu/pull/8395)
- Fix issue with new QBFT/IBFT blocks being produced under certain circumstances. [#8308](https://github.com/hyperledger/besu/issues/8308)
- Fix QBFT and IBFT transitions that change the mining beneficiary [#8387](https://github.com/hyperledger/besu/issues/8387)
- `eth_getLogs` - empty topic is a wildcard match [#8420](https://github.com/hyperledger/besu/pull/8420)
## 25.2.2 hotfix
- Pectra - Sepolia: Fix for deposit contract log decoding [#8383](https://github.com/hyperledger/besu/pull/8383)

View File

@@ -795,7 +795,7 @@ public class BlockchainQueries {
* @param toBlockNumber The block number defining the last block in the search range (inclusive).
* @param query Constraints on required topics by topic index. For a given index if the set of
* topics is non-empty, the topic at this index must match one of the values in the set.
* @param isQueryAlive Whether or not the backend query should stay alive.
* @param isQueryAlive Whether the backend query should stay alive.
* @return The set of logs matching the given constraints.
*/
public List<LogWithMetadata> matchingLogs(
@@ -988,8 +988,8 @@ public class BlockchainQueries {
/**
* Wraps an operation on MutableWorldState with try-with-resources the corresponding block hash.
* This method provides access to the worldstate via a mapper function in order to ensure all of
* the uses of the MutableWorldState are subsequently closed, via the try-with-resources block.
* This method provides access to the worldstate via a mapper function in order to ensure all uses
* of the MutableWorldState are subsequently closed, via the try-with-resources block.
*
* @param <U> return type of the operation on the MutableWorldState
* @param blockHash the block hash

View File

@@ -99,7 +99,7 @@ public class LogsQuery {
}
private boolean matchesTopic(final LogTopic topic, final List<LogTopic> matchCriteria) {
return matchCriteria.contains(null) || matchCriteria.contains(topic);
return matchCriteria.isEmpty() || matchCriteria.contains(null) || matchCriteria.contains(topic);
}
@Override

View File

@@ -14,8 +14,6 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.Address;
@@ -428,23 +426,4 @@ public class LogsQueryTest {
assertThat(query.couldMatch(LogsBloomFilter.builder().insertLog(log).build())).isTrue();
assertThat(query.matches(log)).isTrue();
}
@Test
public void emptySubTopicProducesNoMatches() {
final Address address = Address.fromHexString("0x1111111111111111111111111111111111111111");
final LogTopic topic1 =
LogTopic.fromHexString(
"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
final LogTopic topic2 =
LogTopic.fromHexString(
"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
final List<List<LogTopic>> queryParameter =
Lists.newArrayList(singletonList(topic1), emptyList());
final LogsQuery query = new LogsQuery.Builder().address(address).topics(queryParameter).build();
final Log log = new Log(address, data, Lists.newArrayList(topic1, topic2));
assertThat(query.matches(log)).isFalse();
}
}

View File

@@ -71,4 +71,39 @@ public class LogsQueryTest {
List.of(ERC20_TRANSFER_EVENT, SECOND_ADDRESS_TOPIC, FIRST_ADDRESS_TOPIC))))
.isTrue();
}
@Test
public void testWildcardMatches() {
final LogsQuery query =
new LogsQuery(
List.of(),
List.of(
List.of(), // wildcard match in first spot
List.of(SECOND_ADDRESS_TOPIC)));
assertThat(query.matches(new Log(FIRST_ADDRESS, Bytes.EMPTY, List.of()))).isFalse();
assertThat(query.matches(new Log(FIRST_ADDRESS, Bytes.EMPTY, List.of(ERC20_TRANSFER_EVENT))))
.isFalse();
assertThat(
query.matches(
new Log(
FIRST_ADDRESS,
Bytes.EMPTY,
List.of(ERC20_TRANSFER_EVENT, FIRST_ADDRESS_TOPIC))))
.isFalse();
assertThat(
query.matches(
new Log(
FIRST_ADDRESS,
Bytes.EMPTY,
List.of(ERC20_TRANSFER_EVENT, SECOND_ADDRESS_TOPIC))))
.isTrue();
assertThat(
query.matches(
new Log(
FIRST_ADDRESS,
Bytes.EMPTY,
List.of(ERC20_TRANSFER_EVENT, SECOND_ADDRESS_TOPIC, FIRST_ADDRESS_TOPIC))))
.isTrue();
}
}