Skip to content

Commit

Permalink
New RPC methods miner_setExtraData and miner_getExtraData (hyperl…
Browse files Browse the repository at this point in the history
…edger#7078)

* New RPC methods to set and get block extra data

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Remove redundant methods to set the extra data

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* miner_getExtraData unit tests

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Add CHANGELOG

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Apply suggestions from code review

Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

---------

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
  • Loading branch information
2 people authored and matthew1001 committed Jun 7, 2024
1 parent 477d3a0 commit 2291fc3
Show file tree
Hide file tree
Showing 20 changed files with 291 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
- Update Gradle to 7.6.4 [#7030](https://github.com/hyperledger/besu/pull/7030)
- Remove deprecated Goerli testnet [#7049](https://github.com/hyperledger/besu/pull/7049)
- Default bonsai to use full-flat db and code-storage-by-code-hash [#6984](https://github.com/hyperledger/besu/pull/6894)
- New RPC methods miner_setExtraData and miner_getExtraData [#7078](https://github.com/hyperledger/besu/pull/7078)

### Bug fixes
- Fix txpool dump/restore race condition [#6665](https://github.com/hyperledger/besu/pull/6665)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private void setOptionalFields(
// For simplicity only set these for PoW consensus algorithms.
// Other consensus algorithms use these fields for special purposes or ignore them.
miner.setCoinbase(blockData.getCoinbase().orElse(Address.ZERO));
miner.setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY));
controller.getMiningParameters().setExtraData(blockData.getExtraData().orElse(Bytes.EMPTY));
} else if (blockData.getCoinbase().isPresent() || blockData.getExtraData().isPresent()) {
// Fail if these fields are set for non-ethash chains
final Stream.Builder<String> fields = Stream.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void shouldUseLatestVanityData() {
null,
ethScheduler);

executor.setExtraData(modifiedVanityData);
miningParameters.setExtraData(modifiedVanityData);
final Bytes extraDataBytes = executor.calculateExtraData(blockHeaderBuilder.buildHeader());

final CliqueExtraData cliqueExtraData =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.util.concurrent.CompletableFuture;

import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -108,11 +107,6 @@ public Wei getMinPriorityFeePerGas() {
return activeMiningCoordinator.getMinPriorityFeePerGas();
}

@Override
public void setExtraData(final Bytes extraData) {
activeMiningCoordinator.setExtraData(extraData);
}

@Override
public Optional<Address> getCoinbase() {
return activeMiningCoordinator.getCoinbase();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,6 @@ public BlockCreator create(final BlockHeader parentHeader, final int round) {
ethScheduler);
}

/**
* Sets extra data.
*
* @param extraData the extra data
*/
public void setExtraData(final Bytes extraData) {

miningParameters.setExtraData(extraData.copy());
}

/**
* Sets min transaction gas price.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -154,11 +153,6 @@ public Wei getMinPriorityFeePerGas() {
return blockCreatorFactory.getMinPriorityFeePerGas();
}

@Override
public void setExtraData(final Bytes extraData) {
blockCreatorFactory.setExtraData(extraData);
}

@Override
public Optional<Address> getCoinbase() {
return Optional.of(blockCreatorFactory.getLocalAddress());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import java.util.List;
import java.util.function.Consumer;

import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -162,11 +161,6 @@ public void delegatesToActiveMiningCoordinator() {
coordinator2,
coordinator1);

verifyDelegation(
c -> c.setExtraData(Bytes.EMPTY), GENESIS_BLOCK_NUMBER, coordinator1, coordinator2);
verifyDelegation(
c -> c.setExtraData(Bytes.EMPTY), MIGRATION_BLOCK_NUMBER, coordinator2, coordinator1);

verifyDelegation(
MiningCoordinator::getCoinbase, GENESIS_BLOCK_NUMBER, coordinator1, coordinator2);
verifyDelegation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.util.Collections;
import java.util.concurrent.TimeUnit;

import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -89,13 +88,6 @@ public void getsMinTransactionGasPrice() {
assertThat(bftMiningCoordinator.getMinTransactionGasPrice()).isEqualTo(minGasPrice);
}

@Test
public void setsTheExtraData() {
final Bytes extraData = Bytes.fromHexStringLenient("0x1234");
bftMiningCoordinator.setExtraData(extraData);
verify(bftBlockCreatorFactory).setExtraData(extraData);
}

@Test
public void addsNewChainHeadEventWhenNewCanonicalHeadBlockEventReceived() throws Exception {
BlockAddedEvent headAdvancement =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
import java.util.function.Supplier;

import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -225,11 +224,6 @@ public Wei getMinPriorityFeePerGas() {
return miningParameters.getMinPriorityFeePerGas();
}

@Override
public void setExtraData(final Bytes extraData) {
this.miningParameters.setExtraData(extraData);
}

@Override
public Optional<Address> getCoinbase() {
return miningParameters.getCoinbase();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;

/** The Transition coordinator. */
Expand Down Expand Up @@ -107,12 +106,6 @@ public Wei getMinPriorityFeePerGas() {
return dispatchFunctionAccordingToMergeState(MiningCoordinator::getMinPriorityFeePerGas);
}

@Override
public void setExtraData(final Bytes extraData) {
miningCoordinator.setExtraData(extraData);
mergeCoordinator.setExtraData(extraData);
}

@Override
public Optional<Address> getCoinbase() {
return dispatchFunctionAccordingToMergeState(MiningCoordinator::getCoinbase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ public enum RpcMethod {
MINER_SET_MIN_PRIORITY_FEE("miner_setMinPriorityFee"),
MINER_GET_MIN_GAS_PRICE("miner_getMinGasPrice"),
MINER_SET_MIN_GAS_PRICE("miner_setMinGasPrice"),
MINER_GET_EXTRA_DATA("miner_getExtraData"),
MINER_SET_EXTRA_DATA("miner_setExtraData"),
NET_ENODE("net_enode"),
NET_LISTENING("net_listening"),
NET_PEER_COUNT("net_peerCount"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.methods.miner;

import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.MiningParameters;

public class MinerGetExtraData implements JsonRpcMethod {
private final MiningParameters miningParameters;

public MinerGetExtraData(final MiningParameters miningParameters) {
this.miningParameters = miningParameters;
}

@Override
public String getName() {
return RpcMethod.MINER_GET_EXTRA_DATA.getMethodName();
}

@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), miningParameters.getExtraData().toShortHexString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.methods.miner;

import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
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;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.core.MiningParameters;

import java.nio.charset.StandardCharsets;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MinerSetExtraData implements JsonRpcMethod {
private static final Logger LOG = LoggerFactory.getLogger(MinerSetExtraData.class);

private final MiningParameters miningParameters;

public MinerSetExtraData(final MiningParameters miningParameters) {
this.miningParameters = miningParameters;
}

@Override
public String getName() {
return RpcMethod.MINER_SET_EXTRA_DATA.getMethodName();
}

@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
try {
final String rawParam = requestContext.getRequiredParameter(0, String.class);
Bytes32.fromHexStringLenient(
rawParam); // done for validation, we want a hex string and max 32 bytes
final var extraData = Bytes.fromHexStringLenient(rawParam);
miningParameters.setExtraData(extraData);
LOG.atDebug()
.setMessage("set extra data, raw=[{}] parsed=[{}], UTF-8=[{}]")
.addArgument(rawParam)
.addArgument(extraData::toHexString)
.addArgument(() -> new String(extraData.toArray(), StandardCharsets.UTF_8))
.log();
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), true);
} catch (final IllegalArgumentException invalidJsonRpcParameters) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
new JsonRpcError(RpcErrorType.INVALID_PARAMS, invalidJsonRpcParameters.getMessage()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerChangeTargetGasLimit;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerGetExtraData;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerGetMinGasPrice;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerGetMinPriorityFee;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerSetCoinbase;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerSetEtherbase;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerSetExtraData;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerSetMinGasPrice;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerSetMinPriorityFee;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.miner.MinerStart;
Expand Down Expand Up @@ -58,6 +60,8 @@ protected Map<String, JsonRpcMethod> create() {
new MinerGetMinPriorityFee(miningParameters),
new MinerSetMinPriorityFee(miningParameters),
new MinerGetMinGasPrice(miningParameters),
new MinerSetMinGasPrice(miningParameters));
new MinerSetMinGasPrice(miningParameters),
new MinerGetExtraData(miningParameters),
new MinerSetExtraData(miningParameters));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.methods.miner;

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
import org.hyperledger.besu.ethereum.core.MiningParameters;

import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;

public class MinerGetExtraDataTest {

@Test
public void shouldReturnDefaultExtraData() {
final MiningParameters miningParameters = ImmutableMiningParameters.newDefault();
final MinerGetExtraData method = new MinerGetExtraData(miningParameters);
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", method.getName(), new Object[] {}));

final JsonRpcResponse expected = new JsonRpcSuccessResponse(request.getRequest().getId(), "0x");

final JsonRpcResponse actual = method.response(request);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
}

@Test
public void shouldReturnSetAtRuntimeExtraData() {
final MiningParameters miningParameters = ImmutableMiningParameters.newDefault();
final MinerGetExtraData method = new MinerGetExtraData(miningParameters);
final var extraData = "0x123456";
final Bytes extraDataAtRuntime = Bytes.fromHexString(extraData);

miningParameters.setExtraData(extraDataAtRuntime);

final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("2.0", method.getName(), new Object[] {}));

final JsonRpcResponse expected =
new JsonRpcSuccessResponse(request.getRequest().getId(), extraData);

final JsonRpcResponse actual = method.response(request);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
}
}
Loading

0 comments on commit 2291fc3

Please sign in to comment.