Bugfix/besu 2598 basefee present before fork block (#2603)

Signed-off-by: garyschulte <garyschulte@gmail.com>
pull/2595/head
garyschulte 3 years ago committed by GitHub
parent 1b45e22599
commit dfd82be338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/BlockHeaderValidationRulesetFactory.java
  2. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/fees/LondonFeeMarketException.java
  3. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java
  4. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/GasLimitRangeAndDeltaValidationRule.java
  5. 20
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/LondonFeeMarketBlockHeaderGasPriceValidationRule.java
  6. 25
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/GasLimitRangeAndDeltaValidationRuleTest.java
  7. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/LondonFeeMarketBlockHeaderGasPriceValidationRuleTest.java

@ -26,9 +26,9 @@ import org.hyperledger.besu.ethereum.core.fees.EIP1559;
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.EIP1559BlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasLimitRangeAndDeltaValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasUsageValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.LondonFeeMarketBlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
@ -74,7 +74,7 @@ public class BlockHeaderValidationRulesetFactory {
.addRule(new CoinbaseHeaderValidationRule(epochManager));
if (eip1559.isPresent()) {
builder
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559.get())))
.addRule((new LondonFeeMarketBlockHeaderGasPriceValidationRule(eip1559.get())))
.addRule(new GasUsageValidationRule());
} else {

@ -14,8 +14,18 @@
*/
package org.hyperledger.besu.ethereum.core.fees;
public class EIP1559MissingBaseFeeFromBlockHeader extends Exception {
public EIP1559MissingBaseFeeFromBlockHeader() {
super("Invalid block header: basefee should be specified");
public class LondonFeeMarketException extends Exception {
public static LondonFeeMarketException MissingBaseFeeFromBlockHeader() {
return new LondonFeeMarketException("Invalid block header: basefee should be specified");
}
public static LondonFeeMarketException BaseFeePresentBeforeForkBlock() {
return new LondonFeeMarketException(
"Invalid block header: basefee should not be present before London fork block");
}
private LondonFeeMarketException(final String reason) {
super(reason);
}
}

@ -19,10 +19,10 @@ 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.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;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.LondonFeeMarketBlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ProofOfWorkValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
@ -136,7 +136,7 @@ public final class MainnetBlockHeaderValidator {
true,
PoWHasher.ETHASH_LIGHT,
Optional.of(eip1559)))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
.addRule((new LondonFeeMarketBlockHeaderGasPriceValidationRule(eip1559)));
}
static BlockHeaderValidator.Builder createEip1559OmmerValidator(final EIP1559 eip1559) {
@ -155,6 +155,6 @@ public final class MainnetBlockHeaderValidator {
true,
PoWHasher.ETHASH_LIGHT,
Optional.of(eip1559)))
.addRule((new EIP1559BlockHeaderGasPriceValidationRule(eip1559)));
.addRule((new LondonFeeMarketBlockHeaderGasPriceValidationRule(eip1559)));
}
}

@ -63,6 +63,10 @@ public class GasLimitRangeAndDeltaValidationRule extends AbstractGasLimitSpecifi
if (eip1559.isPresent() && eip1559.get().isForkBlock(header.getNumber())) {
parentGasLimit = parent.getGasLimit() * eip1559.get().getFeeMarket().getSlackCoefficient();
} else if (eip1559.isEmpty() && header.getBaseFee().isPresent()) {
LOG.info(
"Invalid block header: basefee should not be present in a block without a fee market");
return false;
}
final long difference = Math.abs(parentGasLimit - gasLimit);

