diff --git a/ethereum/core/src/main/java/net/consensys/pantheon/ethereum/util/BlockchainUtil.java b/ethereum/core/src/main/java/net/consensys/pantheon/ethereum/util/BlockchainUtil.java deleted file mode 100644 index e0faac6ee2..0000000000 --- a/ethereum/core/src/main/java/net/consensys/pantheon/ethereum/util/BlockchainUtil.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.consensys.pantheon.ethereum.util; - -import tech.pegasys.pantheon.ethereum.chain.Blockchain; -import tech.pegasys.pantheon.ethereum.core.BlockHeader; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.OptionalInt; - -public class BlockchainUtil { - - private BlockchainUtil() {} - - /** - * General purpose utility to process a list of headers and a blockchain, sussing out which header - * in the input list is simultaneously the highest order block number and a direct match with one - * of the headers of the local chain. The point being to determine the point of departure in fork - * situations. - * - * @param blockchain our local copy of the blockchain - * @param headers the list of remote headers - * @param ascendingHeaderOrder whether the headers are sorted in ascending or descending order - * @return index of the highest known header, or an empty value if no header is known - */ - public static OptionalInt findHighestKnownBlockIndex( - final Blockchain blockchain, - final List headers, - final boolean ascendingHeaderOrder) { - int offset = ascendingHeaderOrder ? -1 : 0; - Comparator comparator = knownBlockComparator(blockchain, ascendingHeaderOrder); - - int insertionIndex = -Collections.binarySearch(headers, null, comparator) - 1; - int ancestorIndex = insertionIndex + offset; - if (ancestorIndex < 0 || ancestorIndex >= headers.size()) { - return OptionalInt.empty(); - } - return OptionalInt.of(ancestorIndex); - } - - private static Comparator knownBlockComparator( - final Blockchain blockchain, final boolean ascendingHeaderOrder) { - Comparator comparator = - (final BlockHeader element0, final BlockHeader element1) -> { - if (element0 == null) { - return blockchain.contains(element1.getHash()) ? -1 : 1; - } - return blockchain.contains(element0.getHash()) ? 1 : -1; - }; - return ascendingHeaderOrder ? comparator.reversed() : comparator; - } -} diff --git a/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/util/BlockchainUtilParameterizedTest.java b/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/util/BlockchainUtilParameterizedTest.java deleted file mode 100755 index eb93e424bc..0000000000 --- a/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/util/BlockchainUtilParameterizedTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package net.consensys.pantheon.ethereum.util; - -import static org.assertj.core.api.Assertions.assertThat; - -import tech.pegasys.pantheon.ethereum.core.Block; -import tech.pegasys.pantheon.ethereum.core.BlockBody; -import tech.pegasys.pantheon.ethereum.core.BlockHeader; -import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; -import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain; -import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction; -import tech.pegasys.pantheon.ethereum.testutil.BlockDataGenerator; -import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; -import tech.pegasys.pantheon.services.kvstore.KeyValueStorage; -import tech.pegasys.pantheon.util.uint.UInt256; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.OptionalInt; -import java.util.Random; - -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class BlockchainUtilParameterizedTest { - private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); - private static final Random random = new Random(1337); - - private static final int chainHeight = 89; - private final int commonAncestorHeight; - private static Block genesisBlock; - private static KeyValueStorage localKvStore; - private static DefaultMutableBlockchain localBlockchain; - - private KeyValueStorage remoteKvStore; - private DefaultMutableBlockchain remoteBlockchain; - - private BlockHeader commonHeader; - private List headers; - - public BlockchainUtilParameterizedTest(final int commonAncestorHeight) { - this.commonAncestorHeight = commonAncestorHeight; - } - - @BeforeClass - public static void setupClass() { - genesisBlock = blockDataGenerator.genesisBlock(); - localKvStore = new InMemoryKeyValueStorage(); - localBlockchain = - new DefaultMutableBlockchain( - genesisBlock, localKvStore, MainnetBlockHashFunction::createHash); - // Setup local chain. - for (int i = 1; i <= chainHeight; i++) { - final BlockDataGenerator.BlockOptions options = - new BlockDataGenerator.BlockOptions() - .setBlockNumber(i) - .setParentHash(localBlockchain.getBlockHashByNumber(i - 1).get()); - final Block block = blockDataGenerator.block(options); - final List receipts = blockDataGenerator.receipts(block); - localBlockchain.appendBlock(block, receipts); - } - } - - @Before - public void setup() { - remoteKvStore = new InMemoryKeyValueStorage(); - remoteBlockchain = - new DefaultMutableBlockchain( - genesisBlock, remoteKvStore, MainnetBlockHashFunction::createHash); - - commonHeader = genesisBlock.getHeader(); - for (long i = 1; i <= commonAncestorHeight; i++) { - commonHeader = localBlockchain.getBlockHeader(i).get(); - final List receipts = - localBlockchain.getTxReceipts(commonHeader.getHash()).get(); - final BlockBody commonBody = localBlockchain.getBlockBody(commonHeader.getHash()).get(); - remoteBlockchain.appendBlock(new Block(commonHeader, commonBody), receipts); - } - // Remaining blocks are disparate. - for (long i = commonAncestorHeight + 1L; i <= chainHeight; i++) { - final BlockDataGenerator.BlockOptions localOptions = - new BlockDataGenerator.BlockOptions() - .setBlockNumber(i) - .setParentHash(localBlockchain.getBlockHashByNumber(i - 1).get()); - final Block localBlock = blockDataGenerator.block(localOptions); - final List localReceipts = blockDataGenerator.receipts(localBlock); - localBlockchain.appendBlock(localBlock, localReceipts); - - final BlockDataGenerator.BlockOptions remoteOptions = - new BlockDataGenerator.BlockOptions() - .setDifficulty(UInt256.ONE) // differentiator - .setBlockNumber(i) - .setParentHash(remoteBlockchain.getBlockHashByNumber(i - 1).get()); - final Block remoteBlock = blockDataGenerator.block(remoteOptions); - final List remoteReceipts = blockDataGenerator.receipts(remoteBlock); - remoteBlockchain.appendBlock(remoteBlock, remoteReceipts); - } - headers = new ArrayList<>(); - for (long i = 0L; i <= remoteBlockchain.getChainHeadBlockNumber(); i++) { - headers.add(remoteBlockchain.getBlockHeader(i).get()); - } - } - - @Parameterized.Parameters(name = "commonAncestor={0}") - public static Collection parameters() { - final List params = new ArrayList<>(); - params.add(new Object[] {0}); - params.add(new Object[] {chainHeight}); - params.add(new Object[] {random.nextInt(chainHeight - 1) + 1}); - params.add(new Object[] {random.nextInt(chainHeight - 1) + 1}); - params.add(new Object[] {random.nextInt(chainHeight - 1) + 1}); - return params; - } - - @Test - public void searchesAscending() { - OptionalInt maybeAncestorNumber = - BlockchainUtil.findHighestKnownBlockIndex(localBlockchain, headers, true); - assertThat(maybeAncestorNumber.getAsInt()).isEqualTo(Math.toIntExact(commonHeader.getNumber())); - } - - @Test - public void searchesDescending() { - Collections.reverse(headers); - OptionalInt maybeAncestorNumber = - BlockchainUtil.findHighestKnownBlockIndex(localBlockchain, headers, false); - assertThat(maybeAncestorNumber.getAsInt()) - .isEqualTo(Math.toIntExact(chainHeight - commonHeader.getNumber())); - } -}