Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change requests to use flat encoding #7771

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
49a4411
rename requestsRoot to requestsHash
jframe Oct 9, 2024
cdc9bd5
generalised requests flat encoding and engine api changes
jframe Oct 14, 2024
cee6abc
javadoc
jframe Oct 14, 2024
8f346f4
get tests passing
jframe Oct 15, 2024
4e12780
get tests passing
jframe Oct 15, 2024
42e6865
Merge remote-tracking branch 'upstream/main' into 7685_flat_encoding
jframe Oct 15, 2024
f0d5a24
clean code
jframe Oct 15, 2024
0424317
change requests to single requestData for each requestType
jframe Oct 15, 2024
86f5049
fix PoWBlockCreatorTest after requests data type change
jframe Oct 15, 2024
722823e
don't return request type in getPayload result
jframe Oct 15, 2024
24a33e7
include requests in t8n response
jframe Oct 16, 2024
24de847
update contract addresses for consolidation requests and withdrawal r…
jframe Oct 16, 2024
532cb9d
fix requestHash calculation
jframe Oct 16, 2024
079bcfd
Ensure that execution requests always return a response
jframe Oct 16, 2024
eff46b0
revert changes to evm tool spec tests
jframe Oct 17, 2024
1fdf0db
clean up
jframe Oct 17, 2024
9c2a623
replace AbstractSystemCallRequestProcessor to concrete class and remo…
jframe Oct 17, 2024
afd9023
spotless
jframe Oct 17, 2024
20ca19e
update evmtool tests for 7685 changes
jframe Oct 17, 2024
3ee1b31
use empty requests hash prague fork at genesis
jframe Oct 17, 2024
21b7aae
review suggestions
jframe Oct 17, 2024
7574c84
engine API validation
jframe Oct 18, 2024
ac812b2
Merge remote-tracking branch 'upstream/main' into 7685_flat_encoding
jframe Oct 18, 2024
95d1606
update plugin API hash
jframe Oct 18, 2024
4c62cae
fix GenesisStateTest
jframe Oct 18, 2024
985f4bf
update prague engine API ATs with updated contracts
jframe Oct 22, 2024
f298d46
update prague ATs using PragueAcceptanceTestHelper to use executionRe…
jframe Oct 22, 2024
9114f4d
Merge branch 'main' into 7685_flat_encoding
jframe Oct 22, 2024
3d4f2ec
Change BlockHeader isEmpty check to use the empty requests hash as pa…
jframe Oct 22, 2024
f1b412d
cleanup
jframe Oct 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void testBuildRlpFromHeader() {
new BlockHeaderTestFixture()
.timestamp(1710338135 + 1)
.baseFeePerGas(Wei.of(1000))
.requestsRoot(Hash.ZERO)
.requestsHash(Hash.ZERO)
.withdrawalsRoot(Hash.ZERO)
.blobGasUsed(500L)
.excessBlobGas(BlobGas.of(500L))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockValueCalculator;
import org.hyperledger.besu.ethereum.core.BlockWithReceipts;
import org.hyperledger.besu.ethereum.core.Request;

import java.util.List;
import java.util.Optional;

/** Wrapper for payload plus extra info. */
public class PayloadWrapper {
private final PayloadIdentifier payloadIdentifier;
private final BlockWithReceipts blockWithReceipts;
private final Wei blockValue;
private final Optional<List<Request>> requests;

/**
* Construct a wrapper with the following fields.
Expand All @@ -32,10 +37,13 @@ public class PayloadWrapper {
* @param blockWithReceipts Block with receipts
*/
public PayloadWrapper(
final PayloadIdentifier payloadIdentifier, final BlockWithReceipts blockWithReceipts) {
final PayloadIdentifier payloadIdentifier,
final BlockWithReceipts blockWithReceipts,
final Optional<List<Request>> requests) {
this.blockWithReceipts = blockWithReceipts;
this.payloadIdentifier = payloadIdentifier;
this.blockValue = BlockValueCalculator.calculateBlockValue(blockWithReceipts);
this.requests = requests;
}

/**
Expand Down Expand Up @@ -64,4 +72,13 @@ public PayloadIdentifier payloadIdentifier() {
public BlockWithReceipts blockWithReceipts() {
return blockWithReceipts;
}

/**
* Get the requests
*
* @return requests
*/
public Optional<List<Request>> requests() {
return requests;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
import org.hyperledger.besu.ethereum.BlockProcessingResult;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult;
Expand Down Expand Up @@ -302,7 +303,9 @@ public PayloadIdentifier preparePayload(
if (result.isSuccessful()) {
mergeContext.putPayloadById(
new PayloadWrapper(
payloadIdentifier, new BlockWithReceipts(emptyBlock, result.getReceipts())));
payloadIdentifier,
new BlockWithReceipts(emptyBlock, result.getReceipts()),
result.getYield().flatMap(BlockProcessingOutputs::getRequests)));
LOG.info(
"Start building proposals for block {} identified by {}",
emptyBlock.getHeader().getNumber(),
Expand Down Expand Up @@ -469,7 +472,9 @@ private void evaluateNewBlock(

mergeContext.putPayloadById(
new PayloadWrapper(
payloadIdentifier, new BlockWithReceipts(bestBlock, resultBest.getReceipts())));
payloadIdentifier,
new BlockWithReceipts(bestBlock, resultBest.getReceipts()),
resultBest.getYield().flatMap(BlockProcessingOutputs::getRequests)));
LOG.atDebug()
.setMessage(
"Successfully built block {} for proposal identified by {}, with {} transactions, in {}ms")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public class ProposalTest {
new BlockBody(
Collections.emptyList(),
Collections.emptyList(),
Optional.of(Collections.emptyList()),
Optional.empty()));
Optional.of(Collections.emptyList())));

@Test
public void canRoundTripProposalMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ public enum JsonRpcResponseKey {
TRANSACTION_ROOT,
BASEFEE,
WITHDRAWALS_ROOT,
REQUESTS_ROOT
REQUESTS_HASH
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.OMMERS_HASH;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.PARENT_HASH;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.RECEIPTS_ROOT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.REQUESTS_ROOT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.REQUESTS_HASH;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.SIZE;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.STATE_ROOT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.TIMESTAMP;
Expand Down Expand Up @@ -104,8 +104,8 @@ public JsonRpcResponse response(
final int size = unsignedInt(values.get(SIZE));
final Hash withdrawalsRoot =
values.containsKey(WITHDRAWALS_ROOT) ? hash(values.get(WITHDRAWALS_ROOT)) : null;
final Hash requestsRoot =
values.containsKey(REQUESTS_ROOT) ? hash(values.get(REQUESTS_ROOT)) : null;
final Hash requestsHash =
values.containsKey(REQUESTS_HASH) ? hash(values.get(REQUESTS_HASH)) : null;
final List<JsonNode> ommers = new ArrayList<>();

final BlockHeader header =
Expand All @@ -130,7 +130,7 @@ public JsonRpcResponse response(
null, // ToDo 4844: set with the value of blob_gas_used field
null, // ToDo 4844: set with the value of excess_blob_gas field
null, // TODO 4788: set with the value of the parent beacon block root field
requestsRoot,
requestsHash,
blockHeaderFunctions);

return new JsonRpcSuccessResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public JsonRpcResponse process(
case INVALID_PROPOSAL_PARAMS:
case INVALID_REMOTE_CAPABILITIES_PARAMS:
case INVALID_REWARD_PERCENTILES_PARAMS:
case INVALID_REQUESTS_PARAMS:
case INVALID_SEALER_ID_PARAMS:
case INVALID_STORAGE_KEYS_PARAMS:
case INVALID_SUBSCRIPTION_PARAMS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,23 @@
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.INVALID_BLOCK_HASH;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.SYNCING;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod.EngineStatus.VALID;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getConsolidationRequestValidator;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getDepositRequestValidator;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.RequestValidatorProvider.getWithdrawalRequestValidator;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.WithdrawalsValidatorProvider.getWithdrawalsValidator;

import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.RequestType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.BlockProcessingResult;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ConsolidationRequestParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalRequestParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
Expand All @@ -64,7 +59,6 @@
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.plugin.services.exception.StorageException;
Expand All @@ -75,6 +69,7 @@
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import io.vertx.core.Vertx;
import io.vertx.core.json.Json;
Expand Down Expand Up @@ -141,8 +136,22 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
final Optional<Bytes32> maybeParentBeaconBlockRoot =
maybeParentBeaconBlockRootParam.map(Bytes32::fromHexString);

final Optional<List<String>> maybeRequestsParam;
try {
maybeRequestsParam = requestContext.getOptionalList(3, String.class);
} catch (JsonRpcParameterException e) {
throw new InvalidJsonRpcRequestException(
"Invalid execution request parameters (index 3)",
RpcErrorType.INVALID_REQUESTS_PARAMS,
e);
}

final ValidationResult<RpcErrorType> parameterValidationResult =
validateParameters(blockParam, maybeVersionedHashParam, maybeParentBeaconBlockRootParam);
validateParameters(
blockParam,
maybeVersionedHashParam,
maybeParentBeaconBlockRootParam,
maybeRequestsParam);
if (!parameterValidationResult.isValid()) {
return new JsonRpcErrorResponse(reqId, parameterValidationResult);
}
Expand Down Expand Up @@ -183,44 +192,19 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
return new JsonRpcErrorResponse(reqId, RpcErrorType.INVALID_WITHDRAWALS_PARAMS);
}

final Optional<List<Request>> maybeDepositRequests =
Optional.ofNullable(blockParam.getDepositRequests())
.map(ds -> ds.stream().map(DepositRequestParameter::toDeposit).collect(toList()));
if (!getDepositRequestValidator(
protocolSchedule.get(), blockParam.getTimestamp(), blockParam.getBlockNumber())
.validateParameter(maybeDepositRequests)) {
return new JsonRpcErrorResponse(reqId, RpcErrorType.INVALID_DEPOSIT_REQUEST_PARAMS);
}

final Optional<List<Request>> maybeWithdrawalRequests =
Optional.ofNullable(blockParam.getWithdrawalRequests())
.map(
withdrawalRequest ->
withdrawalRequest.stream()
.map(WithdrawalRequestParameter::toWithdrawalRequest)
.collect(toList()));
if (!getWithdrawalRequestValidator(
protocolSchedule.get(), blockParam.getTimestamp(), blockParam.getBlockNumber())
.validateParameter(maybeWithdrawalRequests)) {
return new JsonRpcErrorResponse(reqId, RpcErrorType.INVALID_WITHDRAWALS_PARAMS);
}

final Optional<List<Request>> maybeConsolidationRequests =
Optional.ofNullable(blockParam.getConsolidationRequests())
.map(
consolidationRequest ->
consolidationRequest.stream()
.map(ConsolidationRequestParameter::toConsolidationRequest)
.collect(toList()));
if (!getConsolidationRequestValidator(
protocolSchedule.get(), blockParam.getTimestamp(), blockParam.getBlockNumber())
.validateParameter(maybeConsolidationRequests)) {
return new JsonRpcErrorResponse(reqId, RpcErrorType.INVALID_CONSOLIDATION_REQUEST_PARAMS);
final Optional<List<Request>> maybeRequests;
try {
maybeRequests = extractRequests(maybeRequestsParam);
} catch (RuntimeException ex) {
return respondWithInvalid(
reqId,
blockParam,
mergeCoordinator.getLatestValidAncestor(blockParam.getParentHash()).orElse(null),
INVALID,
"Invalid requests");
}

Optional<List<Request>> maybeRequests =
RequestUtil.combine(
maybeDepositRequests, maybeWithdrawalRequests, maybeConsolidationRequests);
// TODO JF validate requests

if (mergeContext.get().isSyncing()) {
LOG.debug("We are syncing");
Expand Down Expand Up @@ -289,7 +273,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
? null
: BlobGas.fromHexString(blockParam.getExcessBlobGas()),
maybeParentBeaconBlockRoot.orElse(null),
maybeRequests.map(BodyValidation::requestsRoot).orElse(null),
maybeRequests.map(BodyValidation::requestsHash).orElse(null),
headerFunctions);

// ensure the block hash matches the blockParam hash
Expand Down Expand Up @@ -351,8 +335,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)

final var block =
new Block(
newBlockHeader,
new BlockBody(transactions, Collections.emptyList(), maybeWithdrawals, maybeRequests));
newBlockHeader, new BlockBody(transactions, Collections.emptyList(), maybeWithdrawals));

if (maybeParentHeader.isEmpty()) {
LOG.atDebug()
Expand Down Expand Up @@ -466,7 +449,8 @@ protected EngineStatus getInvalidBlockHashStatus() {
protected ValidationResult<RpcErrorType> validateParameters(
final EnginePayloadParameter parameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<String> maybeBeaconBlockRootParam) {
final Optional<String> maybeBeaconBlockRootParam,
final Optional<List<String>> maybeRequestsParam) {
return ValidationResult.valid();
}

Expand Down Expand Up @@ -562,6 +546,18 @@ private Optional<List<VersionedHash>> extractVersionedHashes(
.collect(Collectors.toList()));
}

private Optional<List<Request>> extractRequests(final Optional<List<String>> maybeRequestsParam) {
if (maybeRequestsParam.isEmpty()) {
return Optional.empty();
}

return maybeRequestsParam.map(
requests ->
IntStream.range(0, requests.size())
.mapToObj(i -> new Request(RequestType.of(i), Bytes.fromHexString(requests.get(i))))
.collect(Collectors.toList()));
}

private void logImportedBlockInfo(final Block block, final int blobCount, final double timeInS) {
final StringBuilder message = new StringBuilder();
message.append("Imported #%,d / %d tx");
Expand All @@ -572,10 +568,6 @@ private void logImportedBlockInfo(final Block block, final int blobCount, final
message.append(" / %d ws");
messageArgs.add(block.getBody().getWithdrawals().get().size());
}
if (block.getBody().getRequests().isPresent()) {
message.append(" / %d rs");
messageArgs.add(block.getBody().getRequests().get().size());
}
message.append(" / %d blobs / base fee %s / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d");
messageArgs.addAll(
List.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public String getName() {
protected ValidationResult<RpcErrorType> validateParameters(
final EnginePayloadParameter payloadParameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<String> maybeBeaconBlockRootParam) {
final Optional<String> maybeBeaconBlockRootParam,
final Optional<List<String>> maybeRequestsParam) {
if (payloadParameter.getBlobGasUsed() != null) {
return ValidationResult.invalid(
RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public String getName() {
protected ValidationResult<RpcErrorType> validateParameters(
final EnginePayloadParameter payloadParameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<String> maybeBeaconBlockRootParam) {
final Optional<String> maybeBeaconBlockRootParam,
final Optional<List<String>> maybeRequestsParam) {
if (payloadParameter.getBlobGasUsed() == null) {
return ValidationResult.invalid(
RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public String getName() {
protected ValidationResult<RpcErrorType> validateParameters(
final EnginePayloadParameter payloadParameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<String> maybeBeaconBlockRootParam) {
final Optional<String> maybeBeaconBlockRootParam,
final Optional<List<String>> maybeRequestsParam) {
if (payloadParameter.getBlobGasUsed() == null) {
return ValidationResult.invalid(
RpcErrorType.INVALID_BLOB_GAS_USED_PARAMS, "Missing blob gas used field");
Expand All @@ -69,8 +70,9 @@ protected ValidationResult<RpcErrorType> validateParameters(
return ValidationResult.invalid(
RpcErrorType.INVALID_PARENT_BEACON_BLOCK_ROOT_PARAMS,
"Missing parent beacon block root field");
} else if (payloadParameter.getDepositRequests() == null) {
return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Missing deposit field");
} else if (maybeRequestsParam.isEmpty()) {
return ValidationResult.invalid(
RpcErrorType.INVALID_REQUESTS_PARAMS, "Missing execution requests field");
} else {
return ValidationResult.valid();
}
Expand Down
Loading
Loading