@ -14,19 +14,22 @@
*/
package org.hyperledger.besu.ethereum.mainnet.headervalidationrules;
import static org.hyperledger.besu.ethereum.core.fees.LondonFeeMarketException.MissingBaseFeeFromBlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.fees.EIP1559;
import org.hyperledger.besu.ethereum.core.fees.EIP1559MissingBaseFeeFromBlockHeader;
import org.hyperledger.besu.ethereum.core.fees.LondonFeeMarketException;
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class EIP1559BlockHeaderGasPriceValidationRule implements DetachedBlockHeaderValidationRule {
public class LondonFeeMarketBlockHeaderGasPriceValidationRule
implements DetachedBlockHeaderValidationRule {
private static final Logger LOG = LogManager.getLogger();
private final EIP1559 eip1559;
public EIP1559BlockHeaderGasPriceValidationRule(final EIP1559 eip1559) {
public LondonFeeMarketBlockHeaderGasPriceValidationRule(final EIP1559 eip1559) {
this.eip1559 = eip1559;
}
@ -34,17 +37,20 @@ public class EIP1559BlockHeaderGasPriceValidationRule implements DetachedBlockHe
public boolean validate(final BlockHeader header, final BlockHeader parent) {
try {
if (!eip1559.isEIP1559(header.getNumber())) {
if (header.getBaseFee().isPresent()) {
throw LondonFeeMarketException.BaseFeePresentBeforeForkBlock();
}
return true;
}
if (eip1559.isForkBlock(header.getNumber())) {
return eip1559.getFeeMarket().getInitialBasefee()
== header.getBaseFee().orElseThrow(EIP1559MissingBaseFeeFromBlockHeader::new);
== header.getBaseFee().orElseThrow(() -> MissingBaseFeeFromBlockHeader());
}
final Long parentBaseFee =
parent.getBaseFee().orElseThrow(EIP1559MissingBaseFeeFromBlockHeader::new);
parent.getBaseFee().orElseThrow(() -> MissingBaseFeeFromBlockHeader());
final Long currentBaseFee =
header.getBaseFee().orElseThrow(EIP1559MissingBaseFeeFromBlockHeader::new);
header.getBaseFee().orElseThrow(() -> MissingBaseFeeFromBlockHeader());
final long targetGasUsed = eip1559.targetGasUsed(parent);
final long expectedBaseFee =
eip1559.computeBaseFee(
@ -58,7 +64,7 @@ public class EIP1559BlockHeaderGasPriceValidationRule implements DetachedBlockHe
}
return true;
} catch (final EIP1559MissingBaseFeeFromBlockHeader e) {
} catch (final LondonFeeMarketException e) {
LOG.info("Invalid block header: " + e.getMessage());
return false;
}

@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -42,22 +43,33 @@ public class GasLimitRangeAndDeltaValidationRuleTest {
@Parameter(3)
public boolean expectedResult;
@Parameter(4)
public Optional<Long> optionalBaseFee;
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(
new Object[][] {
{4096, 4096, new GasLimitRangeAndDeltaValidationRule(4095, 4097), true},
{4096, 4096, new GasLimitRangeAndDeltaValidationRule(4095, 4097), true, Optional.empty()},
// In Range, no change = valid,
{4096, 4096, new GasLimitRangeAndDeltaValidationRule(4094, 4095), false},
{
4096, 4096, new GasLimitRangeAndDeltaValidationRule(4094, 4095), false, Optional.empty()
},
// Out of Range, no change = invalid,
{4099, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), true},
{4099, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), true, Optional.empty()},
// In Range, <1/1024 change = valid,
{4093, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), true},
{4093, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), true, Optional.empty()},
// In Range, ,1/1024 change = valid,
{4092, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), false},
{
4092, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), false, Optional.empty()
},
// In Range, == 1/1024 change = invalid,
{4100, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), false}
{
4100, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), false, Optional.empty()
},
// In Range, == 1/1024 change = invalid,
{4099, 4096, new GasLimitRangeAndDeltaValidationRule(4000, 4200), false, Optional.of(10L)}
// In Range, <1/1024 change, has basefee = invalid,
});
}
@ -66,6 +78,7 @@ public class GasLimitRangeAndDeltaValidationRuleTest {
final BlockHeaderTestFixture blockHeaderBuilder = new BlockHeaderTestFixture();
blockHeaderBuilder.gasLimit(headerGasLimit);
optionalBaseFee.ifPresent(baseFee -> blockHeaderBuilder.baseFeePerGas(baseFee));
final BlockHeader header = blockHeaderBuilder.buildHeader();
blockHeaderBuilder.gasLimit(parentGasLimit);

@ -25,16 +25,16 @@ import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class EIP1559BlockHeaderGasPriceValidationRuleTest {
public class LondonFeeMarketBlockHeaderGasPriceValidationRuleTest {
private static final long FORK_BLOCK = 800L;
private final EIP1559 eip1559 = new EIP1559(FORK_BLOCK);
private EIP1559BlockHeaderGasPriceValidationRule validationRule;
private LondonFeeMarketBlockHeaderGasPriceValidationRule validationRule;
private final FeeMarket feeMarket = FeeMarket.london();
@Before
public void setUp() {
validationRule = new EIP1559BlockHeaderGasPriceValidationRule(eip1559);
validationRule = new LondonFeeMarketBlockHeaderGasPriceValidationRule(eip1559);
}
@Test
@ -43,6 +43,12 @@ public class EIP1559BlockHeaderGasPriceValidationRuleTest {
.isTrue();
}
@Test
public void shouldReturnFalseBeforeFork() {
assertThat(validationRule.validate(blockHeader(FORK_BLOCK - 1, 0, Optional.of(10L)), null))
.isFalse();
}
@Test
public void shouldReturnTrueIfInitialBaseFeeAtForkBlock() {
assertThat(
Loading…
Cancel
Save