@Test(expected = IllegalArgumentException.class) public void appendBlockWithMismatchedReceipts() { final BlockDataGenerator gen = new BlockDataGenerator(); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); final DefaultMutableBlockchain blockchain = createBlockchain(kvStore, genesisBlock); final BlockOptions options = new BlockOptions().setBlockNumber(1L).setParentHash(genesisBlock.getHash()); final Block newBlock = gen.block(options); final List<TransactionReceipt> receipts = gen.receipts(newBlock); receipts.add(gen.receipt()); blockchain.appendBlock(newBlock, receipts); }
@Test public void createSmallChain() { final BlockDataGenerator gen = new BlockDataGenerator(); final List<Block> chain = gen.blockSequence(3); final List<List<TransactionReceipt>> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); final DefaultMutableBlockchain blockchain = createBlockchain(kvStore, chain.get(0)); for (int i = 1; i < chain.size(); i++) { blockchain.appendBlock(chain.get(i), blockReceipts.get(i)); } for (int i = 1; i < chain.size(); i++) { assertBlockDataIsStored(blockchain, chain.get(i), blockReceipts.get(i)); } final Block head = chain.get(chain.size() - 1); assertBlockIsHead(blockchain, head); assertTotalDifficultiesAreConsistent(blockchain, head); assertThat(blockchain.getForks()).isEmpty(); }
@Test public void transactionRoundTrip() { // Setup list of transactions final int txCount = 20; final BlockDataGenerator gen = new BlockDataGenerator(1); final List<Transaction> transactions = new ArrayList<>(); for (int i = 0; i < txCount; ++i) { transactions.add(gen.transaction()); } // Create TransactionsMessage final MessageData initialMessage = TransactionsMessage.create(transactions); // Read message into a generic RawMessage final MessageData raw = new RawMessage(EthPV62.TRANSACTIONS, initialMessage.getData()); // Transform back to a TransactionsMessage from RawMessage final TransactionsMessage message = TransactionsMessage.readFrom(raw); // Check that transactions match original inputs after transformations final Iterator<Transaction> readTransactions = message.transactions(Transaction::readFrom); for (int i = 0; i < txCount; ++i) { Assertions.assertThat(readTransactions.next()).isEqualTo(transactions.get(i)); } Assertions.assertThat(readTransactions.hasNext()).isFalse(); } }
@Test public void getReceiptsStream() throws PeerNotConnected { final ResponseStreamSupplier getStream = (peer) -> peer.getReceipts(asList(gen.hash(), gen.hash())); final MessageData targetMessage = ReceiptsMessage.create(singletonList(gen.receipts(gen.block()))); final MessageData otherMessage = BlockHeadersMessage.create(asList(gen.header(), gen.header())); messageStream(getStream, targetMessage, otherMessage); }
@Test public void getBodiesStream() throws PeerNotConnected { final ResponseStreamSupplier getStream = (peer) -> peer.getBodies(asList(gen.hash(), gen.hash())); final MessageData targetMessage = BlockBodiesMessage.create(asList(gen.body(), gen.body())); final MessageData otherMessage = BlockHeadersMessage.create(asList(gen.header(), gen.header())); messageStream(getStream, targetMessage, otherMessage); }
@Test public void getNodeDataStream() throws PeerNotConnected { final ResponseStreamSupplier getStream = (peer) -> peer.getNodeData(asList(gen.hash(), gen.hash())); final MessageData targetMessage = NodeDataMessage.create(singletonList(gen.bytesValue())); final MessageData otherMessage = BlockHeadersMessage.create(asList(gen.header(), gen.header())); messageStream(getStream, targetMessage, otherMessage); }
@Test public void reorgWithOverlappingTransactions() { final BlockDataGenerator gen = new BlockDataGenerator(1); final List<Block> chain = gen.blockSequence(chainLength); final List<List<TransactionReceipt>> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); .setDifficulty(chain.get(forkBlock).getHeader().getDifficulty().plus(10L)) .addTransaction(overlappingTx) .addTransaction(gen.transaction()); final Block fork = gen.block(options); final List<TransactionReceipt> forkReceipts = gen.receipts(fork); final List<Block> reorgedChain = new ArrayList<>(chain.subList(0, forkBlock)); reorgedChain.add(fork);
private void recordNewBlockEvent() { filterManager.recordBlockEvent( BlockAddedEvent.createForHeadAdvancement(new BlockDataGenerator().block()), blockchainQueries.getBlockchain()); }
@Test(expected = IllegalArgumentException.class) public void initializeExistingWithWrongGenesisBlock() { final BlockDataGenerator gen = new BlockDataGenerator(); // Write to kv store final KeyValueStorage kvStore = new InMemoryKeyValueStorage(); final Block genesisBlock = gen.genesisBlock(); createBlockchain(kvStore, genesisBlock); // Initialize a new blockchain store with same kvStore, but different genesis block createBlockchain(kvStore, gen.genesisBlock()); }
@BeforeClass public static void setupClass() { genesisBlock = blockDataGenerator.genesisBlock(); localBlockchain = createInMemoryBlockchain(genesisBlock); // 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<TransactionReceipt> receipts = blockDataGenerator.receipts(block); localBlockchain.appendBlock(block, receipts); } }
@Test public void appendBlockWithReorgToLongerChain() { final BlockDataGenerator gen = new BlockDataGenerator(2); final List<Block> chain = gen.blockSequence(originalChainLength); final List<List<TransactionReceipt>> blockReceipts = chain.stream().map(gen::receipts).collect(Collectors.toList()); .setBlockNumber(forkStart) .setDifficulty(chain.get(forkStart).getHeader().getDifficulty().minus(5L)); forkBlocks.add(gen.block(options)); .setBlockNumber(forkStart + 1) .setDifficulty(UInt256.of(10L)); forkBlocks.add(gen.block(options));
@Test public void registerSiblingBlocks() { final BlockDataGenerator gen = new BlockDataGenerator(); final Block parentBlock = gen.block(); final Block childBlock = gen.nextBlock(parentBlock); final Block childBlock2 = gen.nextBlock(parentBlock); final List<Block> children = Arrays.asList(childBlock, childBlock2); pendingBlocks.registerPendingBlock(childBlock); pendingBlocks.registerPendingBlock(childBlock2); assertThat(pendingBlocks.contains(childBlock.getHash())).isTrue(); assertThat(pendingBlocks.contains(childBlock2.getHash())).isTrue(); final List<Block> pendingBlocksForParent = pendingBlocks.childrenOf(parentBlock.getHash()); assertThat(pendingBlocksForParent.size()).isEqualTo(2); assertThat(new HashSet<>(pendingBlocksForParent)).isEqualTo(new HashSet<>(children)); }
gen = new BlockDataGenerator(); final Block chainHead = localBlockchain.getChainHeadBlock(); final Block forkBlock = gen.block(gen.nextBlockOptions(chainHead).setDifficulty(UInt256.of(0L))); localBlockchain.appendBlock(forkBlock, gen.receipts(forkBlock));
.setBlockNumber(i) .setParentHash(localBlockchain.getBlockHashByNumber(i - 1).get()); final Block block00 = blockDataGenerator.block(options00); final List<TransactionReceipt> receipts00 = blockDataGenerator.receipts(block00); localBlockchain.appendBlock(block00, receipts00); .setBlockNumber(i) .setParentHash(remoteBlockchain.getBlockHashByNumber(i - 1).get()); final Block block01 = blockDataGenerator.block(options01); final List<TransactionReceipt> receipts01 = blockDataGenerator.receipts(block01); remoteBlockchain.appendBlock(block01, receipts01);
@Test public void roundTripTest() { // Generate some hashes final BlockDataGenerator gen = new BlockDataGenerator(1); final List<Hash> hashes = new ArrayList<>(); final int hashCount = 20; for (int i = 0; i < hashCount; ++i) { hashes.add(gen.hash()); } // Perform round-trip transformation // Create GetNodeData, copy it to a generic message, then read back into a GetNodeData message final MessageData initialMessage = GetNodeDataMessage.create(hashes); final MessageData raw = new RawMessage(EthPV63.GET_NODE_DATA, initialMessage.getData()); final GetNodeDataMessage message = GetNodeDataMessage.readFrom(raw); // Read hashes back out after round trip and check they match originals. final Iterator<Hash> readData = message.hashes().iterator(); for (int i = 0; i < hashCount; ++i) { Assertions.assertThat(readData.next()).isEqualTo(hashes.get(i)); } Assertions.assertThat(readData.hasNext()).isFalse(); } }
@Before public void setup() { gen = new BlockDataGenerator(1); }
@Test public void toFromRlp() { final BlockDataGenerator gen = new BlockDataGenerator(); final TransactionReceipt receipt = gen.receipt(); final TransactionReceipt copy = TransactionReceipt.readFrom(RLP.input(RLP.encode(receipt::writeTo))); assertEquals(receipt, copy); } }
@Test public void ignoresOldNewBlockAnnouncement() { final BlockDataGenerator gen = new BlockDataGenerator(); blockchainUtil.importFirstBlocks(10); final Block blockOne = blockchainUtil.getBlock(1); final Block oldBlock = gen.nextBlock(blockOne); // Sanity check assertThat(blockchain.contains(oldBlock.getHash())).isFalse(); final BlockPropagationManager<Void> propManager = spy(blockPropagationManager); propManager.start(); // Setup peer and messages final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 0); final NewBlockMessage oldAnnouncement = NewBlockMessage.create(oldBlock, UInt256.ZERO); // Broadcast EthProtocolManagerTestUtil.broadcastMessage(ethProtocolManager, peer, oldAnnouncement); final Responder responder = RespondingEthPeer.blockchainResponder(fullBlockchain); peer.respondWhile(responder, peer::hasOutstandingRequests); verify(propManager, times(0)).importOrSavePendingBlock(any()); assertThat(blockchain.contains(oldBlock.getHash())).isFalse(); }
private BlockchainWithData setupBlockchain( final int blocksToAdd, final List<Address> accountsToSetup, final List<UInt256> storageKeys) { checkArgument(blocksToAdd >= 1, "Must add at least one block to the queries"); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); // Generate some queries data final List<BlockData> blockData = new ArrayList<>(blocksToAdd); final List<Block> blocks = gen.blockSequence(blocksToAdd, worldStateArchive, accountsToSetup, storageKeys); for (int i = 0; i < blocksToAdd; i++) { final Block block = blocks.get(i); final List<TransactionReceipt> receipts = gen.receipts(block); blockData.add(new BlockData(block, receipts)); } // Setup blockchain final MutableBlockchain blockchain = createInMemoryBlockchain(blocks.get(0)); blockData .subList(1, blockData.size()) .forEach(b -> blockchain.appendBlock(b.block, b.receipts)); return new BlockchainWithData(blockchain, blockData, worldStateArchive); }
public static RespondingEthPeer create( final EthProtocolManager ethProtocolManager, final UInt256 totalDifficulty, final long estimatedHeight) { final Hash chainHeadHash = gen.hash(); return create(ethProtocolManager, chainHeadHash, totalDifficulty, estimatedHeight); }