The published line delivered the anchor (source and patch 0003) but had lost the chain configuration: no genesis, no run recipe. The unpublished local line had genesis.json, RUN-A-NODE.md and the measured claims, but predated the anchor. This commit carries the package files onto the anchor line: - genesis.json restored, byte for byte as the running nodes hold it - RUN-A-NODE.md restored; the basefee-floor patch returns as 0004; the anchor section states plainly that a build without patch 0003 has not been shown to import headers past block 13,014,000, and that an import proof for a patches-only build is the next thing this repository owes its reader - bootnodes are deliberately NOT published: today's entry points are consensus or origin hosts, and this project does not print its machines' addresses; a dedicated bootnode host is the planned replacement, an enode is available by mail until then
224 lines
9.7 KiB
Diff
224 lines
9.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aere Network <node@aere.network>
|
|
Date: Mon, 3 Aug 2026 04:00:00 +0300
|
|
Subject: [PATCH] Aere Network: fork-gated consensus floor for the EIP-1559
|
|
base fee
|
|
|
|
Adds a real consensus minimum base fee to LondonFeeMarket, gated on a fork
|
|
block. When the block number reaches aere.basefee.floor.forkBlock, the computed
|
|
EIP-1559 base fee is clamped to max(computed, aere.basefee.floor.value).
|
|
|
|
computeBaseFee is used for BOTH block production and block validation, so this
|
|
is a genuine consensus rule and not a display trick: every node must carry the
|
|
change, and a node without it computes the old, lower base fee and rejects the
|
|
floored block.
|
|
|
|
Default forkBlock is Long.MAX_VALUE, so with no configuration the behaviour is
|
|
identical to the unmodified file and pre-fork blocks validate unchanged.
|
|
|
|
NOT ACTIVE ON AERE NETWORK CHAIN 2800. No fork block has been set on mainnet.
|
|
Arming it is a governance decision that has not been taken.
|
|
|
|
Upstream-Status: Inappropriate [Aere Network specific consensus rule]
|
|
|
|
Modified upstream files. One file touched by this patch is a modified copy of a
|
|
Hyperledger Besu source, not new work by Aere Network:
|
|
|
|
ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java
|
|
|
|
Aere Network changed it, against upstream commit
|
|
d2032017bb3b8cb215a97303980a1e4a643f7180. Its original "Copyright ConsenSys AG"
|
|
header is kept unchanged, which is what Apache License 2.0 section 4(c)
|
|
requires, and this patch adds below it a separate "Modifications Copyright"
|
|
block naming exactly what was changed. That in-file block is the notice
|
|
required by Apache License 2.0 section 4(b). It travels inside the diff, so a
|
|
tree with this patch applied carries the notice whether you used git am or git
|
|
apply. This patch creates no new files.
|
|
|
|
Note that the copyright holder on this file is ConsenSys AG, not "contributors
|
|
to Hyperledger Besu" as on the files touched by patches 0001 and 0002. Both
|
|
holders are named in NOTICE, as Apache License 2.0 section 4(d) requires.
|
|
---
|
|
.../mainnet/feemarket/LondonFeeMarket.java | 48 +++++++++++++++++--
|
|
1 file changed, 45 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java
|
|
index 0ee4f74..83a639c 100644
|
|
--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java
|
|
+++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java
|
|
@@ -1,56 +1,87 @@
|
|
/*
|
|
* 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
|
|
*/
|
|
+
|
|
+/*
|
|
+ * Modifications Copyright 2026 Aere Network.
|
|
+ *
|
|
+ * This file was changed by Aere Network: a fork-gated consensus minimum for the
|
|
+ * EIP-1559 base fee was added. Two system properties configure it
|
|
+ * (aere.basefee.floor.forkBlock, aere.basefee.floor.value), a private helper
|
|
+ * applyAereBaseFeeFloor was added, and the three return paths of computeBaseFee
|
|
+ * now pass through that helper. The default fork block is Long.MAX_VALUE, so an
|
|
+ * unconfigured node behaves exactly as the unmodified file does. Nothing upstream
|
|
+ * was removed or rewritten.
|
|
+ *
|
|
+ * The unmodified original is Hyperledger Besu commit
|
|
+ * d2032017bb3b8cb215a97303980a1e4a643f7180. The upstream copyright header above is
|
|
+ * left exactly as it was found.
|
|
+ *
|
|
+ * This notice is required by Apache License 2.0 section 4(b).
|
|
+ */
|
|
package org.hyperledger.besu.ethereum.mainnet.feemarket;
|
|
|
|
import org.hyperledger.besu.config.GenesisConfig;
|
|
import org.hyperledger.besu.datatypes.Wei;
|
|
import org.hyperledger.besu.ethereum.core.Transaction;
|
|
import org.hyperledger.besu.ethereum.core.feemarket.TransactionPriceCalculator;
|
|
|
|
import java.util.Optional;
|
|
|
|
import org.apache.tuweni.units.bigints.UInt256s;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
public class LondonFeeMarket implements BaseFeeMarket {
|
|
private static final Logger LOG = LoggerFactory.getLogger(LondonFeeMarket.class);
|
|
|
|
static final Wei DEFAULT_BASEFEE_INITIAL_VALUE = GenesisConfig.BASEFEE_AT_GENESIS_DEFAULT_VALUE;
|
|
static final long DEFAULT_BASEFEE_MAX_CHANGE_DENOMINATOR = 8L;
|
|
static final long DEFAULT_SLACK_COEFFICIENT = 2L;
|
|
|
|
private static final Wei DEFAULT_BASEFEE_FLOOR = Wei.of(7L);
|
|
|
|
+ // === AERE base-fee floor fork (fork-gated, system-property configured) ===
|
|
+ // A real consensus minimum base fee, not a display trick. When the running block
|
|
+ // number reaches AERE_BASEFEE_FLOOR_FORK_BLOCK, the EIP-1559 base fee is clamped to
|
|
+ // max(computed, AERE_BASEFEE_FLOOR_VALUE). Because computeBaseFee is used for BOTH
|
|
+ // block production AND block validation, this is a genuine consensus rule: every node
|
|
+ // must agree, and a node without this change computes the old (lower) base fee and
|
|
+ // rejects the floored block. Default forkBlock = Long.MAX_VALUE => never active =>
|
|
+ // byte-identical behavior to stock Besu (pre-fork blocks are unchanged).
|
|
+ private static final long AERE_BASEFEE_FLOOR_FORK_BLOCK =
|
|
+ Long.getLong("aere.basefee.floor.forkBlock", Long.MAX_VALUE);
|
|
+ private static final Wei AERE_BASEFEE_FLOOR_VALUE =
|
|
+ Wei.of(Long.getLong("aere.basefee.floor.value", 1_000_000_000L));
|
|
+
|
|
protected final Wei baseFeeInitialValue;
|
|
private final long londonForkBlockNumber;
|
|
private final TransactionPriceCalculator txPriceCalculator;
|
|
private final Wei baseFeeFloor;
|
|
|
|
LondonFeeMarket(final long londonForkBlockNumber, final Optional<Wei> baseFeePerGasOverride) {
|
|
this(TransactionPriceCalculator.eip1559(), londonForkBlockNumber, baseFeePerGasOverride);
|
|
}
|
|
|
|
LondonFeeMarket(
|
|
final TransactionPriceCalculator txPriceCalculator,
|
|
final long londonForkBlockNumber,
|
|
final Optional<Wei> baseFeePerGasOverride) {
|
|
this.txPriceCalculator = txPriceCalculator;
|
|
this.londonForkBlockNumber = londonForkBlockNumber;
|
|
this.baseFeeInitialValue = baseFeePerGasOverride.orElse(DEFAULT_BASEFEE_INITIAL_VALUE);
|
|
this.baseFeeFloor = baseFeeInitialValue.isZero() ? Wei.ZERO : DEFAULT_BASEFEE_FLOOR;
|
|
}
|
|
|
|
@Override
|
|
@@ -66,72 +97,83 @@ public class LondonFeeMarket implements BaseFeeMarket {
|
|
@Override
|
|
public long getSlackCoefficient() {
|
|
return DEFAULT_SLACK_COEFFICIENT;
|
|
}
|
|
|
|
@Override
|
|
public TransactionPriceCalculator getTransactionPriceCalculator() {
|
|
return txPriceCalculator;
|
|
}
|
|
|
|
@Override
|
|
public boolean satisfiesFloorTxFee(final Transaction txn) {
|
|
// ensure effective baseFee is at least above floor
|
|
return txn.getGasPrice()
|
|
.map(Optional::of)
|
|
.orElse(txn.getMaxFeePerGas())
|
|
.filter(fee -> fee.greaterOrEqualThan(baseFeeFloor))
|
|
.isPresent();
|
|
}
|
|
|
|
+ // AERE base-fee floor fork: clamp the computed base fee to the floor once the fork
|
|
+ // block is reached. No-op before the fork block (and always a no-op when the fork is
|
|
+ // unset, i.e. forkBlock = Long.MAX_VALUE), so pre-fork blocks validate byte-identically.
|
|
+ private Wei applyAereBaseFeeFloor(final long blockNumber, final Wei fee) {
|
|
+ if (blockNumber >= AERE_BASEFEE_FLOOR_FORK_BLOCK
|
|
+ && !fee.greaterOrEqualThan(AERE_BASEFEE_FLOOR_VALUE)) {
|
|
+ return AERE_BASEFEE_FLOOR_VALUE;
|
|
+ }
|
|
+ return fee;
|
|
+ }
|
|
+
|
|
@Override
|
|
public Wei computeBaseFee(
|
|
final long blockNumber,
|
|
final Wei parentBaseFee,
|
|
final long parentBlockGasUsed,
|
|
final long targetGasUsed) {
|
|
if (londonForkBlockNumber == blockNumber) {
|
|
- return getInitialBasefee();
|
|
+ return applyAereBaseFeeFloor(blockNumber, getInitialBasefee());
|
|
}
|
|
|
|
long gasDelta;
|
|
Wei feeDelta, baseFee;
|
|
if (parentBlockGasUsed == targetGasUsed) {
|
|
- return parentBaseFee;
|
|
+ return applyAereBaseFeeFloor(blockNumber, parentBaseFee);
|
|
} else if (parentBlockGasUsed > targetGasUsed) {
|
|
gasDelta = parentBlockGasUsed - targetGasUsed;
|
|
final long denominator = getBasefeeMaxChangeDenominator();
|
|
feeDelta =
|
|
UInt256s.max(
|
|
parentBaseFee.multiply(gasDelta).divide(targetGasUsed).divide(denominator), Wei.ONE);
|
|
baseFee = parentBaseFee.add(feeDelta);
|
|
} else {
|
|
gasDelta = targetGasUsed - parentBlockGasUsed;
|
|
final long denominator = getBasefeeMaxChangeDenominator();
|
|
feeDelta = parentBaseFee.multiply(gasDelta).divide(targetGasUsed).divide(denominator);
|
|
baseFee = parentBaseFee.subtract(feeDelta);
|
|
}
|
|
LOG.trace(
|
|
"block #{} parentBaseFee: {} parentGasUsed: {} parentGasTarget: {} baseFee: {}",
|
|
blockNumber,
|
|
parentBaseFee,
|
|
parentBlockGasUsed,
|
|
targetGasUsed,
|
|
baseFee);
|
|
- return baseFee;
|
|
+ return applyAereBaseFeeFloor(blockNumber, baseFee);
|
|
}
|
|
|
|
@Override
|
|
public ValidationMode baseFeeValidationMode(final long blockNumber) {
|
|
return londonForkBlockNumber == blockNumber ? ValidationMode.INITIAL : ValidationMode.ONGOING;
|
|
}
|
|
|
|
@Override
|
|
public ValidationMode gasLimitValidationMode(final long blockNumber) {
|
|
return londonForkBlockNumber == blockNumber ? ValidationMode.INITIAL : ValidationMode.ONGOING;
|
|
}
|
|
|
|
@Override
|
|
public boolean isBeforeForkBlock(final long blockNumber) {
|
|
return londonForkBlockNumber > blockNumber;
|
|
}
|
|
}
|