Added block add event. (#637)

Added block reorg event.
Added revert reason to both events.
Added TransactionReceipt.

Signed-off-by: David Mechler <david.mechler@consensys.net>
pull/642/head
David Mechler 5 years ago committed by GitHub
parent 31246f8937
commit 061e24a5f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 62
      besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java
  2. 127
      besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java
  3. 3
      consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/IbftMiningCoordinatorTest.java
  4. 4
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/AutoTransactionLogBloomCachingService.java
  5. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/filter/FilterManagerLogFilterTest.java
  6. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/filter/FilterManagerTest.java
  7. 24
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractMiningCoordinatorTest.java
  8. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/BlockAddedEvent.java
  9. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainReorgObserver.java
  10. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java
  11. 7
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/TransactionReceipt.java
  12. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/TrailingPeerLimiterTest.java
  13. 2
      plugin-api/build.gradle
  14. 42
      plugin-api/src/main/java/org/hyperledger/besu/plugin/data/AddedBlockContext.java
  15. 58
      plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionReceipt.java
  16. 53
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java

@ -22,9 +22,11 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.LogTopic;
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.plugin.data.AddedBlockContext;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.PropagatedBlockContext;
@ -66,6 +68,38 @@ public class BesuEventsImpl implements BesuEvents {
blockBroadcaster.unsubscribePropagateNewBlocks(listenerIdentifier);
}
@Override
public long addBlockAddedListener(final BlockAddedListener listener) {
return blockchain.observeBlockAdded(
(event, chain) ->
listener.onBlockAdded(
blockAddedContext(
event.getBlock()::getHeader,
event.getBlock()::getBody,
event::getTransactionReceipts)));
}
@Override
public void removeBlockAddedListener(final long listenerIdentifier) {
blockchain.removeObserver(listenerIdentifier);
}
@Override
public long addBlockReorgListener(final BlockReorgListener listener) {
return blockchain.observeChainReorg(
(blockWithReceipts, chain) ->
listener.onBlockReorg(
blockAddedContext(
blockWithReceipts::getHeader,
blockWithReceipts.getBlock()::getBody,
blockWithReceipts::getReceipts)));
}
@Override
public void removeBlockReorgListener(final long listenerIdentifier) {
blockchain.removeObserver(listenerIdentifier);
}
@Override
public long addTransactionAddedListener(final TransactionAddedListener listener) {
return transactionPool.subscribePendingTransactions(listener::onTransactionAdded);
@ -109,11 +143,7 @@ public class BesuEventsImpl implements BesuEvents {
.collect(toUnmodifiableList());
final List<List<LogTopic>> besuTopics =
topics.stream()
.map(
subList ->
subList.stream()
.map(bytes -> LogTopic.wrap(bytes))
.collect(toUnmodifiableList()))
.map(subList -> subList.stream().map(LogTopic::wrap).collect(toUnmodifiableList()))
.collect(toUnmodifiableList());
final LogsQuery logsQuery = new LogsQuery(besuAddresses, besuTopics);
@ -152,4 +182,26 @@ public class BesuEventsImpl implements BesuEvents {
}
};
}
private static AddedBlockContext blockAddedContext(
final Supplier<BlockHeader> blockHeaderSupplier,
final Supplier<BlockBody> blockBodySupplier,
final Supplier<List<TransactionReceipt>> transactionReceiptsSupplier) {
return new AddedBlockContext() {
@Override
public BlockHeader getBlockHeader() {
return blockHeaderSupplier.get();
}
@Override
public BlockBody getBlockBody() {
return blockBodySupplier.get();
}
@Override
public List<TransactionReceipt> getTransactionReceipts() {
return transactionReceiptsSupplier.get();
}
};
}
}

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldState;
@ -50,6 +51,7 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.data.AddedBlockContext;
import org.hyperledger.besu.plugin.data.LogWithMetadata;
import org.hyperledger.besu.plugin.data.PropagatedBlockContext;
import org.hyperledger.besu.plugin.data.SyncStatus;
@ -228,6 +230,131 @@ public class BesuEventsImplTest {
serviceImpl.removeBlockPropagatedListener(5L);
}
@Test
public void addedBlockEventFiresAfterSubscribe() {
final AtomicReference<AddedBlockContext> result = new AtomicReference<>();
serviceImpl.addBlockAddedListener(result::set);
assertThat(result.get()).isNull();
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash()));
List<TransactionReceipt> transactionReceipts = gen.receipts(block);
blockchain.appendBlock(block, transactionReceipts);
assertThat(result.get()).isNotNull();
assertThat(result.get().getBlockHeader()).isEqualTo(block.getHeader());
assertThat(result.get().getTransactionReceipts()).isEqualTo(transactionReceipts);
}
@Test
public void addedBlockEventDoesNotFireAfterUnsubscribe() {
final AtomicReference<AddedBlockContext> result = new AtomicReference<>();
final long id = serviceImpl.addBlockAddedListener(result::set);
assertThat(result.get()).isNull();
serviceImpl.removeBlockAddedListener(id);
result.set(null);
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash()));
blockchain.appendBlock(block, gen.receipts(block));
assertThat(result.get()).isNull();
}
@Test
public void additionWithoutSubscriptionsCompletes() {
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash()));
blockchain.appendBlock(block, gen.receipts(block));
}
@Test
public void addedBlockEventUselessUnsubscribesCompletes() {
serviceImpl.removeBlockAddedListener(5);
serviceImpl.removeBlockAddedListener(5L);
}
@Test
public void reorgedBlockEventFiresAfterSubscribe() {
final AtomicReference<AddedBlockContext> result = new AtomicReference<>();
serviceImpl.addBlockReorgListener(result::set);
assertThat(result.get()).isNull();
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 1));
blockchain.appendBlock(block, gen.receipts(block));
assertThat(result.get()).isNull();
final var reorgBlock =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 2));
List<TransactionReceipt> transactionReceipts = gen.receipts(reorgBlock);
blockchain.appendBlock(reorgBlock, transactionReceipts);
assertThat(result.get()).isNotNull();
assertThat(result.get().getBlockHeader()).isEqualTo(reorgBlock.getHeader());
assertThat(result.get().getTransactionReceipts()).isEqualTo(transactionReceipts);
}
@Test
public void reorgedBlockEventDoesNotFireAfterUnsubscribe() {
final AtomicReference<AddedBlockContext> result = new AtomicReference<>();
final long id = serviceImpl.addBlockReorgListener(result::set);
assertThat(result.get()).isNull();
serviceImpl.removeBlockReorgListener(id);
result.set(null);
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 1));
blockchain.appendBlock(block, gen.receipts(block));
assertThat(result.get()).isNull();
final var reorgBlock =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 1));
blockchain.appendBlock(reorgBlock, gen.receipts(reorgBlock));
assertThat(result.get()).isNull();
}
@Test
public void reorgWithoutSubscriptionsCompletes() {
final var block =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 1));
blockchain.appendBlock(block, gen.receipts(block));
final var reorgBlock =
gen.block(
new BlockDataGenerator.BlockOptions()
.setParentHash(blockchain.getGenesisBlock().getHash())
.setBlockNumber(blockchain.getGenesisBlock().getHeader().getNumber() + 1));
List<TransactionReceipt> transactionReceipts = gen.receipts(reorgBlock);
blockchain.appendBlock(reorgBlock, transactionReceipts);
}
@Test
public void reorgedBlockEventUselessUnsubscribesCompletes() {
serviceImpl.removeBlockReorgListener(5);
serviceImpl.removeBlockReorgListener(5L);
}
@Test
public void transactionAddedEventFiresAfterSubscribe() {
final AtomicReference<Transaction> result = new AtomicReference<>();

@ -103,7 +103,8 @@ public class IbftMiningCoordinatorTest {
@Test
public void addsNewChainHeadEventWhenNewCanonicalHeadBlockEventReceived() throws Exception {
BlockAddedEvent headAdvancement =
BlockAddedEvent.createForHeadAdvancement(block, Collections.emptyList());
BlockAddedEvent.createForHeadAdvancement(
block, Collections.emptyList(), Collections.emptyList());
ibftMiningCoordinator.onBlockAdded(headAdvancement, blockChain);
assertThat(eventQueue.size()).isEqualTo(1);

@ -58,9 +58,9 @@ public class AutoTransactionLogBloomCachingService {
chainReorgSubscriptionId =
OptionalLong.of(
blockchain.observeChainReorg(
(header, __) ->
(blockWithReceipts, __) ->
transactionLogBloomCacher.cacheLogsBloomForBlockHeader(
header, Optional.empty(), true)));
blockWithReceipts.getHeader(), Optional.empty(), true)));
transactionLogBloomCacher
.getScheduler()

@ -37,6 +37,7 @@ import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -149,7 +150,9 @@ public class FilterManagerLogFilterTest {
final Block block = gen.block();
filterManager.recordBlockEvent(
BlockAddedEvent.createForHeadAdvancement(
block, LogWithMetadata.generate(block, gen.receipts(block), false)),
block,
LogWithMetadata.generate(block, gen.receipts(block), false),
Collections.emptyList()),
blockchainQueries.getBlockchain());
}

