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

[EIP-1559] Step 8 - Disable GasLimitRangeAndDeltaValidationRule and update ProofOfWorkValidationRule #722

Merged
merged 31 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ba37fd0
Added changelog entries for PR:
AbdelStark Mar 12, 2020
872f9cc
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 13, 2020
e417b30
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 16, 2020
a2fb831
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 17, 2020
c07ed7d
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 17, 2020
1c1e22f
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 18, 2020
ee10a25
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 19, 2020
40cd31d
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 23, 2020
e96c01a
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 25, 2020
2c782ba
Merge remote-tracking branch 'upstream/master'
AbdelStark Mar 31, 2020
8b7f62d
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 2, 2020
ce2a4c9
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 3, 2020
97fc9b5
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 6, 2020
95947ab
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 6, 2020
63cc028
Merge branch 'master' of https://github.com/hyperledger/besu
AbdelStark Apr 7, 2020
6c83695
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 9, 2020
f9ff230
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 9, 2020
96433d6
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 10, 2020
dd1c9b9
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 14, 2020
a1a337a
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 14, 2020
f258611
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 14, 2020
ec0f09a
Merge remote-tracking branch 'upstream/master'
AbdelStark Apr 15, 2020
9cdeea1
For post EIP-1559 blocks we must disable GasLimitRangeAndDeltaValidat…
AbdelStark Apr 15, 2020
5a15a73
Rename logger
AbdelStark Apr 15, 2020
c5ca0b1
Rename logger
AbdelStark Apr 15, 2020
33be1bb
Merge branch 'master' into 720
AbdelStark Apr 15, 2020
dc01da3
Fix base fee computation and add tests.
AbdelStark Apr 15, 2020
df457ce
Merge branch '720' of https://github.com/abdelhamidbakhta/besu into 720
AbdelStark Apr 15, 2020
bb6c120
Merge remote-tracking branch 'upstream/master' into 720
AbdelStark Apr 16, 2020
9e273be
Address PR comments
AbdelStark Apr 16, 2020
9955d2b
Merge branch 'master' into 720
AbdelStark Apr 16, 2020
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 @@ -40,4 +40,10 @@ public class ExperimentalEIPs {
description = "Enable non-finalized Berlin features (default: ${DEFAULT-VALUE})",
arity = "1")
public static boolean berlinEnabled = BERLIN_ENABLED_DEFAULT_VALUE;

