You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuweni.apache.org by to...@apache.org on 2020/06/01 06:03:16 UTC

[incubator-tuweni] branch master updated (0c601c6 -> 42cf5ad)

This is an automated email from the ASF dual-hosted git repository.

toulmean pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git.


    from 0c601c6  remove println
     new afee6d7  move tests to integration tests
     new 42cf5ad  Add tests for getting headers

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 dependency-versions.gradle                         |   2 +
 devp2p-eth/build.gradle                            |   1 +
 .../tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt} |  28 ++-
 .../org/apache/tuweni/devp2p/eth/EthHandler.kt     |  39 ++--
 .../org/apache/tuweni/devp2p/eth/Messages.kt       |   8 +-
 .../org/apache/tuweni/devp2p/eth/EthHandlerTest.kt | 226 ++++++++++-----------
 .../tuweni/eth/repository/BlockchainIndex.kt       |   4 +-
 .../tuweni/eth/repository/BlockchainRepository.kt  |   9 +-
 8 files changed, 162 insertions(+), 155 deletions(-)
 copy devp2p-eth/src/{test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt => integrationTest/kotlin/org/apache/tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt} (91%)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tuweni.apache.org
For additional commands, e-mail: commits-help@tuweni.apache.org


[incubator-tuweni] 01/02: move tests to integration tests

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

toulmean pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git

commit afee6d7ff598bc712cabb4176d6894a9cab2363c
Author: Antoine Toulme <an...@lunar-ocean.com>
AuthorDate: Sun May 31 15:02:40 2020 -0700

    move tests to integration tests
---
 .../tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt} |  28 +++--
 .../org/apache/tuweni/devp2p/eth/EthHandlerTest.kt | 122 ---------------------
 2 files changed, 18 insertions(+), 132 deletions(-)

diff --git a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt b/devp2p-eth/src/integrationTest/kotlin/org/apache/tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt
similarity index 91%
copy from devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
copy to devp2p-eth/src/integrationTest/kotlin/org/apache/tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt
index ac2b1b9..4233889 100644
--- a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
+++ b/devp2p-eth/src/integrationTest/kotlin/org/apache/tuweni/devp2p/eth/ConnectToAnotherNodeTest.kt
@@ -32,9 +32,7 @@ import org.apache.tuweni.junit.VertxInstance
 import org.apache.tuweni.kv.MapKeyValueStore
 import org.apache.tuweni.rlpx.vertx.VertxRLPxService
 import org.apache.tuweni.units.bigints.UInt256
-import org.junit.jupiter.api.Assertions.assertFalse
-import org.junit.jupiter.api.Assertions.assertNotNull
-import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Assertions
 import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