@ -233,7 +233,8 @@ public class FilterManagerTest {
new BlockDataGenerator.BlockOptions().setBlockNumber(blockNumber).setParentHash(parentHash);
currentBlock = blockGenerator.block(options);
filterManager.recordBlockEvent(
BlockAddedEvent.createForHeadAdvancement(currentBlock, Collections.emptyList()),
BlockAddedEvent.createForHeadAdvancement(
currentBlock, Collections.emptyList(), Collections.emptyList()),
blockchainQueries.getBlockchain());
return currentBlock.getHash();
}

@ -106,7 +106,9 @@ public class AbstractMiningCoordinatorTest {
miningCoordinator.start();
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@ -118,7 +120,9 @@ public class AbstractMiningCoordinatorTest {
miningCoordinator.start();
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verify(blockMiner).cancel();
verify(minerExecutor, times(2)).startAsyncMining(any(), any(), any());
@ -175,7 +179,9 @@ public class AbstractMiningCoordinatorTest {
miningCoordinator.start();
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@ -185,7 +191,9 @@ public class AbstractMiningCoordinatorTest {
miningCoordinator.enable();
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@ -198,7 +206,9 @@ public class AbstractMiningCoordinatorTest {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@ -213,7 +223,9 @@ public class AbstractMiningCoordinatorTest {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(BLOCK, Collections.emptyList()), blockchain);
BlockAddedEvent.createForHeadAdvancement(
BLOCK, Collections.emptyList(), Collections.emptyList()),
blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}

@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import java.util.Collections;
import java.util.List;
@ -27,6 +28,7 @@ public class BlockAddedEvent {
private final Block block;
private final List<Transaction> addedTransactions;
private final List<Transaction> removedTransactions;
private final List<TransactionReceipt> transactionReceipts;
private final EventType eventType;
private final List<LogWithMetadata> logsWithMetadata;
private final Hash commonAncestorHash;
@ -42,23 +44,28 @@ public class BlockAddedEvent {
final Block block,
final List<Transaction> addedTransactions,
final List<Transaction> removedTransactions,
final List<TransactionReceipt> transactionReceipts,
final List<LogWithMetadata> logsWithMetadata,
final Hash commonAncestorHash) {
this.eventType = eventType;
this.block = block;
this.addedTransactions = addedTransactions;
this.removedTransactions = removedTransactions;
this.transactionReceipts = transactionReceipts;
this.logsWithMetadata = logsWithMetadata;
this.commonAncestorHash = commonAncestorHash;
}
public static BlockAddedEvent createForHeadAdvancement(
final Block block, final List<LogWithMetadata> logsWithMetadata) {
final Block block,
final List<LogWithMetadata> logsWithMetadata,
final List<TransactionReceipt> transactionReceipts) {
return new BlockAddedEvent(
EventType.HEAD_ADVANCED,
block,
block.getBody().getTransactions(),
Collections.emptyList(),
transactionReceipts,
logsWithMetadata,
block.getHeader().getParentHash());
}
@ -67,6 +74,7 @@ public class BlockAddedEvent {
final Block block,
final List<Transaction> addedTransactions,
final List<Transaction> removedTransactions,
final List<TransactionReceipt> transactionReceipts,
final List<LogWithMetadata> logsWithMetadata,
final Hash commonAncestorHash) {
return new BlockAddedEvent(
@ -74,6 +82,7 @@ public class BlockAddedEvent {
block,
addedTransactions,
removedTransactions,
transactionReceipts,
logsWithMetadata,
commonAncestorHash);
}
@ -85,6 +94,7 @@ public class BlockAddedEvent {
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList(),
block.getHeader().getParentHash());
}
@ -108,6 +118,10 @@ public class BlockAddedEvent {
return removedTransactions;
}
public List<TransactionReceipt> getTransactionReceipts() {
return transactionReceipts;
}
public List<LogWithMetadata> getLogsWithMetadata() {
return logsWithMetadata;
}

@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.ethereum.chain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockWithReceipts;
public interface ChainReorgObserver {
void onBlockAdded(BlockHeader blockHeader, Blockchain blockchain);
void onBlockAdded(BlockWithReceipts blockWithReceipts, Blockchain blockchain);
}

@ -288,7 +288,8 @@ public class DefaultBlockchain implements MutableBlockchain {
return BlockAddedEvent.createForHeadAdvancement(
newBlock,
LogWithMetadata.generate(
blockWithReceipts.getBlock(), blockWithReceipts.getReceipts(), false));
blockWithReceipts.getBlock(), blockWithReceipts.getReceipts(), false),
blockWithReceipts.getReceipts());
} else if (totalDifficulty.compareTo(blockchainStorage.getTotalDifficulty(chainHead).get())
> 0) {
// New block represents a chain reorganization
@ -345,7 +346,7 @@ public class DefaultBlockchain implements MutableBlockchain {
newTransactions.put(
blockHash, currentNewChainWithReceipts.getBlock().getBody().getTransactions());
addAddedLogsWithMetadata(addedLogsWithMetadata, currentNewChainWithReceipts);
notifyChainReorgBlockAdded(currentNewChainWithReceipts.getHeader());
notifyChainReorgBlockAdded(currentNewChainWithReceipts);
currentNewChainWithReceipts = getParentBlockWithReceipts(currentNewChainWithReceipts);
}
@ -401,6 +402,7 @@ public class DefaultBlockchain implements MutableBlockchain {
newChainHeadWithReceipts.getBlock(),
newTransactions.values().stream().flatMap(Collection::stream).collect(toList()),
removedTransactions,
newChainHeadWithReceipts.getReceipts(),
Stream.concat(removedLogsWithMetadata.stream(), addedLogsWithMetadata.stream())
.collect(Collectors.toUnmodifiableList()),
currentNewChainWithReceipts.getBlock().getHash());
@ -569,7 +571,7 @@ public class DefaultBlockchain implements MutableBlockchain {
blockAddedObservers.forEach(observer -> observer.onBlockAdded(event, this));
}
private void notifyChainReorgBlockAdded(final BlockHeader blockHeader) {
blockReorgObservers.forEach(observer -> observer.onBlockAdded(blockHeader, this));
private void notifyChainReorgBlockAdded(final BlockWithReceipts blockWithReceipts) {
blockReorgObservers.forEach(observer -> observer.onBlockAdded(blockWithReceipts, this));
}
}

@ -37,7 +37,7 @@ import org.apache.tuweni.bytes.Bytes;
* formats: logs, logs bloom, and cumulative gas used in the block. The TransactionReceiptType
* attribute is the best way to check which format has been used.
*/
public class TransactionReceipt {
public class TransactionReceipt implements org.hyperledger.besu.plugin.data.TransactionReceipt {
private static final int NONEXISTENT = -1;
@ -228,6 +228,7 @@ public class TransactionReceipt {
*
* @return the total amount of gas consumed in the block after the transaction has been processed
*/
@Override
public long getCumulativeGasUsed() {
return cumulativeGasUsed;
}
@ -237,6 +238,7 @@ public class TransactionReceipt {
*
* @return the logs generated by the transaction
*/
@Override
public List<Log> getLogs() {
return logs;
}
@ -246,6 +248,7 @@ public class TransactionReceipt {
*
* @return the logs bloom filter for the logs generated by the transaction
*/
@Override
public LogsBloomFilter getBloomFilter() {
return bloomFilter;
}
@ -255,6 +258,7 @@ public class TransactionReceipt {
*
* @return the status code if the transaction receipt is status-encoded; otherwise {@code -1}
*/
@Override
public int getStatus() {
return status;
}
@ -263,6 +267,7 @@ public class TransactionReceipt {
return transactionReceiptType;
}
@Override
public Optional<Bytes> getRevertReason() {
return revertReason;
}

@ -118,6 +118,7 @@ public class TrailingPeerLimiterTest {
new Block(
new BlockHeaderTestFixture().number(500).buildHeader(),
new BlockBody(emptyList(), emptyList())),
Collections.emptyList(),
Collections.emptyList());
trailingPeerLimiter.onBlockAdded(blockAddedEvent, blockchain);
@ -135,6 +136,7 @@ public class TrailingPeerLimiterTest {
new Block(
new BlockHeaderTestFixture().number(599).buildHeader(),
new BlockBody(emptyList(), emptyList())),
Collections.emptyList(),
Collections.emptyList());
trailingPeerLimiter.onBlockAdded(blockAddedEvent, blockchain);

@ -65,7 +65,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files
knownHash = 'xsbRG+RsUybzMTULPcsLugarMHFTU7ohQBKw44x2/zQ='
knownHash = 'fL4EQBDRXnw1hiUIUMscLxRG/uWznpZSNJGSIp9+mFo='
}
check.dependsOn('checkAPIChanges')

@ -0,0 +1,42 @@
/*
* 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.plugin.data;
import java.util.List;
/** The minimum set of data for a AddedBlockContext. */
public interface AddedBlockContext {
/**
* A {@link BlockHeader} object.
*
* @return A {@link BlockHeader}
*/
BlockHeader getBlockHeader();
/**
* A {@link BlockHeader} object.
*
* @return A {@link BlockHeader}
*/
BlockBody getBlockBody();
/**
* A list of transaction receipts for the added block.
*
* @return A List of {@link TransactionReceipt}
*/
List<? extends TransactionReceipt> getTransactionReceipts();
}

@ -0,0 +1,58 @@
/*
* 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.plugin.data;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
/** A transaction receipt, containing information pertaining a transaction execution. */
public interface TransactionReceipt {
/**
* Returns the total amount of gas consumed in the block after the transaction has been processed.
*
* @return the total amount of gas consumed in the block after the transaction has been processed
*/
long getCumulativeGasUsed();
/**
* Returns the logs generated by the transaction.
*
* @return the logs generated by the transaction
*/
List<? extends Log> getLogs();
/**
* Returns the Bytes for the logs generated by the transaction
*
* @return the Bytes for the logs generated by the transaction
*/
Bytes getBloomFilter();
/**
* Returns the status code for the status-encoded transaction receipt
*
* @return the status code if the transaction receipt is status-encoded; otherwise {@code -1}
*/
int getStatus();
/**
* Returns the ABI-encoded revert reason for the failed transaction (if applicable)
*
* @return the ABI-encoded revert reason for the failed transaction (if applicable)
*/
Optional<Bytes> getRevertReason();
}

@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.plugin.services;
import org.hyperledger.besu.plugin.data.AddedBlockContext;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.LogWithMetadata;
import org.hyperledger.besu.plugin.data.PropagatedBlockContext;
@ -57,6 +58,36 @@ public interface BesuEvents {
*/
void removeBlockPropagatedListener(long listenerIdentifier);
/**
* Add a listener watching for new blocks added.
*
* @param blockAddedListener The listener that will accept the Block object as the event.
* @return an id to be used as an identifier when de-registering the event.
*/
long addBlockAddedListener(BlockAddedListener blockAddedListener);
/**
* Remove the block added listener from besu notifications.
*
* @param listenerIdentifier The id that was returned from addBlockAddedListener;
*/
void removeBlockAddedListener(long listenerIdentifier);
/**
* Add a listener watching for new reorg blocks added.
*
* @param blockReorgListener The listener that will accept the reorg Block object as the event.
* @return an id to be used as an identifier when de-registering the event.
*/
long addBlockReorgListener(BlockReorgListener blockReorgListener);
/**
* Remove the block reorg listener from besu notifications.
*
* @param listenerIdentifier The id that was returned from addBlockReorgListener;
*/
void removeBlockReorgListener(long listenerIdentifier);
/**
* Add a listener watching new transactions added to the node.
*
@ -138,6 +169,28 @@ public interface BesuEvents {
void onBlockPropagated(PropagatedBlockContext propagatedBlockContext);
}
/** The listener interface for receiving new block added events. */
interface BlockAddedListener {
/**
* Invoked when a new block has been evaluated and validated.
*
* @param addedBlockContext block being added.
*/
void onBlockAdded(AddedBlockContext addedBlockContext);
}
/** The listener interface for receiving new block reorg events. */
interface BlockReorgListener {
/**
* Invoked when a reorg block has been evaluated and validated.
*
* @param addedBlockContext reorg block being added.
*/
void onBlockReorg(AddedBlockContext addedBlockContext);
}
/** The listener interface for receiving new transaction added events. */
interface TransactionAddedListener {

Loading…
Cancel
Save