public static void eip1559MustBeEnabled() {
if (!eip1559Enabled) {
throw new RuntimeException("EIP-1559 feature flag must be enabled --Xeip1559-enabled");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.core.fees;

import static java.lang.Math.floorDiv;

import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.core.AcceptedTransactionTypes;
import org.hyperledger.besu.ethereum.core.Transaction;
Expand All @@ -33,10 +35,30 @@ public EIP1559(final long forkBlockNumber) {
public long computeBaseFee(final long parentBaseFee, final long parentBlockGasUsed) {
guardActivation();
long delta = parentBlockGasUsed - feeMarket.getTargetGasUsed();
return parentBaseFee
+ ((parentBaseFee * delta)
/ feeMarket.getTargetGasUsed()
/ feeMarket.getBasefeeMaxChangeDenominator());
long baseFee =
parentBaseFee
+ floorDiv(
floorDiv(parentBaseFee * delta, feeMarket.getTargetGasUsed()),
feeMarket.getBasefeeMaxChangeDenominator());
boolean neg = false;
long diff = baseFee - parentBaseFee;
if (diff < 0) {
neg = true;
diff = -diff;
}

long max = floorDiv(parentBaseFee, feeMarket.getBasefeeMaxChangeDenominator());
if (max < 1) {
max = 1;
}
if (diff > max) {
if (neg) {
max = -max;
}
baseFee = parentBaseFee + max;
}

return baseFee;
}

public boolean isValidBaseFee(final long parentBaseFee, final long baseFee) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
*/
package org.hyperledger.besu.ethereum.mainnet;

import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.fees.EIP1559;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.CalculatedDifficultyValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.EIP1559BlockHeaderGasLimitValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.EIP1559BlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ExtraDataMaxLengthValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasLimitRangeAndDeltaValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasUsageValidationRule;
Expand Down Expand Up @@ -87,4 +91,31 @@ private static BlockHeaderValidator.Builder<Void> createValidator() {
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule());
}

static BlockHeaderValidator.Builder<Void> createEip1559Validator(final EIP1559 eip1559) {
ExperimentalEIPs.eip1559MustBeEnabled();
return new BlockHeaderValidator.Builder<Void>()
.addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(true))
.addRule(new EIP1559BlockHeaderGasLimitValidationRule(eip1559))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
}

static BlockHeaderValidator.Builder<Void> createEip1559OmmerValidator(final EIP1559 eip1559) {
ExperimentalEIPs.eip1559MustBeEnabled();
return new BlockHeaderValidator.Builder<Void>()
.addRule(CalculatedDifficultyValidationRule::new)
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule(true))
.addRule(new EIP1559BlockHeaderGasLimitValidationRule(eip1559))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.core.fees.EIP1559;
import org.hyperledger.besu.ethereum.mainnet.contractvalidation.MaxCodeSizeRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.EIP1559BlockHeaderGasLimitValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.EIP1559BlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionValidator;
import org.hyperledger.besu.ethereum.vm.MessageFrame;
Expand Down Expand Up @@ -350,27 +348,22 @@ static ProtocolSpecBuilder<Void> eip1559Definition(
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final GenesisConfigOptions genesisConfigOptions) {
if (!ExperimentalEIPs.eip1559Enabled) {
throw new RuntimeException("EIP-1559 feature flag must be enabled --Xeip1559-enabled");
}
ExperimentalEIPs.eip1559MustBeEnabled();
final EIP1559 eip1559 = new EIP1559(genesisConfigOptions.getEIP1559BlockNumber().orElse(0));
final ProtocolSpecBuilder<Void> eip1559ProtocolSpecBuilder =
muirGlacierDefinition(chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
true,
chainId,
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSITIONAL_TRANSACTIONS))
.name("EIP-1559");
final BlockHeaderValidator.Builder<Void> blockHeaderValidatorBuilder =
eip1559ProtocolSpecBuilder.getBlockHeaderValidatorBuilder();
blockHeaderValidatorBuilder
.addRule(new EIP1559BlockHeaderGasLimitValidationRule(eip1559))
.addRule(new EIP1559BlockHeaderGasPriceValidationRule(eip1559));
return eip1559ProtocolSpecBuilder;
return muirGlacierDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
true,
chainId,
Optional.of(eip1559),
AcceptedTransactionTypes.FEE_MARKET_TRANSITIONAL_TRANSACTIONS))
.name("EIP-1559")
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator.createEip1559Validator(eip1559))
.ommerHeaderValidatorBuilder(
MainnetBlockHeaderValidator.createEip1559OmmerValidator(eip1559));
}

// TODO EIP-1559 change for the actual fork name when known
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.apache.logging.log4j.Logger;

