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

fee history #2466

Merged
merged 40 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
62dd31f
beginning
RatanRSur Jun 14, 2021
ec78644
fee history class and other stuff
RatanRSur Jun 14, 2021
27a79f1
get first 3 fields working
RatanRSur Jun 14, 2021
e250c30
add a bunch of stuff to the failing test
RatanRSur Jun 14, 2021
22dd003
add headers
RatanRSur Jun 14, 2021
dedf4dc
spotless
RatanRSur Jun 14, 2021
b5a6470
get all fields test working
RatanRSur Jun 16, 2021
3f7ac5f
0 for base fee
RatanRSur Jun 16, 2021
97a147c
add extra base fee
RatanRSur Jun 17, 2021
1470c40
update names to latest spec
RatanRSur Jun 17, 2021
7f61250
test block count higher than chain head
RatanRSur Jun 17, 2021
70fdcca
add test for all zeros
RatanRSur Jun 17, 2021
15ce6b5
error on block too high
RatanRSur Jun 17, 2021
8b3a7e0
spotless
RatanRSur Jun 17, 2021
4a4a354
get rpc spec test wired up and failing
RatanRSur Jun 17, 2021
ad89e50
fix tests
RatanRSur Jun 17, 2021
d0051dc
spotless
RatanRSur Jun 17, 2021
60b5184
sorting and comments
RatanRSur Jun 17, 2021
c55e7a9
remove redundant assignment
RatanRSur Jun 17, 2021
760338f
fix transaction selector
RatanRSur Jun 17, 2021
b169d79
make test presume 1559
RatanRSur Jun 17, 2021
cfb06bc
fix range errors
RatanRSur Jun 17, 2021
253259f
switch to Immutable
RatanRSur Jun 17, 2021
7ba5890
add fork block stuff
RatanRSur Jun 17, 2021
783ac54
spotless
RatanRSur Jun 17, 2021
4c89cdf
Merge branch 'master' of github.com:hyperledger/besu into fee-history
RatanRSur Jun 17, 2021
8aa77a6
test upper bound for block count
RatanRSur Jun 17, 2021
4aa9cc5
cleanup
RatanRSur Jun 17, 2021
07f5f71
Merge branch 'master' of github.com:hyperledger/besu into fee-history
RatanRSur Jun 21, 2021
ae2c951
fix reorg tests
RatanRSur Jun 21, 2021
3afe531
Merge branch 'master' of github.com:hyperledger/besu into fee-history
RatanRSur Jun 21, 2021
cc96aad
fix tests
RatanRSur Jun 21, 2021
b07979c
fix epfpg calc
RatanRSur Jun 21, 2021
89cdd45
fix lambda names
RatanRSur Jun 22, 2021
a65895d
remove unnecessary check
RatanRSur Jun 22, 2021
47de7f9
changelog
RatanRSur Jun 22, 2021
ce02ef3
Merge branch 'master' into fee-history
garyschulte Jun 22, 2021
7e31430
Merge branch 'master' of github.com:hyperledger/besu into fee-history
RatanRSur Jun 22, 2021
a098f81
update ref tests
RatanRSur Jun 22, 2021
96bc38c
changelog
RatanRSur Jun 22, 2021
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
Prev Previous commit
Next Next commit
add extra base fee
Signed-off-by: Ratan Rai Sur <ratan.r.sur@gmail.com>
  • Loading branch information
RatanRSur committed Jun 17, 2021
commit 97a147c9b69887e99b8e0bd29c74d166f3d88b8e
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,25 @@
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.LongStream;
import java.util.stream.Stream;

public class EthFeeHistory implements JsonRpcMethod {
private final ProtocolSchedule protocolSchedule;
private final BlockchainQueries blockchainQueries;
private final Blockchain blockchain;

public EthFeeHistory(final BlockchainQueries blockchainQueries) {
public EthFeeHistory(
final ProtocolSchedule protocolSchedule, final BlockchainQueries blockchainQueries) {
this.protocolSchedule = protocolSchedule;
this.blockchainQueries = blockchainQueries;
this.blockchain = blockchainQueries.getBlockchain();
}
Expand All @@ -55,34 +61,56 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) {
final Optional<List<Double>> maybeRewardPercentiles =
request.getOptionalParameter(2, Double[].class).map(Arrays::asList);

final long resolvedBlockNumber =
final long resolvedHighestBlockNumber =
highestBlock
.getNumber()
.orElse(
highestBlock.isEarliest()
? BlockHeader.GENESIS_BLOCK_NUMBER
: blockchain
.getChainHeadBlockNumber() /* both latest and pending use the head block until we have pending block support */);
final long firstBlock = Math.max(0, resolvedBlockNumber - (blockCount - 1));
final long firstBlock = Math.max(0, resolvedHighestBlockNumber - (blockCount - 1));

final List<Long> baseFees =
final List<BlockHeader> blockHeaders =
LongStream.range(firstBlock, firstBlock + blockCount)
.mapToObj(blockchain::getBlockHeader)
.flatMap(Optional::stream)
.collect(toUnmodifiableList());

// we return the base fees for the blocks requested and 1 more because we can always compute it
final List<Long> explicitlyRequestedBaseFees =
LongStream.range(firstBlock, firstBlock + blockCount)
.mapToObj(blockchain::getBlockHeader)
.map(
maybeBlockHeader ->
maybeBlockHeader.flatMap(ProcessableBlockHeader::getBaseFee).orElse(0L))
.collect(toUnmodifiableList());
final long nextBlockNumber = resolvedHighestBlockNumber + 1;
final Long nextBaseFee =
blockchain
.getBlockHeader(nextBlockNumber)
.map(blockHeader -> blockHeader.getBaseFee().orElse(0L))
.orElseGet(
() ->
protocolSchedule
.getByBlockNumber(nextBlockNumber)
.getEip1559()
.map(
eip1559 -> {
final BlockHeader lastBlockHeader =
blockHeaders.get(blockHeaders.size() - 1);
return eip1559.computeBaseFee(
nextBlockNumber,
explicitlyRequestedBaseFees.get(
explicitlyRequestedBaseFees.size() - 1),
lastBlockHeader.getGasUsed(),
eip1559.targetGasUsed(lastBlockHeader));
})
.orElse(0L));

final List<Double> gasUsedRatios =
LongStream.range(firstBlock, firstBlock + blockCount)
.mapToObj(blockchain::getBlockHeader)
.flatMap(
maybeBlockheader ->
maybeBlockheader
.map(
blockHeader ->
blockHeader.getGasUsed() / (double) blockHeader.getGasLimit())
.stream())
blockHeaders.stream()
.map(blockHeader -> blockHeader.getGasUsed() / (double) blockHeader.getGasLimit())
.collect(toUnmodifiableList());

final Optional<List<List<Long>>> maybeRewards =
Expand All @@ -95,7 +123,12 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) {

return new JsonRpcSuccessResponse(
request.getRequest().getId(),
new FeeHistory(firstBlock, baseFees, gasUsedRatios, maybeRewards));
new FeeHistory(
firstBlock,
Stream.concat(explicitlyRequestedBaseFees.stream(), Stream.of(nextBaseFee))
.collect(toUnmodifiableList()),
gasUsedRatios,
maybeRewards));
}

