Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### Bug fixes
- Fix tracing in precompiled contracts when halting for out of gas [#7318](https://github.com/hyperledger/besu/issues/7318)
- Correctly release txpool save and restore lock in case of exceptions [#7473](https://github.com/hyperledger/besu/pull/7473)
- Fix for `eth_gasPrice` could not retrieve block error [#7482](https://github.com/hyperledger/besu/pull/7482)

## 24.8.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
Expand Down Expand Up @@ -976,27 +977,35 @@ public <U> Optional<U> getAndMapWorldState(
}

public Wei gasPrice() {
final long blockHeight = headBlockNumber();
final var chainHeadHeader = blockchain.getChainHeadHeader();
final Block chainHeadBlock = blockchain.getChainHeadBlock();
final var chainHeadHeader = chainHeadBlock.getHeader();
final long blockHeight = chainHeadHeader.getNumber();

final var nextBlockProtocolSpec =
protocolSchedule.getForNextBlockHeader(chainHeadHeader, System.currentTimeMillis());
final var nextBlockFeeMarket = nextBlockProtocolSpec.getFeeMarket();

final Wei[] gasCollection =
LongStream.rangeClosed(
Math.max(0, blockHeight - apiConfig.getGasPriceBlocks() + 1), blockHeight)
.mapToObj(
l ->
blockchain
.getBlockByNumber(l)
.map(Block::getBody)
.map(BlockBody::getTransactions)
.orElseThrow(
() -> new IllegalStateException("Could not retrieve block #" + l)))
Stream.concat(
LongStream.range(
Math.max(0, blockHeight - apiConfig.getGasPriceBlocks() + 1), blockHeight)
.mapToObj(
l ->
blockchain
.getBlockByNumber(l)
.orElseThrow(
() ->
new IllegalStateException(
"Could not retrieve block #" + l))),
Stream.of(chainHeadBlock))
.map(Block::getBody)
.map(BlockBody::getTransactions)
.flatMap(Collection::stream)
.filter(t -> t.getGasPrice().isPresent())
.map(t -> t.getGasPrice().get())
.sorted()
.toArray(Wei[]::new);

return (gasCollection == null || gasCollection.length == 0)
? gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket)
: UInt256s.max(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -61,7 +63,6 @@
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.internal.verification.VerificationModeFactory;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -106,8 +107,8 @@ public void shouldReturnMinValueWhenNoTransactionsExist() {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);

verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
verify(blockchain).getChainHeadBlock();
verify(blockchain, times(99)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}

Expand All @@ -127,8 +128,7 @@ public void shouldReturnBaseFeeAsMinValueOnGenesis() {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);

verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(1)).getBlockByNumber(anyLong());
verify(blockchain).getChainHeadBlock();
verifyNoMoreInteractions(blockchain);
}

Expand All @@ -146,8 +146,8 @@ public void shouldReturnMedianWhenTransactionsExist() {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);

verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
verify(blockchain).getChainHeadBlock();
verify(blockchain, times(99)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}

Expand All @@ -165,8 +165,8 @@ public void shortChainQueriesAllBlocks() {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);

verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(81)).getBlockByNumber(anyLong());
verify(blockchain).getChainHeadBlock();
verify(blockchain, times(80)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}

Expand Down Expand Up @@ -252,8 +252,7 @@ public void ethGasPriceAtGenesis(
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);

verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(1)).getBlockByNumber(anyLong());
verify(blockchain).getChainHeadBlock();
verifyNoMoreInteractions(blockchain);
}

Expand Down Expand Up @@ -328,12 +327,14 @@ private void mockBlockchain(
blocksByNumber.put(i, createFakeBlock(i, txsNum, baseFee));
}

when(blockchain.getChainHeadBlockNumber()).thenReturn(chainHeadBlockNumber);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(
invocation -> Optional.of(blocksByNumber.get(invocation.getArgument(0, Long.class))));

when(blockchain.getChainHeadHeader())
when(blockchain.getChainHeadBlock()).thenReturn(blocksByNumber.get(chainHeadBlockNumber));
if (chainHeadBlockNumber > 1) {
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(
invocation -> Optional.of(blocksByNumber.get(invocation.getArgument(0, Long.class))));
}
lenient()
.when(blockchain.getChainHeadHeader())
.thenReturn(blocksByNumber.get(chainHeadBlockNumber).getHeader());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ default boolean contains(final Hash blockHash) {
*/
Optional<BlockBody> getBlockBody(Hash blockHeaderHash);

/**
* Safe version of {@code getBlockBody} (it should take any locks necessary to ensure any block
* updates that might be taking place have been completed first)
*
* @param blockHeaderHash The hash of the block whose header we want to retrieve.
* @return The block body corresponding to this block hash.
*/
Optional<BlockBody> getBlockBodySafe(Hash blockHeaderHash);

/**
* Given a block's hash, returns the list of transaction receipts associated with this block's
* transactions. Associated block is not necessarily on the canonical chain.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,10 @@ public BlockHeader getChainHeadHeader() {

@Override
public Block getChainHeadBlock() {
return new Block(chainHeader, blockchainStorage.getBlockBody(chainHeader.getHash()).get());
return new Block(
chainHeader,
getBlockBody(chainHeader.getHash())
.orElseGet(() -> getBlockBodySafe(chainHeader.getHash()).get()));
}

@Override
Expand Down Expand Up @@ -337,6 +340,11 @@ public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
.orElseGet(() -> blockchainStorage.getBlockBody(blockHeaderHash));
}

@Override
public synchronized Optional<BlockBody> getBlockBodySafe(final Hash blockHeaderHash) {
return getBlockBody(blockHeaderHash);
}

@Override
public Optional<List<TransactionReceipt>> getTxReceipts(final Hash blockHeaderHash) {
return transactionReceiptsCache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
throw new UnsupportedOperationException();
}

@Override
public synchronized Optional<BlockBody> getBlockBodySafe(final Hash blockHeaderHash) {
return getBlockBody(blockHeaderHash);
}

@Override
public Optional<List<TransactionReceipt>> getTxReceipts(final Hash blockHeaderHash) {
// Deterministic, but just not implemented.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ public Optional<BlockBody> getBlockBody(final Hash blockHeaderHash) {
throw new UnsupportedOperationException();
}

@Override
public synchronized Optional<BlockBody> getBlockBodySafe(final Hash blockHeaderHash) {
return getBlockBody(blockHeaderHash);
}

@Override
public Optional<List<TransactionReceipt>> getTxReceipts(final Hash blockHeaderHash) {
// Deterministic, but just not implemented.
Expand Down