public class EIP1559BlockHeaderGasLimitValidationRule implements DetachedBlockHeaderValidationRule {
private final Logger LOG = LogManager.getLogger(CalculatedDifficultyValidationRule.class);
private final Logger LOG = LogManager.getLogger(EIP1559BlockHeaderGasLimitValidationRule.class);
private final EIP1559 eip1559;
private final FeeMarket feeMarket = FeeMarket.eip1559();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.apache.logging.log4j.Logger;

public class EIP1559BlockHeaderGasPriceValidationRule implements DetachedBlockHeaderValidationRule {
private final Logger LOG = LogManager.getLogger(CalculatedDifficultyValidationRule.class);
private final Logger LOG = LogManager.getLogger(EIP1559BlockHeaderGasPriceValidationRule.class);
private final EIP1559 eip1559;
private final FeeMarket feeMarket = FeeMarket.eip1559();

Expand All @@ -51,7 +51,7 @@ public boolean validate(final BlockHeader header, final BlockHeader parent) {
if (baseFee != header.getBaseFee().orElseThrow()) {
LOG.trace(
"Invalid block header: basefee {} does not equal expected basefee {}",
header.getBaseFee(),
header.getBaseFee().orElseThrow(),
baseFee);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet.headervalidationrules;

import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
Expand All @@ -36,8 +37,28 @@ public final class ProofOfWorkValidationRule implements DetachedBlockHeaderValid

static final EthHasher HASHER = new EthHasher.Light();

private final boolean includeBaseFee;

public ProofOfWorkValidationRule() {
this(false);
}

public ProofOfWorkValidationRule(final boolean includeBaseFee) {
this.includeBaseFee = includeBaseFee;
}

@Override
public boolean validate(final BlockHeader header, final BlockHeader parent) {
if (includeBaseFee) {
if (!ExperimentalEIPs.eip1559Enabled) {
LOG.warn("Invalid block header: EIP-1559 feature flag must be enabled --Xeip1559-enabled");
return false;
} else if (header.getBaseFee().isEmpty()) {
LOG.warn("Invalid block header: missing mandatory base fee.");
return false;
}
}

final byte[] hashBuffer = new byte[64];
final Hash headerHash = hashHeader(header);
HASHER.hash(hashBuffer, header.getNonce(), header.getNumber(), headerHash.toArray());
Expand Down Expand Up @@ -95,6 +116,10 @@ Hash hashHeader(final BlockHeader header) {
out.writeLongScalar(header.getGasUsed());
out.writeLongScalar(header.getTimestamp());
out.writeBytes(header.getExtraData());
if (includeBaseFee && header.getBaseFee().isPresent()) {
AbdelStark marked this conversation as resolved.
Show resolved Hide resolved
ExperimentalEIPs.eip1559MustBeEnabled();
out.writeLongScalar(header.getBaseFee().get());
}
out.endList();

return Hash.hash(out.encoded());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright ConsenSys AG.
*
* 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.fees;

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

import org.hyperledger.besu.config.experimental.ExperimentalEIPs;

import java.util.Arrays;
import java.util.Collection;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class EIP1559BaseFeeTest {

private static final long MARKER_BASE_FEE = 1049238967;
private final EIP1559 eip1559 = new EIP1559(0L);
private static final FeeMarket FEE_MARKET = FeeMarket.eip1559();

@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(
new Object[][] {
{
FEE_MARKET.getInitialBasefee(),
FEE_MARKET.getTargetGasUsed(),
FEE_MARKET.getInitialBasefee()
},
{FEE_MARKET.getInitialBasefee(), 7000000, 962500000},
{1100000000, FEE_MARKET.getTargetGasUsed(), 1100000000},
{1100000000, 9000000, 1086250000},
{1086250000, 9000000, 1072671875},
{1072671875, 9000000, 1059263476},
{1059263476, 10001000, 1059276716},
{1059276716, 16000000, 1138722469},
{MARKER_BASE_FEE, 0, 918084097},
{MARKER_BASE_FEE, 5, 918084161},
{MARKER_BASE_FEE, 5000, 918149673},
{MARKER_BASE_FEE, 500000, 924641839},
{MARKER_BASE_FEE, FEE_MARKET.getTargetGasUsed(), MARKER_BASE_FEE},
{MARKER_BASE_FEE, FEE_MARKET.getMaxGas(), 1127931889}
});
}

private final long parentBaseFee;
private final long parentGasUsed;
private final long expectedBaseFee;

public EIP1559BaseFeeTest(
final long parentBaseFee, final long parentGasUsed, final long expectedBaseFee) {
this.parentBaseFee = parentBaseFee;
this.parentGasUsed = parentGasUsed;
this.expectedBaseFee = expectedBaseFee;
}

@Before
public void setUp() {
ExperimentalEIPs.eip1559Enabled = true;
}

@After
public void reset() {
ExperimentalEIPs.eip1559Enabled = ExperimentalEIPs.EIP1559_ENABLED_DEFAULT_VALUE;
}

@Test
public void assertThatBaseFeeIsCorrect() {
assertThat(eip1559.computeBaseFee(parentBaseFee, parentGasUsed)).isEqualTo(expectedBaseFee);
}
}