@@ -43,6 +41,10 @@ import java.net.InetSocketAddress
 @ExtendWith(LuceneIndexWriterExtension::class, VertxExtension::class, BouncyCastleExtension::class)
 class EthHandlerTest {
 
+  /**
+   * To run this test, run an Ethereum mainnet node at home and point this test to it.
+   *
+   */
   @Disabled
   @Test
   fun testCollectHeaders(@LuceneIndexWriter writer: IndexWriter, @VertxInstance vertx: Vertx) = runBlocking {
@@ -61,7 +63,7 @@ class EthHandlerTest {
     val service = VertxRLPxService(
       vertx,
       30304,
-      "0.0.0.0",
+      "127.0.0.1",
       30304,
       SECP256K1.KeyPair.random(),
       listOf(
@@ -79,20 +81,26 @@ class EthHandlerTest {
     val id = service.connectTo(
       SECP256K1.PublicKey.fromHexString(
         "b1c9e33ebfd9446151688f0abaf171dac6df31ea5205a200f2cbaf5f8be" +
-          "d241c9f93732f25109e16badea1aa657a6078240657688cbbddb91a50aa8c7c34a9cc"),
+          "d241c9f93732f25109e16badea1aa657a6078240657688cbbddb91a50aa8c7c34a9cc"
+      ),
       InetSocketAddress("192.168.88.46", 30303)
     ).await()
 
-    service.send(EthSubprotocol.ETH64, 3, id, GetBlockHeaders(genesisBlock.header.hash, 100, 0, false).toBytes())
+    service.send(
+      EthSubprotocol.ETH64,
+      MessageType.GetBlockHeaders.code,
+      id,
+      GetBlockHeaders(genesisBlock.header.hash, 100, 0, false).toBytes()
+    )
 
     Thread.sleep(3000)
     val header = repository.findBlockByHashOrNumber(UInt256.valueOf(99L).toBytes())
-    assertFalse(header.isEmpty())
+    Assertions.assertFalse(header.isEmpty())
 
     val header3 = repository.findBlockByHashOrNumber(UInt256.valueOf(101L).toBytes())
-    assertTrue(header3.isEmpty())
+    Assertions.assertTrue(header3.isEmpty())
     val header2 = repository.findBlockByHashOrNumber(UInt256.valueOf(100L).toBytes())
-    assertTrue(header2.isEmpty())
+    Assertions.assertTrue(header2.isEmpty())
     service.send(EthSubprotocol.ETH64, 3, id, GetBlockHeaders(header[0], 100, 0, false).toBytes())
     Thread.sleep(3000)
   }
@@ -163,6 +171,6 @@ class EthHandlerTest {
     service2.start().await()
     val value = service.connectTo(service2kp.publicKey(), InetSocketAddress("127.0.0.1", service2.actualPort()))
       .await()
-    assertNotNull(value)
+    Assertions.assertNotNull(value)
   }
 }
diff --git a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt b/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
index ac2b1b9..86b1ffb 100644
--- a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
+++ b/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
@@ -43,126 +43,4 @@ import java.net.InetSocketAddress
 @ExtendWith(LuceneIndexWriterExtension::class, VertxExtension::class, BouncyCastleExtension::class)
 class EthHandlerTest {
 
-  @Disabled
-  @Test
-  fun testCollectHeaders(@LuceneIndexWriter writer: IndexWriter, @VertxInstance vertx: Vertx) = runBlocking {
-    val contents = EthHandlerTest::class.java.getResourceAsStream("/mainnet.json").readAllBytes()
-    val genesisFile = GenesisFile.read(contents)
-    val genesisBlock = genesisFile.toBlock()
-
-    val repository = BlockchainRepository.init(
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      BlockchainIndex(writer),
-      genesisBlock
-    )
-    val service = VertxRLPxService(
-      vertx,
-      30304,
-      "0.0.0.0",
-      30304,
-      SECP256K1.KeyPair.random(),
-      listOf(
-        EthSubprotocol(
-          repository = repository,
-          blockchainInfo = SimpleBlockchainInformation(
-            UInt256.valueOf(genesisFile.chainId.toLong()), genesisBlock.header.difficulty,
-            genesisBlock.header.hash, genesisBlock.header.hash, genesisFile.forks
-          )
-        )
-      ),
-      "Tuweni Experiment 0.1"
-    )
-    service.start().await()
-    val id = service.connectTo(
-      SECP256K1.PublicKey.fromHexString(
-        "b1c9e33ebfd9446151688f0abaf171dac6df31ea5205a200f2cbaf5f8be" +
-          "d241c9f93732f25109e16badea1aa657a6078240657688cbbddb91a50aa8c7c34a9cc"),
-      InetSocketAddress("192.168.88.46", 30303)
-    ).await()
-
-    service.send(EthSubprotocol.ETH64, 3, id, GetBlockHeaders(genesisBlock.header.hash, 100, 0, false).toBytes())
-
-    Thread.sleep(3000)
-    val header = repository.findBlockByHashOrNumber(UInt256.valueOf(99L).toBytes())
-    assertFalse(header.isEmpty())
-
-    val header3 = repository.findBlockByHashOrNumber(UInt256.valueOf(101L).toBytes())
-    assertTrue(header3.isEmpty())
-    val header2 = repository.findBlockByHashOrNumber(UInt256.valueOf(100L).toBytes())
-    assertTrue(header2.isEmpty())
-    service.send(EthSubprotocol.ETH64, 3, id, GetBlockHeaders(header[0], 100, 0, false).toBytes())
-    Thread.sleep(3000)
-  }
-
-  @Test
-  fun twoServers(@LuceneIndexWriter writer: IndexWriter, @VertxInstance vertx: Vertx) = runBlocking {
-    val contents = EthHandlerTest::class.java.getResourceAsStream("/mainnet.json").readAllBytes()
-    val genesisBlock = GenesisFile.read(contents).toBlock()
-
-    val repository = BlockchainRepository.init(
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      BlockchainIndex(writer),
-      genesisBlock
-    )
-    val service = VertxRLPxService(
-      vertx,
-      30303,
-      "127.0.0.1",
-      30303,
-      SECP256K1.KeyPair.random(),
-      listOf(
-        EthSubprotocol(
-          repository = repository,
-          blockchainInfo = SimpleBlockchainInformation(
-            UInt256.ZERO,
-            genesisBlock.header.difficulty,
-            genesisBlock.header.hash,
-            genesisBlock.header.hash,
-            emptyList()
-          )
-        )
-      ),
-      "Tuweni Experiment 0.1"
-    )
-    service.start().await()
-    val repository2 = BlockchainRepository.init(
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      MapKeyValueStore(),
-      BlockchainIndex(writer),
-      genesisBlock
-    )
-    val service2kp = SECP256K1.KeyPair.random()
-    val service2 = VertxRLPxService(
-      vertx,
-      0,
-      "127.0.0.1",
-      0,
-      service2kp,
-      listOf(
-        EthSubprotocol(
-          repository = repository2,
-          blockchainInfo = SimpleBlockchainInformation(
-            UInt256.ZERO,
-            genesisBlock.header.difficulty,
-            genesisBlock.header.hash,
-            genesisBlock.header.hash,
-            emptyList()
-          )
-        )
-      ),
-      "Tuweni Experiment 0.1"
-    )
-    service2.start().await()
-    val value = service.connectTo(service2kp.publicKey(), InetSocketAddress("127.0.0.1", service2.actualPort()))
-      .await()
-    assertNotNull(value)
-  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tuweni.apache.org
For additional commands, e-mail: commits-help@tuweni.apache.org


[incubator-tuweni] 02/02: Add tests for getting headers

Posted by to...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

toulmean pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-tuweni.git

commit 42cf5ad1cc353499bd04a9d1200006805eeb6e3f
Author: Antoine Toulme <an...@lunar-ocean.com>
AuthorDate: Sun May 31 23:03:00 2020 -0700

    Add tests for getting headers
---
 dependency-versions.gradle                         |   2 +
 devp2p-eth/build.gradle                            |   1 +
 .../org/apache/tuweni/devp2p/eth/EthHandler.kt     |  39 +++---
 .../org/apache/tuweni/devp2p/eth/Messages.kt       |   8 +-
 .../org/apache/tuweni/devp2p/eth/EthHandlerTest.kt | 138 +++++++++++++++++++--
 .../tuweni/eth/repository/BlockchainIndex.kt       |   4 +-
 .../tuweni/eth/repository/BlockchainRepository.kt  |   9 +-
 7 files changed, 161 insertions(+), 40 deletions(-)

diff --git a/dependency-versions.gradle b/dependency-versions.gradle
index bbe202d..f7f75f8 100644
--- a/dependency-versions.gradle
+++ b/dependency-versions.gradle
@@ -66,6 +66,8 @@ dependencyManagement {
     }
     dependency('org.mapdb:mapdb:3.0.7')
     dependency('org.miracl.milagro.amcl:milagro-crypto-java:0.4.0')
+    dependency('org.mockito:mockito-junit-jupiter:3.3.3')
+
     dependency('org.rocksdb:rocksdbjni:5.17.2')
     dependency('org.slf4j:slf4j-api:1.7.30')
 
diff --git a/devp2p-eth/build.gradle b/devp2p-eth/build.gradle
index ffd74ac..fb31487 100644
--- a/devp2p-eth/build.gradle
+++ b/devp2p-eth/build.gradle
@@ -33,6 +33,7 @@ dependencies {
   testCompile 'org.bouncycastle:bcprov-jdk15on'
   testCompile 'org.junit.jupiter:junit-jupiter-api'
   testCompile 'org.junit.jupiter:junit-jupiter-params'
+  testCompile 'org.mockito:mockito-junit-jupiter'
 
   testRuntime 'org.junit.jupiter:junit-jupiter-engine'
   testRuntime 'ch.qos.logback:logback-classic'
diff --git a/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/EthHandler.kt b/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/EthHandler.kt
index 8293270..ae16b05 100644
--- a/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/EthHandler.kt
+++ b/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/EthHandler.kt
@@ -130,30 +130,29 @@ internal class EthHandler(
   }
 
   private suspend fun handleGetBlockHeaders(connectionId: String, blockHeaderRequest: GetBlockHeaders) {
-    val matches = repository.findBlockByHashOrNumber(blockHeaderRequest.hash)
-    if (matches.isEmpty()) {
-      return
-    }
+    val matches = repository.findBlockByHashOrNumber(blockHeaderRequest.block)
     val headers = ArrayList<BlockHeader>()
-    val header = repository.retrieveBlockHeader(matches[0])
-    header?.let {
-      headers.add(it)
-      var blockNumber = it.number
-      for (i in 1..blockHeaderRequest.maxHeaders) {
-        blockNumber = if (blockHeaderRequest.reverse) {
-          blockNumber.subtract(blockHeaderRequest.skip)
-        } else {
-          blockNumber.add(blockHeaderRequest.skip)
-        }
-        val nextMatches = repository.findBlockByHashOrNumber(blockNumber.toBytes())
-        if (nextMatches.isEmpty()) {
-          break
+    if (matches.isNotEmpty()) {
+      val header = repository.retrieveBlockHeader(matches[0])
+      header?.let {
+        headers.add(it)
+        var blockNumber = it.number
+        for (i in 2..blockHeaderRequest.maxHeaders) {
+          blockNumber = if (blockHeaderRequest.reverse) {
+            blockNumber.subtract(blockHeaderRequest.skip + 1)
+          } else {
+            blockNumber.add(blockHeaderRequest.skip + 1)
+          }
+          val nextMatches = repository.findBlockByHashOrNumber(blockNumber.toBytes())
+          if (nextMatches.isEmpty()) {
+            break
+          }
+          val nextHeader = repository.retrieveBlockHeader(nextMatches[0]) ?: break
+          headers.add(nextHeader)
         }
-        val nextHeader = repository.retrieveBlockHeader(nextMatches[0]) ?: break
-        headers.add(nextHeader)
       }
-      service.send(EthSubprotocol.ETH64, MessageType.BlockHeaders.code, connectionId, BlockHeaders(headers).toBytes())
     }
+    service.send(EthSubprotocol.ETH64, MessageType.BlockHeaders.code, connectionId, BlockHeaders(headers).toBytes())
   }
 
   private suspend fun handleNewBlockHashes(message: NewBlockHashes) {
diff --git a/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/Messages.kt b/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/Messages.kt
index c3ea031..356b043 100644
--- a/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/Messages.kt
+++ b/devp2p-eth/src/main/kotlin/org/apache/tuweni/devp2p/eth/Messages.kt
@@ -112,20 +112,20 @@ data class NewBlockHashes(val hashes: List<Pair<Hash, Long>>) {
   }
 }
 
-data class GetBlockHeaders(val hash: Hash, val maxHeaders: Long, val skip: Long, val reverse: Boolean) {
+data class GetBlockHeaders(val block: Bytes, val maxHeaders: Long, val skip: Long, val reverse: Boolean) {
   companion object {
 
     fun read(payload: Bytes): GetBlockHeaders = RLP.decodeList(payload) {
-      val hash = Hash.fromBytes(it.readValue())
+      val block = it.readValue()
       val maxHeaders = it.readLong()
       val skip = it.readLong()
       val reverse = it.readInt() == 1
-      GetBlockHeaders(hash, maxHeaders, skip, reverse)
+      GetBlockHeaders(block, maxHeaders, skip, reverse)
     }
   }
 
   fun toBytes(): Bytes = RLP.encodeList { writer ->
-    writer.writeValue(hash)
+    writer.writeValue(block)
     writer.writeLong(maxHeaders)
     writer.writeLong(skip)
     writer.writeInt(if (reverse) 1 else 0)
diff --git a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt b/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
index 86b1ffb..22148ea 100644
--- a/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
+++ b/devp2p-eth/src/test/kotlin/org/apache/tuweni/devp2p/eth/EthHandlerTest.kt
@@ -16,31 +16,151 @@
  */
 package org.apache.tuweni.devp2p.eth
 
-import io.vertx.core.Vertx
 import kotlinx.coroutines.runBlocking
 import org.apache.lucene.index.IndexWriter
+import org.apache.tuweni.bytes.Bytes
+import org.apache.tuweni.bytes.Bytes32
 import org.apache.tuweni.concurrent.coroutines.await
 import org.apache.tuweni.crypto.SECP256K1
-import org.apache.tuweni.eth.genesis.GenesisFile
+import org.apache.tuweni.devp2p.eth.EthSubprotocol.Companion.ETH64
+import org.apache.tuweni.eth.Address
+import org.apache.tuweni.eth.Block
+import org.apache.tuweni.eth.BlockBody
+import org.apache.tuweni.eth.BlockHeader
+import org.apache.tuweni.eth.Hash
+import org.apache.tuweni.eth.Transaction
 import org.apache.tuweni.eth.repository.BlockchainIndex
 import org.apache.tuweni.eth.repository.BlockchainRepository
 import org.apache.tuweni.junit.BouncyCastleExtension
 import org.apache.tuweni.junit.LuceneIndexWriter
 import org.apache.tuweni.junit.LuceneIndexWriterExtension
 import org.apache.tuweni.junit.VertxExtension
-import org.apache.tuweni.junit.VertxInstance
 import org.apache.tuweni.kv.MapKeyValueStore
-import org.apache.tuweni.rlpx.vertx.VertxRLPxService
+import org.apache.tuweni.rlp.RLP
+import org.apache.tuweni.rlpx.RLPxService
 import org.apache.tuweni.units.bigints.UInt256
-import org.junit.jupiter.api.Assertions.assertFalse
-import org.junit.jupiter.api.Assertions.assertNotNull
-import org.junit.jupiter.api.Assertions.assertTrue
-import org.junit.jupiter.api.Disabled
+import org.apache.tuweni.units.bigints.UInt64
+import org.apache.tuweni.units.ethereum.Gas
+import org.apache.tuweni.units.ethereum.Wei
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
-import java.net.InetSocketAddress
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import java.time.Instant
+import java.time.temporal.ChronoUnit
 
 @ExtendWith(LuceneIndexWriterExtension::class, VertxExtension::class, BouncyCastleExtension::class)
 class EthHandlerTest {
 
+  private lateinit var genesisBlock: Block
+  private lateinit var handler: EthHandler
+  private lateinit var repository: BlockchainRepository
+  private lateinit var service: RLPxService
+
+  @BeforeEach
+  fun setup(@LuceneIndexWriter writer: IndexWriter) = runBlocking {
+    val header = BlockHeader(
+      Hash.fromBytes(Bytes32.random()),
+      Hash.fromBytes(Bytes32.random()),
+      Address.fromBytes(Bytes.random(20)),
+      Hash.fromBytes(Bytes32.random()),
+      Hash.fromBytes(Bytes32.random()),
+      Hash.fromBytes(Bytes32.random()),
+      Bytes32.random(),
+      UInt256.fromBytes(Bytes32.random()),
+      UInt256.ZERO,
+      Gas.valueOf(3000),
+      Gas.valueOf(2000),
+      Instant.now().plusSeconds(30).truncatedTo(ChronoUnit.SECONDS),
+      Bytes.of(2, 3, 4, 5, 6, 7, 8, 9, 10),
+      Hash.fromBytes(Bytes32.random()),
+      UInt64.ZERO
+    )
+    val body = BlockBody(
+      listOf(
+        Transaction(
+          UInt256.valueOf(1),
+          Wei.valueOf(2),
+          Gas.valueOf(2),
+          Address.fromBytes(Bytes.random(20)),
+          Wei.valueOf(2),
+          Bytes.random(12),
+          SECP256K1.KeyPair.random()
+        )
+      ),
+      listOf(header)
+    )
+    genesisBlock = Block(header, body)
+    repository = BlockchainRepository.init(
+      MapKeyValueStore(),
+      MapKeyValueStore(),
+      MapKeyValueStore(),
+      MapKeyValueStore(),
+      BlockchainIndex(writer),
+      genesisBlock
+    )
+    service = mock(RLPxService::class.java)
+    handler = EthHandler(
+      blockchainInfo = SimpleBlockchainInformation(
+        UInt256.valueOf(42L),
+        UInt256.ONE,
+        genesisBlock.header.hash,
+        genesisBlock.header.hash,
+        emptyList()
+      ),
+      service = service,
+      repository = repository
+    )
+  }
+
+  private fun createChildBlockHeader(parentBlock: BlockHeader): BlockHeader {
+    val emptyListHash = Hash.hash(RLP.encodeList { })
+    val emptyHash = Hash.hash(RLP.encode { writer -> writer.writeValue(Bytes.EMPTY) })
+    return BlockHeader(
+      parentBlock.hash,
+      emptyListHash,
+      Address.fromBytes(Bytes.random(20)),
+      parentBlock.stateRoot,
+      emptyHash,
+      emptyHash,
+      Bytes.wrap(ByteArray(256)),
+      parentBlock.difficulty,
+      parentBlock.number.add(1),
+      parentBlock.gasLimit,
+      Gas.valueOf(0),
+      Instant.now(),
+      Bytes.random(45),
+      Hash.fromBytes(Bytes32.random()),
+      UInt64.ZERO
+    )
+  }
+
+  @Test
+  fun testGetHeaders() = runBlocking {
+    var header = repository.retrieveGenesisBlock().header
+    for (i in 1..10) {
+      val newHeader = createChildBlockHeader(header)
+      repository.storeBlockHeader(newHeader)
+      header = newHeader
+    }
+
+    handler.handle(
+      "foo",
+      MessageType.GetBlockHeaders.code,
+      GetBlockHeaders(genesisBlock.header.hash, 3, 1, false).toBytes()
+    ).await()
+
+    val messageCapture = ArgumentCaptor.forClass(Bytes::class.java)
+    verify(service).send(eq(ETH64), eq(MessageType.BlockHeaders.code), eq("foo"), messageCapture.capture())
+
+    val messageRead = BlockHeaders.read(messageCapture.value)
+    assertEquals(3, messageRead.headers.size)
+    assertEquals(UInt256.ZERO, messageRead.headers[0].number)
+    assertEquals(UInt256.valueOf(2), messageRead.headers[1].number)
+    assertEquals(UInt256.valueOf(4), messageRead.headers[2].number)
+  }
 }
diff --git a/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainIndex.kt b/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainIndex.kt
index ce7cf6a..a4b0edd 100644
--- a/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainIndex.kt
+++ b/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainIndex.kt
@@ -143,7 +143,7 @@ interface BlockchainIndexReader {
    * @param hashOrNumber the hash of a block header, or its number as a 32-byte word
    * @return the matching block header hashes.
    */
-  fun findByHashOrNumber(hashOrNumber: Bytes32): List<Hash>
+  fun findByHashOrNumber(hashOrNumber: Bytes): List<Hash>
 
   /**
    * Find a value in a range.
@@ -582,7 +582,7 @@ class BlockchainIndex(private val indexWriter: IndexWriter) : BlockchainIndexWri
     ).firstOrNull()
   }
 
-  override fun findByHashOrNumber(hashOrNumber: Bytes32): List<Hash> {
+  override fun findByHashOrNumber(hashOrNumber: Bytes): List<Hash> {
     val query = BooleanQuery.Builder()
       .setMinimumNumberShouldMatch(1)
       .add(BooleanClause(TermQuery(Term("_id", toBytesRef(hashOrNumber))), BooleanClause.Occur.SHOULD))
diff --git a/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainRepository.kt b/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainRepository.kt
index aa9f1ca..6cb0887 100644
--- a/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainRepository.kt
+++ b/eth-repository/src/main/kotlin/org/apache/tuweni/eth/repository/BlockchainRepository.kt
@@ -17,7 +17,6 @@
 package org.apache.tuweni.eth.repository
 
 import org.apache.tuweni.bytes.Bytes
-import org.apache.tuweni.bytes.Bytes32
 import org.apache.tuweni.eth.Block
 import org.apache.tuweni.eth.BlockBody
 import org.apache.tuweni.eth.BlockHeader
@@ -235,7 +234,7 @@ class BlockchainRepository
    */
   suspend fun retrieveChainHeadHeader(): BlockHeader? {
     return blockchainIndex.findByLargest(BlockHeaderFields.TOTAL_DIFFICULTY)
-      ?.let { retrieveBlockHeader(it) } ?: retrieveGenesisBlock()?.getHeader()
+      ?.let { retrieveBlockHeader(it) } ?: retrieveGenesisBlock().getHeader()
   }
 
   /**
@@ -243,8 +242,8 @@ class BlockchainRepository
    *
    * @return the genesis block
    */
-  suspend fun retrieveGenesisBlock(): Block? {
-    return chainMetadata.get(GENESIS_BLOCK)?.let { retrieveBlock(it) }
+  suspend fun retrieveGenesisBlock(): Block {
+    return chainMetadata.get(GENESIS_BLOCK).let { retrieveBlock(it!!)!! }
   }
 
   /**
@@ -284,7 +283,7 @@ class BlockchainRepository
    * @param blockNumberOrBlockHash the number or hash of the block
    * @return the matching blocks
    */
-  fun findBlockByHashOrNumber(blockNumberOrBlockHash: Bytes32): List<Hash> {
+  fun findBlockByHashOrNumber(blockNumberOrBlockHash: Bytes): List<Hash> {
     return blockchainIndex.findByHashOrNumber(blockNumberOrBlockHash)
   }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tuweni.apache.org
For additional commands, e-mail: commits-help@tuweni.apache.org