mirror of https://github.com/hyperledger/besu
EIP-7251 add consolidation request type (#7266)
* add request type for consolidations, encoder, decoder and tests * added raw tx for consolidation * add consolidation reqs to EngineGetPayloadResultV4 * set storage slot value to 0 initially and value for tx * updates plugin api Signed-off-by: Justin Florentine <justin+github@florentine.us> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: Justin Florentine <justin+github@florentine.us> Co-authored-by: Justin Florentine <justin+github@florentine.us>pull/7330/head
parent
23123719fb
commit
223f1bc3bb
File diff suppressed because one or more lines are too long
@ -0,0 +1,43 @@ |
||||
{ |
||||
"request": { |
||||
"jsonrpc": "2.0", |
||||
"method": "eth_getBlockByNumber", |
||||
"params": [ |
||||
"0x00", true |
||||
], |
||||
"id": 67 |
||||
}, |
||||
"response": { |
||||
"jsonrpc": "2.0", |
||||
"id": 67, |
||||
"result": { |
||||
"number": "0x0", |
||||
"hash" : "0x38d7daa68e8bac41a0a237b7cbfcef480cb9bd9adc7b282d7b0d23ff4eb8d6e5", |
||||
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
"nonce" : "0x0000000000000042", |
||||
"sha3Uncles" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
"logsBloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
"transactionsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", |
||||
"stateRoot" : "0x3ed8435adb5f3526144e6babdd3fc8c661a86097cf7e743441b41fda096fc4dd", |
||||
"receiptsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", |
||||
"miner" : "0x0000000000000000000000000000000000000000", |
||||
"difficulty" : "0x400000000", |
||||
"totalDifficulty" : "0x400000000", |
||||
"extraData" : "0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
"baseFeePerGas" : "0x7", |
||||
"size" : "0x2ba", |
||||
"gasLimit" : "0x1c9c380", |
||||
"gasUsed" : "0x0", |
||||
"timestamp" : "0x0", |
||||
"uncles" : [ ], |
||||
"transactions" : [ ], |
||||
"withdrawalsRoot" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", |
||||
"withdrawals" : [ ], |
||||
"blobGasUsed" : "0x0", |
||||
"excessBlobGas" : "0x0", |
||||
"parentBeaconBlockRoot" : "0x0000000000000000000000000000000000000000000000000000000000000000" |
||||
} |
||||
}, |
||||
"statusCode": 200 |
||||
} |
@ -0,0 +1,14 @@ |
||||
{ |
||||
"request": { |
||||
"jsonrpc": "2.0", |
||||
"method": "eth_sendRawTransaction", |
||||
"params": ["0xf8c80185e8d4a51000832dc6c09400b42dbf2194e931e80326d950320f7d9dbeac0201b860fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe822fe0a05b88b593926d340f448918ef1c6263356c37f2434774e0fdb1cb9d90cfa5a23ba003a86aac4adb774181ba51eda17efb5fbed99ad57895e6eb56ccdf508a88a7cc"], |
||||
"id": 67 |
||||
}, |
||||
"response": { |
||||
"jsonrpc": "2.0", |
||||
"id": 67, |
||||
"result": "0xa4252f576c4e16cb020f86f8a30d4fa990ee0cbfc84198a6d0eb118dd2f8b72d" |
||||
}, |
||||
"statusCode": 200 |
||||
} |
@ -0,0 +1,102 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator; |
||||
import com.fasterxml.jackson.annotation.JsonGetter; |
||||
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
|
||||
public class ConsolidationRequestParameter { |
||||
|
||||
private final String sourceAddress; |
||||
private final String sourcePubkey; |
||||
private final String targetPubkey; |
||||
|
||||
@JsonCreator |
||||
public ConsolidationRequestParameter( |
||||
@JsonProperty("sourceAddress") final String sourceAddress, |
||||
@JsonProperty("sourcePubkey") final String sourcePubkey, |
||||
@JsonProperty("targetPubkey") final String targetPubkey) { |
||||
this.sourceAddress = sourceAddress; |
||||
this.sourcePubkey = sourcePubkey; |
||||
this.targetPubkey = targetPubkey; |
||||
} |
||||
|
||||
public static ConsolidationRequestParameter fromConsolidationRequest( |
||||
final ConsolidationRequest consolidationRequest) { |
||||
return new ConsolidationRequestParameter( |
||||
consolidationRequest.getSourceAddress().toHexString(), |
||||
consolidationRequest.getSourcePubkey().toHexString(), |
||||
consolidationRequest.getTargetPubkey().toHexString()); |
||||
} |
||||
|
||||
public ConsolidationRequest toConsolidationRequest() { |
||||
return new ConsolidationRequest( |
||||
Address.fromHexString(sourceAddress), |
||||
BLSPublicKey.fromHexString(sourcePubkey), |
||||
BLSPublicKey.fromHexString(targetPubkey)); |
||||
} |
||||
|
||||
@JsonGetter |
||||
public String getSourceAddress() { |
||||
return sourceAddress; |
||||
} |
||||
|
||||
@JsonGetter |
||||
public String getSourcePubKey() { |
||||
return sourcePubkey; |
||||
} |
||||
|
||||
@JsonGetter |
||||
public String getTargetPubKey() { |
||||
return targetPubkey; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object o) { |
||||
if (this == o) return true; |
||||
if (o == null || getClass() != o.getClass()) return false; |
||||
final ConsolidationRequestParameter that = (ConsolidationRequestParameter) o; |
||||
return Objects.equals(sourceAddress, that.sourceAddress) |
||||
&& Objects.equals(sourcePubkey, that.sourcePubkey) |
||||
&& Objects.equals(targetPubkey, that.targetPubkey); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return Objects.hash(sourceAddress, sourcePubkey, targetPubkey); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ConsolidationRequestParameter{" |
||||
+ "sourceAddress='" |
||||
+ sourceAddress |
||||
+ '\'' |
||||
+ ", sourcePubkey='" |
||||
+ sourcePubkey |
||||
+ '\'' |
||||
+ ", targetPubkey='" |
||||
+ targetPubkey |
||||
+ '\'' |
||||
+ '}'; |
||||
} |
||||
} |
@ -0,0 +1,90 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.datatypes.PublicKey; |
||||
import org.hyperledger.besu.datatypes.RequestType; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
public class ConsolidationRequest extends Request |
||||
implements org.hyperledger.besu.plugin.data.ConsolidationRequest { |
||||
|
||||
private final Address sourceAddress; |
||||
private final BLSPublicKey sourcePubkey; |
||||
private final BLSPublicKey targetPubkey; |
||||
|
||||
public ConsolidationRequest( |
||||
final Address sourceAddress, |
||||
final BLSPublicKey sourcePubkey, |
||||
final BLSPublicKey targetPubkey) { |
||||
this.sourceAddress = sourceAddress; |
||||
this.sourcePubkey = sourcePubkey; |
||||
this.targetPubkey = targetPubkey; |
||||
} |
||||
|
||||
@Override |
||||
public RequestType getType() { |
||||
return RequestType.CONSOLIDATION; |
||||
} |
||||
|
||||
@Override |
||||
public Address getSourceAddress() { |
||||
return sourceAddress; |
||||
} |
||||
|
||||
@Override |
||||
public PublicKey getSourcePubkey() { |
||||
return sourcePubkey; |
||||
} |
||||
|
||||
@Override |
||||
public PublicKey getTargetPubkey() { |
||||
return targetPubkey; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ConsolidationRequest{" |
||||
+ "sourceAddress=" |
||||
+ sourceAddress |
||||
+ " sourcePubkey=" |
||||
+ sourcePubkey |
||||
+ " targetPubkey=" |
||||
+ targetPubkey |
||||
+ '}'; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(final Object o) { |
||||
if (this == o) { |
||||
return true; |
||||
} |
||||
if (o == null || getClass() != o.getClass()) { |
||||
return false; |
||||
} |
||||
final ConsolidationRequest that = (ConsolidationRequest) o; |
||||
return Objects.equals(sourceAddress, that.sourceAddress) |
||||
&& Objects.equals(sourcePubkey, that.sourcePubkey) |
||||
&& Objects.equals(targetPubkey, that.targetPubkey); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return Objects.hash(sourceAddress, sourcePubkey, targetPubkey); |
||||
} |
||||
} |
@ -0,0 +1,40 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
import org.hyperledger.besu.ethereum.rlp.RLP; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class ConsolidationRequestDecoder { |
||||
|
||||
public static ConsolidationRequest decode(final RLPInput rlpInput) { |
||||
rlpInput.enterList(); |
||||
final Address sourceAddress = Address.readFrom(rlpInput); |
||||
final BLSPublicKey sourcePublicKey = BLSPublicKey.readFrom(rlpInput); |
||||
final BLSPublicKey targetPublicKey = BLSPublicKey.readFrom(rlpInput); |
||||
rlpInput.leaveList(); |
||||
|
||||
return new ConsolidationRequest(sourceAddress, sourcePublicKey, targetPublicKey); |
||||
} |
||||
|
||||
public static ConsolidationRequest decodeOpaqueBytes(final Bytes input) { |
||||
return decode(RLP.input(input)); |
||||
} |
||||
} |
@ -0,0 +1,60 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.datatypes.RequestType; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
import org.hyperledger.besu.ethereum.core.Request; |
||||
import org.hyperledger.besu.ethereum.rlp.RLP; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class ConsolidationRequestEncoder { |
||||
|
||||
/** |
||||
* Encodes a Request into RLP format if it is a ConsolidationRequest. |
||||
* |
||||
* @param request The Request to encode, which must be a ConsolidationRequest. |
||||
* @param rlpOutput The RLPOutput to write the encoded data to. |
||||
* @throws IllegalArgumentException if the provided request is not a ConsolidationRequest. |
||||
*/ |
||||
public static void encode(final Request request, final RLPOutput rlpOutput) { |
||||
if (!request.getType().equals(RequestType.CONSOLIDATION)) { |
||||
throw new IllegalArgumentException( |
||||
"The provided request is not of type ConsolidationRequest."); |
||||
} |
||||
encodeConsolidationRequest((ConsolidationRequest) request, rlpOutput); |
||||
} |
||||
|
||||
/** |
||||
* Encodes the details of a ConsolidationRequest into RLP format. |
||||
* |
||||
* @param consolidationRequest The ConsolidationRequest to encode. |
||||
* @param rlpOutput The RLPOutput to write the encoded data to. |
||||
*/ |
||||
private static void encodeConsolidationRequest( |
||||
final ConsolidationRequest consolidationRequest, final RLPOutput rlpOutput) { |
||||
rlpOutput.startList(); |
||||
rlpOutput.writeBytes(consolidationRequest.getSourceAddress()); |
||||
rlpOutput.writeBytes(consolidationRequest.getSourcePubkey()); |
||||
rlpOutput.writeBytes(consolidationRequest.getTargetPubkey()); |
||||
rlpOutput.endList(); |
||||
} |
||||
|
||||
public static Bytes encodeOpaqueBytes(final Request consolidationRequest) { |
||||
return RLP.encode(rlpOutput -> encode(consolidationRequest, rlpOutput)); |
||||
} |
||||
} |
@ -0,0 +1,68 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.mainnet.requests; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class ConsolidationRequestProcessor |
||||
extends AbstractSystemCallRequestProcessor<ConsolidationRequest> { |
||||
public static final Address CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS = |
||||
Address.fromHexString("0x00b42dbF2194e931E80326D950320f7d9Dbeac02"); |
||||
|
||||
private static final int ADDRESS_BYTES = 20; |
||||
private static final int PUBLIC_KEY_BYTES = 48; |
||||
private static final int CONSOLIDATION_REQUEST_BYTES_SIZE = |
||||
ADDRESS_BYTES + PUBLIC_KEY_BYTES + PUBLIC_KEY_BYTES; |
||||
|
||||
/** |
||||
* Gets the call address for consolidation requests. |
||||
* |
||||
* @return The call address. |
||||
*/ |
||||
@Override |
||||
protected Address getCallAddress() { |
||||
return CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS; |
||||
} |
||||
|
||||
/** |
||||
* Gets the size of the bytes representing a single consolidation request. |
||||
* |
||||
* @return The size of the bytes representing a single consolidation request. |
||||
*/ |
||||
@Override |
||||
protected int getRequestBytesSize() { |
||||
return CONSOLIDATION_REQUEST_BYTES_SIZE; |
||||
} |
||||
|
||||
/** |
||||
* Parses a single consolidation request from the provided bytes. |
||||
* |
||||
* @param requestBytes The bytes representing a single consolidation request. |
||||
* @return A parsed {@link ConsolidationRequest} object. |
||||
*/ |
||||
@Override |
||||
protected ConsolidationRequest parseRequest(final Bytes requestBytes) { |
||||
final Address sourceAddress = Address.wrap(requestBytes.slice(0, ADDRESS_BYTES)); |
||||
final BLSPublicKey sourcePublicKey = |
||||
BLSPublicKey.wrap(requestBytes.slice(ADDRESS_BYTES, PUBLIC_KEY_BYTES)); |
||||
final BLSPublicKey targetPublicKey = |
||||
BLSPublicKey.wrap(requestBytes.slice(ADDRESS_BYTES + PUBLIC_KEY_BYTES, PUBLIC_KEY_BYTES)); |
||||
return new ConsolidationRequest(sourceAddress, sourcePublicKey, targetPublicKey); |
||||
} |
||||
} |
@ -0,0 +1,92 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.mainnet.requests; |
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getConsolidationRequests; |
||||
|
||||
import org.hyperledger.besu.datatypes.Hash; |
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
import org.hyperledger.besu.ethereum.core.Request; |
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
public class ConsolidationRequestValidator implements RequestValidator { |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConsolidationRequestValidator.class); |
||||
|
||||
public static final int MAX_CONSOLIDATION_REQUESTS_PER_BLOCK = 1; |
||||
|
||||
private boolean validateConsolidationRequestParameter( |
||||
final Optional<List<ConsolidationRequest>> consolidationRequests) { |
||||
return consolidationRequests.isPresent(); |
||||
} |
||||
|
||||
private boolean validateConsolidationRequestsInBlock( |
||||
final Block block, final List<ConsolidationRequest> consolidationRequests) { |
||||
final Hash blockHash = block.getHash(); |
||||
|
||||
final List<ConsolidationRequest> consolidationRequestsInBlock = |
||||
block |
||||
.getBody() |
||||
.getRequests() |
||||
.flatMap(requests -> getConsolidationRequests(Optional.of(requests))) |
||||
.orElse(Collections.emptyList()); |
||||
|
||||
if (consolidationRequestsInBlock.size() > MAX_CONSOLIDATION_REQUESTS_PER_BLOCK) { |
||||
LOG.warn( |
||||
"Block {} has more than the allowed maximum number of consolidation requests", blockHash); |
||||
return false; |
||||
} |
||||
|
||||
// Validate ConsolidationRequests
|
||||
final boolean expectedConsolidationRequestMatch = |
||||
consolidationRequests.equals(consolidationRequestsInBlock); |
||||
if (!expectedConsolidationRequestMatch) { |
||||
LOG.warn( |
||||
"Block {} has a mismatch between block consolidations and RPC consolidation requests (in_block = {}, " |
||||
+ "expected = {})", |
||||
blockHash, |
||||
consolidationRequestsInBlock, |
||||
consolidationRequests); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean validate( |
||||
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) { |
||||
var consolidationRequests = |
||||
getConsolidationRequests(Optional.of(requests)).orElse(Collections.emptyList()); |
||||
return validateConsolidationRequestsInBlock(block, consolidationRequests); |
||||
} |
||||
|
||||
@Override |
||||
public boolean validateParameter(final Optional<List<Request>> request) { |
||||
if (request.isEmpty()) { |
||||
return true; |
||||
} |
||||
var consolidationRequests = |
||||
RequestUtil.filterRequestsOfType(request.get(), ConsolidationRequest.class); |
||||
return validateConsolidationRequestParameter(Optional.of(consolidationRequests)); |
||||
} |
||||
} |
@ -0,0 +1,46 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
import org.hyperledger.besu.ethereum.core.Request; |
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; |
||||
import org.hyperledger.besu.ethereum.rlp.RLP; |
||||
|
||||
import org.assertj.core.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
class ConsolidationRequestDecoderTest { |
||||
|
||||
@Test |
||||
public void shouldDecodeWithdrawalRequest() { |
||||
final ConsolidationRequest expectedConsolidationRequest = |
||||
new ConsolidationRequest( |
||||
Address.fromHexString("0x814FaE9f487206471B6B0D713cD51a2D35980000"), |
||||
BLSPublicKey.fromHexString( |
||||
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), |
||||
BLSPublicKey.fromHexString( |
||||
"0xa09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e")); |
||||
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput(); |
||||
expectedConsolidationRequest.writeTo(out); |
||||
|
||||
final Request decodedWithdrawalRequest = RequestDecoder.decode(RLP.input(out.encoded())); |
||||
|
||||
Assertions.assertThat(decodedWithdrawalRequest).isEqualTo(expectedConsolidationRequest); |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
class ConsolidationRequestEncoderTest { |
||||
|
||||
private final String expectedEncodedBytes = |
||||
"f87794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416eb0a09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e"; |
||||
|
||||
final ConsolidationRequest consolidationRequest = |
||||
new ConsolidationRequest( |
||||
Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"), |
||||
BLSPublicKey.fromHexString( |
||||
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), |
||||
BLSPublicKey.fromHexString( |
||||
"0xa09a4a15bf67b328c9b101d09e5c6ee6672978f7ad9ef0d9e2c457aee99223555d8601f0cb3bcc4ce1af9864779a416e")); |
||||
|
||||
@Test |
||||
void shouldEncodeConsolidationRequest() { |
||||
final Bytes encoded = ConsolidationRequestEncoder.encodeOpaqueBytes(consolidationRequest); |
||||
assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedEncodedBytes)); |
||||
} |
||||
|
||||
@Test |
||||
void shouldEncodeRequest() { |
||||
final Bytes encoded = RequestEncoder.encodeOpaqueBytes(consolidationRequest); |
||||
assertThat(encoded) |
||||
.isEqualTo( |
||||
Bytes.fromHexString( |
||||
String.format( |
||||
"0x%02X%s", |
||||
consolidationRequest.getType().getSerializedType(), expectedEncodedBytes))); |
||||
} |
||||
} |
@ -0,0 +1,136 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.mainnet; |
||||
|
||||
import static org.hyperledger.besu.ethereum.mainnet.requests.ConsolidationRequestValidator.MAX_CONSOLIDATION_REQUESTS_PER_BLOCK; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.BLSPublicKey; |
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; |
||||
import org.hyperledger.besu.ethereum.core.ConsolidationRequest; |
||||
import org.hyperledger.besu.ethereum.core.Request; |
||||
|
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
import java.util.stream.IntStream; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
import org.apache.tuweni.bytes.Bytes48; |
||||
|
||||
public class ConsolidationRequestValidatorTestFixtures { |
||||
|
||||
private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); |
||||
|
||||
static ConsolidationRequestTestParameter |
||||
blockWithConsolidationRequestsAndWithdrawalRequestsRoot() { |
||||
final ConsolidationRequest consolidationRequest = createConsolidationRequest(); |
||||
final Optional<List<Request>> maybeConsolidationRequests = |
||||
Optional.of(List.of(consolidationRequest)); |
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions = |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setRequestsRoot(BodyValidation.requestsRoot(maybeConsolidationRequests.get())) |
||||
.setRequests(maybeConsolidationRequests); |
||||
final Block block = blockDataGenerator.block(blockOptions); |
||||
|
||||
return new ConsolidationRequestTestParameter( |
||||
"Block with consolidation requests and withdrawal_requests_root", |
||||
block, |
||||
Optional.of(List.of(consolidationRequest))); |
||||
} |
||||
|
||||
static ConsolidationRequestTestParameter blockWithConsolidationRequestsMismatch() { |
||||
final ConsolidationRequest consolidationRequest = createConsolidationRequest(); |
||||
|
||||
final Optional<List<Request>> requests = |
||||
Optional.of(List.of(consolidationRequest, consolidationRequest)); |
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions = |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setRequestsRoot(BodyValidation.requestsRoot(requests.get())) |
||||
.setRequests(requests); |
||||
final Block block = blockDataGenerator.block(blockOptions); |
||||
|
||||
return new ConsolidationRequestTestParameter( |
||||
"Block with consolidation requests mismatch", |
||||
block, |
||||
Optional.of(List.of(consolidationRequest, consolidationRequest)), |
||||
List.of(createConsolidationRequest())); |
||||
} |
||||
|
||||
static ConsolidationRequestTestParameter blockWithMoreThanMaximumConsolidationRequests() { |
||||
final List<ConsolidationRequest> consolidationRequests = |
||||
IntStream.range(0, MAX_CONSOLIDATION_REQUESTS_PER_BLOCK + 1) |
||||
.mapToObj(__ -> createConsolidationRequest()) |
||||
.toList(); |
||||
|
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest = |
||||
Optional.of(consolidationRequests); |
||||
final Optional<List<Request>> maybeRequests = |
||||
Optional.of(consolidationRequests.stream().map(r -> (Request) r).toList()); |
||||
|
||||
final BlockDataGenerator.BlockOptions blockOptions = |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setRequestsRoot(BodyValidation.requestsRoot(maybeRequests.get())) |
||||
.setRequests(maybeRequests); |
||||
final Block block = blockDataGenerator.block(blockOptions); |
||||
|
||||
return new ConsolidationRequestTestParameter( |
||||
"Block with more than maximum consolidation requests", block, maybeConsolidationRequest); |
||||
} |
||||
|
||||
static ConsolidationRequest createConsolidationRequest() { |
||||
return new ConsolidationRequest( |
||||
Address.extract(Bytes32.random()), |
||||
BLSPublicKey.wrap(Bytes48.random()), |
||||
BLSPublicKey.wrap(Bytes48.random())); |
||||
} |
||||
|
||||
static class ConsolidationRequestTestParameter { |
||||
|
||||
String description; |
||||
Block block; |
||||
Optional<List<ConsolidationRequest>> maybeConsolidationRequest; |
||||
List<ConsolidationRequest> expectedConsolidationRequest; |
||||
|
||||
public ConsolidationRequestTestParameter( |
||||
final String description, |
||||
final Block block, |
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest) { |
||||
this( |
||||
description, |
||||
block, |
||||
maybeConsolidationRequest, |
||||
maybeConsolidationRequest.orElseGet(List::of)); |
||||
} |
||||
|
||||
public ConsolidationRequestTestParameter( |
||||
final String description, |
||||
final Block block, |
||||
final Optional<List<ConsolidationRequest>> maybeConsolidationRequest, |
||||
final List<ConsolidationRequest> expectedConsolidationRequest) { |
||||
this.description = description; |
||||
this.block = block; |
||||
this.maybeConsolidationRequest = maybeConsolidationRequest; |
||||
this.expectedConsolidationRequest = expectedConsolidationRequest; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return description; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,76 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.mainnet; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithConsolidationRequestsAndWithdrawalRequestsRoot; |
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithConsolidationRequestsMismatch; |
||||
import static org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.blockWithMoreThanMaximumConsolidationRequests; |
||||
|
||||
import org.hyperledger.besu.ethereum.core.Request; |
||||
import org.hyperledger.besu.ethereum.mainnet.ConsolidationRequestValidatorTestFixtures.ConsolidationRequestTestParameter; |
||||
import org.hyperledger.besu.ethereum.mainnet.requests.ConsolidationRequestValidator; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
import java.util.stream.Stream; |
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.Arguments; |
||||
import org.junit.jupiter.params.provider.MethodSource; |
||||
|
||||
class PragueConsolidationRequestValidatorTest { |
||||
|
||||
@ParameterizedTest(name = "{index}: {0}") |
||||
@MethodSource("paramsForValidateConsolidationRequestParameter") |
||||
public void validateConsolidationRequestParameter( |
||||
final String description, |
||||
final Optional<List<Request>> maybeRequests, |
||||
final boolean expectedValidity) { |
||||
assertThat(new ConsolidationRequestValidator().validateParameter(maybeRequests)) |
||||
.isEqualTo(expectedValidity); |
||||
} |
||||
|
||||
private static Stream<Arguments> paramsForValidateConsolidationRequestParameter() { |
||||
return Stream.of( |
||||
Arguments.of( |
||||
"Allowed ConsolidationRequests - validating empty ConsolidationRequests", |
||||
Optional.empty(), |
||||
true), |
||||
Arguments.of( |
||||
"Allowed ConsolidationRequests - validating present ConsolidationRequests", |
||||
Optional.of(List.of()), |
||||
true)); |
||||
} |
||||
|
||||
@ParameterizedTest(name = "{index}: {0}") |
||||
@MethodSource("validateConsolidationRequestsInBlockParamsForPrague") |
||||
public void validateConsolidationRequestsInBlock_WhenPrague( |
||||
final ConsolidationRequestTestParameter param, final boolean expectedValidity) { |
||||
assertThat( |
||||
new ConsolidationRequestValidator() |
||||
.validate( |
||||
param.block, new ArrayList<>(param.expectedConsolidationRequest), List.of())) |
||||
.isEqualTo(expectedValidity); |
||||
} |
||||
|
||||
private static Stream<Arguments> validateConsolidationRequestsInBlockParamsForPrague() { |
||||
return Stream.of( |
||||
Arguments.of(blockWithConsolidationRequestsAndWithdrawalRequestsRoot(), true), |
||||
Arguments.of(blockWithConsolidationRequestsMismatch(), false), |
||||
Arguments.of(blockWithMoreThanMaximumConsolidationRequests(), false)); |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.plugin.data; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.PublicKey; |
||||
import org.hyperledger.besu.plugin.Unstable; |
||||
|
||||
/** A consolidation request is an operation sent to the Beacon Node for processing. */ |
||||
@Unstable |
||||
public interface ConsolidationRequest { |
||||
|
||||
/** |
||||
* Withdrawal credential (0x01) associated with the validator |
||||
* |
||||
* @return withdrawal credential address |
||||
*/ |
||||
Address getSourceAddress(); |
||||
|
||||
/** |
||||
* Public key of the address that sends the consolidation |
||||
* |
||||
* @return public key of sender |
||||
*/ |
||||
PublicKey getSourcePubkey(); |
||||
|
||||
/** |
||||
* Public key of the address to receives the consolidation |
||||
* |
||||
* @return public key of target |
||||
*/ |
||||
PublicKey getTargetPubkey(); |
||||
} |
Loading…
Reference in new issue