Minor improvements to EIP-7685 (#7142)

Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
This commit is contained in:
Gabriel-Trintinalia
2024-05-28 17:55:38 +10:00
committed by GitHub
parent 067164f7b5
commit 7a5a3e0957
20 changed files with 101 additions and 64 deletions

View File

@@ -14,8 +14,6 @@
*/
package org.hyperledger.besu.datatypes;
import java.util.Arrays;
/** Enum representing different types of requests with associated serialized type values. */
public enum RequestType {
/** DEPOSITS */
@@ -47,12 +45,12 @@ public enum RequestType {
* RequestType}.
*/
public static RequestType of(final int serializedTypeValue) {
return Arrays.stream(RequestType.values())
.filter(requestType -> requestType.typeValue == serializedTypeValue)
.findFirst()
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Unsupported request type: 0x%02X", serializedTypeValue)));
return switch (serializedTypeValue) {
case 0x00 -> DEPOSIT;
case 0x01 -> WITHDRAWAL;
default ->
throw new IllegalArgumentException(
String.format("Unsupported request type: 0x%02X", serializedTypeValue));
};
}
}

View File

@@ -66,6 +66,6 @@ public class RequestValidatorProvider {
final ProtocolSpec protocolSchedule) {
return Optional.ofNullable(protocolSchedule)
.map(ProtocolSpec::getRequestsValidatorCoordinator)
.orElseGet(() -> new RequestsValidatorCoordinator.Builder().build());
.orElseGet(RequestsValidatorCoordinator::empty);
}
}

View File

@@ -14,6 +14,9 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests;
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineGetPayloadBodiesResultV1.PayloadBody;
@@ -24,12 +27,8 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockValueCalculator;
import org.hyperledger.besu.ethereum.core.BlockWithReceipts;
import org.hyperledger.besu.ethereum.core.Deposit;
import org.hyperledger.besu.ethereum.core.Request;
import org.hyperledger.besu.ethereum.core.WithdrawalRequest;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil;
import java.util.ArrayList;
import java.util.List;
@@ -176,23 +175,12 @@ public class BlockResultFactory {
blockWithReceipts.getHeader(),
txs,
blockWithReceipts.getBlock().getBody().getWithdrawals(),
getDepositRequest(blockWithReceipts.getBlock().getBody().getRequests()),
getWithdrawalRequest(blockWithReceipts.getBlock().getBody().getRequests()),
getDepositRequests(blockWithReceipts.getBlock().getBody().getRequests()),
getWithdrawalRequests(blockWithReceipts.getBlock().getBody().getRequests()),
Quantity.create(blockValue),
blobsBundleV1);
}
private Optional<List<Deposit>> getDepositRequest(final Optional<List<Request>> requests) {
return requests.map(
requestList -> RequestUtil.filterRequestsOfType(requestList, Deposit.class));
}
private Optional<List<WithdrawalRequest>> getWithdrawalRequest(
final Optional<List<Request>> requests) {
return requests.map(
requestList -> RequestUtil.filterRequestsOfType(requestList, WithdrawalRequest.class));
}
public BlockResult transactionHash(final BlockWithMetadata<Hash, Hash> blockWithMetadata) {
return transactionHash(blockWithMetadata, false);
}

View File

@@ -521,7 +521,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
}
private void mockProhibitedRequestsValidator() {
var validator = new RequestsValidatorCoordinator.Builder().build();
var validator = RequestsValidatorCoordinator.empty();
when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator);
}
}

View File

@@ -158,7 +158,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
final List<DepositParameter> deposits = List.of();
lenient()
.when(protocolSpec.getRequestsValidatorCoordinator())
.thenReturn(new RequestsValidatorCoordinator.Builder().build());
.thenReturn(RequestsValidatorCoordinator.empty());
var resp =
resp(
@@ -311,7 +311,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
}
private void mockProhibitedRequestsValidator() {
var validator = new RequestsValidatorCoordinator.Builder().build();
var validator = RequestsValidatorCoordinator.empty();
when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator);
}

View File

@@ -134,7 +134,7 @@ abstract class AbstractBlockCreatorTest {
UInt64.valueOf(539967));
final List<Deposit> expectedDeposits = List.of(expectedDeposit);
final Optional<List<Request>> depositsFromReceipts =
var depositsFromReceipts =
new DepositRequestProcessor(DEFAULT_DEPOSIT_CONTRACT_ADDRESS).process(null, receipts);
assertThat(depositsFromReceipts.get()).isEqualTo(expectedDeposits);
}

