@@ -70,7 +70,7 @@ class EthereumFullBlocksReader(
|
|||||||
val blockSplit = splitByTransactions(block.json!!)
|
val blockSplit = splitByTransactions(block.json!!)
|
||||||
|
|
||||||
val transactions = Flux.fromIterable(block.transactions)
|
val transactions = Flux.fromIterable(block.transactions)
|
||||||
.flatMap { txes.read(it) }
|
.flatMapSequential { txes.read(it) }
|
||||||
.collectList()
|
.collectList()
|
||||||
|
|
||||||
return@flatMap transactions.flatMap { transactionsData ->
|
return@flatMap transactions.flatMap { transactionsData ->
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import io.emeraldpay.dshackle.cache.TxMemCache
|
|||||||
import io.emeraldpay.dshackle.data.BlockContainer
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
import io.emeraldpay.dshackle.data.BlockId
|
import io.emeraldpay.dshackle.data.BlockId
|
||||||
import io.emeraldpay.dshackle.data.TxContainer
|
import io.emeraldpay.dshackle.data.TxContainer
|
||||||
|
import io.emeraldpay.dshackle.data.TxId
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
import io.infinitape.etherjar.domain.BlockHash
|
import io.infinitape.etherjar.domain.BlockHash
|
||||||
import io.infinitape.etherjar.domain.TransactionId
|
import io.infinitape.etherjar.domain.TransactionId
|
||||||
@@ -30,9 +31,11 @@ import io.infinitape.etherjar.rpc.json.BlockJson
|
|||||||
import io.infinitape.etherjar.rpc.json.TransactionJson
|
import io.infinitape.etherjar.rpc.json.TransactionJson
|
||||||
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
import io.infinitape.etherjar.rpc.json.TransactionRefJson
|
||||||
import org.apache.commons.codec.binary.Hex
|
import org.apache.commons.codec.binary.Hex
|
||||||
|
import reactor.core.publisher.Mono
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
class EthereumFullBlocksReaderSpec extends Specification {
|
class EthereumFullBlocksReaderSpec extends Specification {
|
||||||
@@ -111,6 +114,21 @@ class EthereumFullBlocksReaderSpec extends Specification {
|
|||||||
it
|
it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all transaction2
|
||||||
|
def block4 = new BlockJson().with {
|
||||||
|
it.number = 103
|
||||||
|
it.hash = BlockHash.from(hash3)
|
||||||
|
it.totalDifficulty = BigInteger.ONE
|
||||||
|
it.timestamp = Instant.now()
|
||||||
|
it.transactions = [
|
||||||
|
new TransactionRefJson(tx1.hash),
|
||||||
|
new TransactionRefJson(tx2.hash),
|
||||||
|
new TransactionRefJson(tx3.hash),
|
||||||
|
new TransactionRefJson(tx4.hash)
|
||||||
|
]
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def "Read transactions and return full block"() {
|
def "Read transactions and return full block"() {
|
||||||
setup:
|
setup:
|
||||||
@@ -178,6 +196,34 @@ class EthereumFullBlocksReaderSpec extends Specification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "Produce block with original order of transactions"() {
|
||||||
|
setup:
|
||||||
|
def txes = Mock(Reader) {
|
||||||
|
1 * it.read(TxId.from(tx1.hash)) >> Mono.just(TxContainer.from(tx1)).delayElement(Duration.ofMillis(50))
|
||||||
|
1 * it.read(TxId.from(tx2.hash)) >> Mono.just(TxContainer.from(tx2)).delayElement(Duration.ofMillis(40))
|
||||||
|
1 * it.read(TxId.from(tx3.hash)) >> Mono.just(TxContainer.from(tx3)).delayElement(Duration.ofMillis(30))
|
||||||
|
1 * it.read(TxId.from(tx4.hash)) >> Mono.just(TxContainer.from(tx4)).delayElement(Duration.ofMillis(20))
|
||||||
|
}
|
||||||
|
def blocks = new BlocksMemCache()
|
||||||
|
blocks.add(BlockContainer.from(block4))
|
||||||
|
|
||||||
|
def full = new EthereumFullBlocksReader(blocks, txes)
|
||||||
|
|
||||||
|
when:
|
||||||
|
def act = full.read(BlockId.from(block4.hash)).block()
|
||||||
|
act = objectMapper.readValue(act.json, BlockJson)
|
||||||
|
def transactions = act.transactions
|
||||||
|
|
||||||
|
then:
|
||||||
|
transactions.size() == 4
|
||||||
|
transactions[0] instanceof TransactionJson
|
||||||
|
transactions[1] instanceof TransactionJson
|
||||||
|
transactions[0].hash == TransactionId.from(hash1)
|
||||||
|
transactions[1].hash == TransactionId.from(hash2)
|
||||||
|
transactions[2].hash == TransactionId.from(hash3)
|
||||||
|
transactions[3].hash == TransactionId.from(hash4)
|
||||||
|
}
|
||||||
|
|
||||||
def "Read block without transactions"() {
|
def "Read block without transactions"() {
|
||||||
setup:
|
setup:
|
||||||
def txes = new TxMemCache()
|
def txes = new TxMemCache()
|
||||||
|
|||||||
@@ -3,5 +3,12 @@
|
|||||||
.Run from project root directory:
|
.Run from project root directory:
|
||||||
[source,bash]
|
[source,bash]
|
||||||
----
|
----
|
||||||
./gradlew run --args="--configPath=./testing/dshackle/dshackle.yaml"
|
./gradlew run --args="--configPath=./testing/dshackle/dshackle-mock.yaml"
|
||||||
|
----
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
[source,bash]
|
||||||
|
----
|
||||||
|
./gradlew run --args="--configPath=./testing/dshackle/dshackle-real.yaml"
|
||||||
----
|
----
|
||||||
|
|||||||
29
testing/dshackle/dshackle-real.yaml
Normal file
29
testing/dshackle/dshackle-real.yaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
version: v1
|
||||||
|
port: 12448
|
||||||
|
|
||||||
|
tls:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
cluster:
|
||||||
|
upstreams:
|
||||||
|
- id: eth-1
|
||||||
|
chain: ethereum
|
||||||
|
connection:
|
||||||
|
ethereum:
|
||||||
|
rpc:
|
||||||
|
url: "${DSHACKLE_TEST_ETH1_RPC}"
|
||||||
|
ws:
|
||||||
|
url: "${DSHACKLE_TEST_ETH1_WS}"
|
||||||
|
origin: "${DSHACKLE_TEST_ETH1_WSORIGIN}"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
redis:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
port: 18081
|
||||||
|
tls:
|
||||||
|
enabled: false
|
||||||
|
routes:
|
||||||
|
- id: eth
|
||||||
|
blockchain: ethereum
|
||||||
@@ -24,8 +24,20 @@ class ProxyClient {
|
|||||||
this.objectMapper = new ObjectMapper()
|
this.objectMapper = new ObjectMapper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ProxyClient ethereumMock() {
|
||||||
|
return forPrefix(18080, "eth")
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProxyClient ethereumReal() {
|
||||||
|
return forPrefix(18081, "eth")
|
||||||
|
}
|
||||||
|
|
||||||
static ProxyClient forPrefix(String prefix) {
|
static ProxyClient forPrefix(String prefix) {
|
||||||
return new ProxyClient("http://127.0.0.1:18080/$prefix")
|
return forPrefix(18080, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProxyClient forPrefix(int port, String prefix) {
|
||||||
|
return new ProxyClient("http://127.0.0.1:$port/$prefix")
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProxyClient forOriginal(int port) {
|
static ProxyClient forOriginal(int port) {
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package io.emeraldpay.dshackle.testing.trial.proxy
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.testing.trial.Debugger
|
||||||
|
import io.emeraldpay.dshackle.testing.trial.ProxyClient
|
||||||
|
import spock.lang.Specification
|
||||||
|
import spock.lang.Timeout
|
||||||
|
|
||||||
|
class GetBlockRealSpec extends Specification {
|
||||||
|
|
||||||
|
def client = ProxyClient.ethereumReal()
|
||||||
|
|
||||||
|
def setup() {
|
||||||
|
Debugger.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
def cleanup() {
|
||||||
|
Debugger.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Timeout(15)
|
||||||
|
def "Correct order for transactions on #height"() {
|
||||||
|
expect:
|
||||||
|
def results = [
|
||||||
|
(client.execute("eth_getBlockByNumber", ["0x" + Integer.toString(height, 16), false]).result["transactions"] as List<String>),
|
||||||
|
(client.execute("eth_getBlockByNumber", ["0x" + Integer.toString(height, 16), true]).result["transactions"] as List<Map<String, Object>>)
|
||||||
|
.collect { it.hash }
|
||||||
|
]
|
||||||
|
|
||||||
|
println(results[0])
|
||||||
|
println(results[1])
|
||||||
|
|
||||||
|
results[0] == results[1]
|
||||||
|
|
||||||
|
where:
|
||||||
|
height << (10_000_000..10_000_500)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user