Skip to content

Commit

Permalink
EIP-6110: Add deposits in EL (Part 1) (hyperledger#5055)
Browse files Browse the repository at this point in the history
Add deposits to the Execution Layer block structure: EIP-6110. The scope of this commit is to add Deposit related info into BlockHeader and BlockBody. The rest of the EIP including RPC API and validating Deposit with be included in future PRs.

---------

Signed-off-by: Navie Chan <naviechan@gmail.com>
Signed-off-by: navie <naviechan@gmail.com>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
  • Loading branch information
ensi321 authored and eum602 committed Nov 3, 2023
1 parent e879c6b commit 2c95733
Show file tree
Hide file tree
Showing 70 changed files with 1,582 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public static BlockHeader createBlockHeader(
new BigInteger(block.getNonceRaw().substring(2), 16).longValue(),
null,
null,
null,
blockHeaderFunctions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ private void setSyncTarget() {
mock(EthPeer.class),
new org.hyperledger.besu.ethereum.core.BlockHeader(
null, null, null, null, null, null, null, null, 1, 1, 1, 1, null, null, null, 1, null,
null, null));
null, null, null));
}

private void clearSyncTarget() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public BlockCreationResult createBlock(
final Bytes32 random,
final long timestamp,
final Optional<List<Withdrawal>> withdrawals) {

return createBlock(
maybeTransactions,
Optional.of(Collections.emptyList()),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.datatypes;

import static com.google.common.base.Preconditions.checkArgument;

import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.rlp.RLPInput;

import com.fasterxml.jackson.annotation.JsonCreator;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.DelegatingBytes;

/** A BLS public key. */
public class BLSPublicKey extends DelegatingBytes
implements org.hyperledger.besu.plugin.data.PublicKey {

/** The constant SIZE. */
public static final int SIZE = 48;

/**
* Instantiates a new BLSPublicKey.
*
* @param bytes the bytes
*/
protected BLSPublicKey(final Bytes bytes) {
super(bytes);
}

/**
* Wrap public key.
*
* @param value the value
* @return the BLS public key
*/
public static BLSPublicKey wrap(final Bytes value) {
checkArgument(
value.size() == SIZE, "A BLS public key must be %s bytes long, got %s", SIZE, value.size());
return new BLSPublicKey(value);
}

/**
* Creates a bls public key from the given RLP-encoded input.
*
* @param input The input to read from
* @return the input's corresponding public key
*/
public static BLSPublicKey readFrom(final RLPInput input) {
final Bytes bytes = input.readBytes();
if (bytes.size() != SIZE) {
throw new RLPException(
String.format("BLSPublicKey unexpected size of %s (needs %s)", bytes.size(), SIZE));
}
return BLSPublicKey.wrap(bytes);
}

/**
* Parse a hexadecimal string representing an public key.
*
* @param str A hexadecimal string (with or without the leading '0x') representing a valid bls
* public key.
* @return The parsed bls public key: {@code null} if the provided string is {@code null}.
* @throws IllegalArgumentException if the string is either not hexadecimal, or not the valid
* representation of a BLSPublicKey.
*/
@JsonCreator
public static BLSPublicKey fromHexString(final String str) {
if (str == null) return null;
return wrap(Bytes.fromHexStringLenient(str, SIZE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.datatypes;

import static com.google.common.base.Preconditions.checkArgument;

import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.rlp.RLPInput;

import com.fasterxml.jackson.annotation.JsonCreator;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.DelegatingBytes;

/** A BLS Signature * */
public class BLSSignature extends DelegatingBytes
implements org.hyperledger.besu.plugin.data.Signature {

/** The constant SIZE. */
public static final int SIZE = 96;

/**
* Instantiates a new BLSSignature.
*
* @param bytes the bytes
*/
protected BLSSignature(final Bytes bytes) {
super(bytes);
}

/**
* Wrap signature.
*
* @param value the value
* @return the signature
*/
public static BLSSignature wrap(final Bytes value) {
checkArgument(
value.size() == SIZE, "A signature must be %s bytes long, got %s", SIZE, value.size());
return new BLSSignature(value);
}

/**
* Creates a signature from the given RLP-encoded input.
*
* @param input The input to read from
* @return the input's corresponding signature
*/
public static BLSSignature readFrom(final RLPInput input) {
final Bytes bytes = input.readBytes();
if (bytes.size() != SIZE) {
throw new RLPException(
String.format("BLSSignature unexpected size of %s (needs %s)", bytes.size(), SIZE));
}
return BLSSignature.wrap(bytes);
}

/**
* Parse a hexadecimal string representing a signature.
*
* @param str A hexadecimal string (with or without the leading '0x') representing a valid bls
* signature.
* @return The parsed signature: {@code null} if the provided string is {@code null}.
* @throws IllegalArgumentException if the string is either not hexadecimal, or not the valid
* representation of a bls signature.
*/
@JsonCreator
public static BLSSignature fromHexString(final String str) {
if (str == null) return null;
return wrap(Bytes.fromHexStringLenient(str, SIZE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ public enum JsonRpcResponseKey {
TOTAL_DIFFICULTY,
TRANSACTION_ROOT,
BASEFEE,
WITHDRAWALS_ROOT
WITHDRAWALS_ROOT,
DEPOSITS_ROOT
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.BASEFEE;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.COINBASE;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.DEPOSITS_ROOT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.DIFFICULTY;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.EXTRA_DATA;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcResponseKey.GAS_LIMIT;
Expand Down Expand Up @@ -103,6 +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 depositsRoot =
values.containsKey(DEPOSITS_ROOT) ? hash(values.get(DEPOSITS_ROOT)) : null;
final List<JsonNode> ommers = new ArrayList<>();

final BlockHeader header =
Expand All @@ -125,6 +128,7 @@ public JsonRpcResponse response(
nonce,
withdrawalsRoot,
null, // ToDo 4844: set with the value of excess_data_gas field
depositsRoot,
blockHeaderFunctions);

return new JsonRpcSuccessResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)
0,
maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null),
null,
null,
headerFunctions);

// ensure the block hash matches the blockParam hash
Expand Down Expand Up @@ -201,7 +202,9 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext)

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

if (parentHeader.isEmpty()) {
LOG.atDebug()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* 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.BLSPublicKey;
import org.hyperledger.besu.datatypes.BLSSignature;
import org.hyperledger.besu.datatypes.GWei;
import org.hyperledger.besu.ethereum.core.Deposit;

import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.vertx.core.json.JsonObject;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt64;

public class DepositParameter {

private final String publicKey;

private final String withdrawalCredentials;
private final String amount;

private final String signature;
private final String index;

@JsonCreator
public DepositParameter(
@JsonProperty("pubKey") final String pubKey,
@JsonProperty("withdrawal_credentials") final String withdrawalCredentials,
@JsonProperty("amount") final String amount,
@JsonProperty("signature") final String signature,
@JsonProperty("index") final String index) {
this.publicKey = pubKey;
this.withdrawalCredentials = withdrawalCredentials;
this.amount = amount;
this.signature = signature;
this.index = index;
}

public static DepositParameter fromDeposit(final Deposit deposit) {
return new DepositParameter(
deposit.getPublicKey().toString(),
deposit.getWithdrawalCredentials().toString(),
deposit.getAmount().toShortHexString(),
deposit.getSignature().toString(),
deposit.getIndex().toBytes().toQuantityHexString());
}

public Deposit toDeposit() {
return new Deposit(
BLSPublicKey.fromHexString(publicKey),
Bytes32.fromHexString(withdrawalCredentials),
GWei.fromHexString(amount),
BLSSignature.fromHexString(signature),
UInt64.fromHexString(index));
}

public JsonObject asJsonObject() {
return new JsonObject()
.put("pubKey", publicKey)
.put("withdrawalCredentials", withdrawalCredentials)
.put("amount", amount)
.put("signature", signature)
.put("index", index);
}

@JsonGetter
public String getPublicKey() {
return publicKey;
}

@JsonGetter
public String getWithdrawalCredentials() {
return withdrawalCredentials;
}

@JsonGetter
public String getAmount() {
return amount;
}

@JsonGetter
public String getSignature() {
return signature;
}

@JsonGetter
public String getIndex() {
return index;
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final DepositParameter that = (DepositParameter) o;
return Objects.equals(publicKey, that.publicKey)
&& Objects.equals(withdrawalCredentials, that.withdrawalCredentials)
&& Objects.equals(amount, that.amount)
&& Objects.equals(signature, that.signature)
&& Objects.equals(index, that.index);
}

@Override
public int hashCode() {
return Objects.hash(publicKey, withdrawalCredentials, amount, signature, index);
}

@Override
public String toString() {
return "DepositParameter{"
+ "pubKey='"
+ publicKey
+ '\''
+ ", withdrawalCredentials='"
+ withdrawalCredentials
+ '\''
+ ", amount='"
+ amount
+ '\''
+ ", signature='"
+ signature
+ '\''
+ ", index='"
+ index
+ '\''
+ '}';
}
}
Loading

0 comments on commit 2c95733

Please sign in to comment.