private List<Long> computeRewards(
Expand Down Expand Up @@ -167,6 +200,22 @@ public List<Double> getGasUsedRatios() {
return gasUsedRatios;
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final FeeHistory that = (FeeHistory) o;
return firstBlock == that.firstBlock
&& baseFees.equals(that.baseFees)
&& gasUsedRatios.equals(that.gasUsedRatios)
&& maybeRewards.equals(that.maybeRewards);
}

@Override
public int hashCode() {
return Objects.hash(firstBlock, baseFees, gasUsedRatios, maybeRewards);
}

@Override
public String toString() {
return String.format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.config.GenesisConfigOptions;
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.exception.InvalidJsonRpcParameters;
Expand All @@ -35,6 +36,12 @@
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.fees.EIP1559;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSpecs;
import org.hyperledger.besu.ethereum.mainnet.MutableProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DefaultWorldStateArchive;
Expand All @@ -43,17 +50,21 @@
import org.junit.Test;
import org.mockito.Mock;

import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;

public class EthFeeHistoryTest {
final BlockDataGenerator gen = new BlockDataGenerator();
private MutableBlockchain blockchain;
private BlockchainQueries blockchainQueries;
private EthFeeHistory method;
private ProtocolSchedule protocolSchedule;

@Before
public void setUp() {
protocolSchedule = mock(ProtocolSchedule.class);
final Block genesisBlock = gen.genesisBlock();
blockchain = createInMemoryBlockchain(genesisBlock);
gen.blockSequence(genesisBlock, 10)
Expand All @@ -64,7 +75,7 @@ public void setUp() {
new DefaultWorldStateArchive(
new WorldStateKeyValueStorage(new InMemoryKeyValueStorage()),
new WorldStatePreimageKeyValueStorage(new InMemoryKeyValueStorage())));
method = new EthFeeHistory(blockchainQueries);
method = new EthFeeHistory(protocolSchedule, blockchainQueries);
}

@Test
Expand All @@ -85,15 +96,18 @@ public void params() {
}

@Test
public void allFieldsPresentForLatestBlockGenerated() {
public void allFieldsPresentForLatestBlock() {
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
when(londonSpec.getEip1559()).thenReturn(Optional.of(new EIP1559(5)));
when(protocolSchedule.getByBlockNumber(eq(11L))).thenReturn(londonSpec);
assertThat(
((JsonRpcSuccessResponse)
method.response(feeHistoryRequestContext(1, "latest", new double[] {100.0})))
.getResult())
.isEqualTo(
new EthFeeHistory.FeeHistory(
10,
List.of(47177L),
List.of(47177L, 53074L),
List.of(0.9999999992132459),
Optional.of(List.of(List.of(1524742083L)))));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,13 @@ private ProcessableBlockHeader createPendingBlockHeader(final long timestamp) {
final EIP1559 eip1559 = protocolSpec.getEip1559().orElseThrow();
if (eip1559.isForkBlock(newBlockNumber)) {
gasLimit = gasLimit * eip1559.getFeeMarket().getSlackCoefficient();
baseFee = eip1559.getFeeMarket().getInitialBasefee();
} else {
baseFee =
eip1559.computeBaseFee(
newBlockNumber,
parentHeader.getBaseFee().orElseThrow(),
parentHeader.getGasUsed(),
eip1559.targetGasUsed(parentHeader));
}
baseFee =
eip1559.computeBaseFee(
newBlockNumber,
parentHeader.getBaseFee().orElseThrow(),
parentHeader.getGasUsed(),
eip1559.targetGasUsed(parentHeader));
}
return BlockHeaderBuilder.create()
.parentHash(parentHeader.getHash())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public long computeBaseFee(
final long parentBaseFee,
final long parentBlockGasUsed,
final long targetGasUsed) {
if (isForkBlock(blockNumber)) {
return getFeeMarket().getInitialBasefee();
}

long gasDelta, feeDelta, baseFee;
if (parentBlockGasUsed == targetGasUsed) {
return parentBaseFee;
Expand Down