View File

@@ -89,7 +89,7 @@ public final class BodyValidation {
}
/**
* Generates the request root for a list of requests
* Generates the requests root for a list of requests
*
* @param requests list of request
* @return the requests root

View File

@@ -78,7 +78,7 @@ public class ProtocolSpecBuilder {
new WithdrawalsValidator.ProhibitedWithdrawals();
private WithdrawalsProcessor withdrawalsProcessor;
private RequestsValidatorCoordinator requestsValidatorCoordinator =
new RequestsValidatorCoordinator.Builder().build();
RequestsValidatorCoordinator.empty();
private RequestProcessorCoordinator requestProcessorCoordinator;
protected BlockHashProcessor blockHashProcessor;
private FeeMarket feeMarket = FeeMarket.legacy();

View File

@@ -39,13 +39,13 @@ public class DepositRequestProcessor implements RequestProcessor {
}
@Override
public Optional<List<Request>> process(
public Optional<List<? extends Request>> process(
final MutableWorldState ignored, final List<TransactionReceipt> transactionReceipts) {
if (depositContractAddress.isEmpty()) {
return Optional.empty();
}
List<Deposit> deposits = findDepositsFromReceipts(transactionReceipts);
return Optional.of(deposits.stream().map(r -> (Request) r).toList());
return Optional.of(deposits);
}
@VisibleForTesting

View File

@@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.mainnet.requests;
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Deposit;
@@ -23,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.encoding.DepositDecoder;
import org.hyperledger.besu.evm.log.Log;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -75,7 +78,7 @@ public class DepositsValidator implements RequestValidator {
@Override
public boolean validate(
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) {
var deposits = RequestUtil.filterRequestsOfType(requests, Deposit.class);
var deposits = getDepositRequests(Optional.of(requests)).orElse(Collections.emptyList());
return validateDeposits(block, deposits, receipts);
}
}

View File

@@ -22,7 +22,7 @@ import java.util.List;
import java.util.Optional;
public interface RequestProcessor {
Optional<List<Request>> process(
Optional<List<? extends Request>> process(
final MutableWorldState mutableWorldState,
final List<TransactionReceipt> transactionReceipts);
}

View File

@@ -14,7 +14,9 @@
*/
package org.hyperledger.besu.ethereum.mainnet.requests;
import org.hyperledger.besu.ethereum.core.Deposit;
import org.hyperledger.besu.ethereum.core.Request;
import org.hyperledger.besu.ethereum.core.WithdrawalRequest;
import java.util.ArrayList;
import java.util.Collections;
@@ -40,6 +42,23 @@ public class RequestUtil {
return requests.stream().filter(requestType::isInstance).map(requestType::cast).toList();
}
public static Optional<List<Deposit>> getDepositRequests(final Optional<List<Request>> requests) {
return requests.map(r -> filterRequestsOfType(r, Deposit.class));
}
public static Optional<List<WithdrawalRequest>> getWithdrawalRequests(
final Optional<List<Request>> requests) {
return requests.map(r -> filterRequestsOfType(r, WithdrawalRequest.class));
}
/**
* Combines two optional lists of requests into a single optional list.
*
* @param maybeDeposits Optional list of deposit requests.
* @param maybeWithdrawalRequest Optional list of withdrawal requests.
* @return An Optional containing the combined list of requests, or an empty Optional if both
* inputs are empty.
*/
public static Optional<List<Request>> combine(
final Optional<List<Request>> maybeDeposits,
final Optional<List<Request>> maybeWithdrawalRequest) {

View File

@@ -41,6 +41,10 @@ public class RequestsValidatorCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(RequestsValidatorCoordinator.class);
private final ImmutableSortedMap<RequestType, RequestValidator> validators;
public static RequestsValidatorCoordinator empty() {
return new Builder().build();
}
/**
* Constructs a new RequestsDelegateValidator with a mapping of request types to their respective
* validators.

View File

@@ -25,7 +25,7 @@ import java.util.Optional;
public class WithdrawalRequestProcessor implements RequestProcessor {
@Override
public Optional<List<Request>> process(
public Optional<List<? extends Request>> process(
final MutableWorldState mutableWorldState,
final List<TransactionReceipt> transactionReceipts) {
@@ -33,6 +33,6 @@ public class WithdrawalRequestProcessor implements RequestProcessor {
WithdrawalRequestContractHelper.popWithdrawalRequestsFromQueue(mutableWorldState).stream()
.toList();
return Optional.of(withdrawalRequests.stream().map(r -> (Request) r).toList());
return Optional.of(withdrawalRequests);
}
}

View File

@@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.mainnet.requests;
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Request;
@@ -45,7 +47,7 @@ public class WithdrawalRequestValidator implements RequestValidator {
block
.getBody()
.getRequests()
.map(requests -> RequestUtil.filterRequestsOfType(requests, WithdrawalRequest.class))
.flatMap(requests -> getWithdrawalRequests(Optional.of(requests)))
.orElse(Collections.emptyList());
// TODO Do we need to allow for customization? (e.g. if the value changes in the next fork)
@@ -74,7 +76,8 @@ public class WithdrawalRequestValidator implements RequestValidator {
@Override
public boolean validate(
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) {
var withdrawalRequests = RequestUtil.filterRequestsOfType(requests, WithdrawalRequest.class);
var withdrawalRequests =
getWithdrawalRequests(Optional.of(requests)).orElse(Collections.emptyList());
return validateWithdrawalRequestsInBlock(block, withdrawalRequests);
}

View File

@@ -114,7 +114,7 @@ class BlockImportExceptionHandlingTest {
when(protocolContext.getWorldStateArchive()).thenReturn(worldStateArchive);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getRequestsValidatorCoordinator())
.thenReturn(new RequestsValidatorCoordinator.Builder().build());
.thenReturn(RequestsValidatorCoordinator.empty());
when(protocolSpec.getBlockHashProcessor()).thenReturn(new FrontierBlockHashProcessor());
mainnetBlockValidator =
new MainnetBlockValidator(

View File

@@ -27,24 +27,35 @@ import org.apache.tuweni.units.bigints.UInt64;
import org.junit.jupiter.api.Test;
class DepositEncoderTest {
private final String expectedDepositEncodedBytes =
"f8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501";
final Deposit deposit =
new Deposit(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(
"0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"),
GWei.of(32000000000L),
BLSSignature.fromHexString(
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.ONE);
@Test
void shouldEncodeDeposit() {
final Deposit deposit =
new Deposit(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(
"0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"),
GWei.of(32000000000L),
BLSSignature.fromHexString(
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.ONE);
final Bytes encoded = DepositEncoder.encodeOpaqueBytes(deposit);
assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedDepositEncodedBytes));
}
@Test
void shouldEncodeDepositRequest() {
final Bytes encoded = RequestEncoder.encodeOpaqueBytes(deposit);
// Request encoding is Request = RequestType ++ RequestData
assertThat(encoded)
.isEqualTo(
Bytes.fromHexString(
"0xf8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501"));
String.format(
"0x%02X%s",
deposit.getType().getSerializedType(), expectedDepositEncodedBytes)));
}
}

View File

@@ -25,20 +25,31 @@ import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
class WithdrawalRequestEncoderTest {
private final String expectedEncodedBytes =
"f84794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e05";
final WithdrawalRequest withdrawalRequest =
new WithdrawalRequest(
Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"),
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
GWei.of(5));
@Test
void shouldEncodeWithdrawalRequest() {
final WithdrawalRequest withdrawalRequest =
new WithdrawalRequest(
Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"),
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
GWei.of(5));
final Bytes encoded = WithdrawalRequestEncoder.encodeOpaqueBytes(withdrawalRequest);
assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedEncodedBytes));
}
@Test
void shouldEncodeRequest() {
final Bytes encoded = RequestEncoder.encodeOpaqueBytes(withdrawalRequest);
assertThat(encoded)
.isEqualTo(
Bytes.fromHexString(
"0xf84794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e05"));
String.format(
"0x%02X%s",
withdrawalRequest.getType().getSerializedType(), expectedEncodedBytes)));
}
}

View File

@@ -70,7 +70,7 @@ abstract class AbstractBlockProcessorTest {
lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
lenient()
.when(protocolSpec.getRequestsValidatorCoordinator())
.thenReturn(new RequestsValidatorCoordinator.Builder().build());
.thenReturn(RequestsValidatorCoordinator.empty());
lenient()
.when(protocolSpec.getBlockHashProcessor())
.thenReturn(new FrontierBlockHashProcessor());

View File

@@ -51,7 +51,7 @@ public class MainnetBlockProcessorTest extends AbstractBlockProcessorTest {
public void setup() {
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getRequestsValidatorCoordinator())
.thenReturn(new RequestsValidatorCoordinator.Builder().build());
.thenReturn(RequestsValidatorCoordinator.empty());
when(protocolSpec.getBlockHashProcessor()).thenReturn(new FrontierBlockHashProcessor());
}