1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-02-22 14:22:39 +01:00

Improve unit tests (#908)

* Bitcoin tests: generate 150 blocks instead of 500

We don't need to generate 432 blocks to activate segwit but we still need to have
spendable coins and coinbase maturity is 100 blocks even on regtest.

* Electrum client: test against mainnet Electrum servers

Previous test against testnet servers was flaky because testnet Electrum
servers are unrelable. Here we test against our own server on mainnet (and
2 servers from our list for the pool test).
This commit is contained in:
Fabrice Drouin 2019-03-22 13:26:55 +01:00 committed by Pierre-Marie Padiou
parent 1c9ac1d62d
commit 32d8a08ad1
5 changed files with 36 additions and 32 deletions

View file

@ -86,7 +86,7 @@ trait BitcoindService extends Logging {
sender.receiveOne(5 second).isInstanceOf[JValue]
}, max = 30 seconds, interval = 500 millis)
logger.info(s"generating initial blocks...")
sender.send(bitcoincli, BitcoinReq("generate", 500))
sender.send(bitcoincli, BitcoinReq("generate", 150))
sender.expectMsgType[JValue](30 seconds)
}

View file

@ -16,6 +16,8 @@
package fr.acinq.eclair.blockchain.electrum
import java.net.InetSocketAddress
import akka.actor.{ActorRef, ActorSystem, Props}
import akka.testkit.{TestKit, TestProbe}
import fr.acinq.bitcoin.{ByteVector32, Crypto, Transaction}
@ -30,7 +32,8 @@ import scala.concurrent.duration._
class ElectrumClientPoolSpec extends TestKit(ActorSystem("test")) with FunSuiteLike with Logging with BeforeAndAfterAll {
var pool: ActorRef = _
val probe = TestProbe()
val referenceTx = Transaction.read("0200000003947e307df3ab452d23f02b5a65f4ada1804ee733e168e6197b0bd6cc79932b6c010000006a473044022069346ec6526454a481690a3664609f9e8032c34553015cfa2e9b25ebb420a33002206998f21a2aa771ad92a0c1083f4181a3acdb0d42ca51d01be1309da2ffb9cecf012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff966d9d969cd5f95bfd53003a35fcc1a50f4fb51f211596e6472583fdc5d38470000000006b4830450221009c9757515009c5709b5b678d678185202b817ef9a69ffb954144615ab11762210220732216384da4bf79340e9c46d0effba6ba92982cca998adfc3f354cec7715f800121035f7c3e077108035026f4ebd5d6ca696ef088d4f34d45d94eab4c41202ec74f9bfefffffff8d5062f5b04455c6cfa7e3f250e5a4fb44308ba2b86baf77f9ad0d782f57071010000006a47304402207f9f7dd91fe537a26d5554105977e3949a5c8c4ef53a6a3bff6da2d36eff928f02202b9427bef487a1825fd0c3c6851d17d5f19e6d73dfee22bf06db591929a2044d012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff02809698000000000017a914c82753548fdf4be1c3c7b14872c90b5198e67eaa876e642500000000001976a914e2365ec29471b3e271388b22eadf0e7f54d307a788ac6f771200")
// this is tx #2690 of block #500000
val referenceTx = Transaction.read("0200000001983c5b32ced1de5ae97d3ce9b7436f8bb0487d15bf81e5cae97b1e238dc395c6000000006a47304402205957c75766e391350eba2c7b752f0056cb34b353648ecd0992a8a81fc9bcfe980220629c286592842d152cdde71177cd83086619744a533f262473298cacf60193500121021b8b51f74dbf0ac1e766d162c8707b5e8d89fc59da0796f3b4505e7c0fb4cf31feffffff0276bd0101000000001976a914219de672ba773aa0bc2e15cdd9d2e69b734138fa88ac3e692001000000001976a914301706dede031e9fb4b60836e073a4761855f6b188ac09a10700")
val scriptHash = Crypto.sha256(referenceTx.txOut(0).publicKeyScript).reverse
import scala.concurrent.ExecutionContext.Implicits.global
@ -39,14 +42,14 @@ class ElectrumClientPoolSpec extends TestKit(ActorSystem("test")) with FunSuiteL
}
test("init an electrumx connection pool") {
val stream = classOf[ElectrumClientSpec].getResourceAsStream("/electrum/servers_testnet.json")
val addresses = ElectrumClientPool.readServerAddresses(stream, sslEnabled = false)
val stream = classOf[ElectrumClientSpec].getResourceAsStream("/electrum/servers_mainnet.json")
val addresses = ElectrumClientPool.readServerAddresses(stream, sslEnabled = false).take(2) + ElectrumClientPool.ElectrumServerAddress(new InetSocketAddress("electrum.acinq.co", 50002), SSL.STRICT)
assert(addresses.nonEmpty)
stream.close()
pool = system.actorOf(Props(new ElectrumClientPool(addresses)), "electrum-client")
}
test("connect to an electrumx testnet server") {
test("connect to an electrumx mainnet server") {
probe.send(pool, AddStatusListener(probe.ref))
// make sure our master is stable, if the first master that we select is behind the other servers we will switch
// during the first few seconds
@ -56,18 +59,18 @@ class ElectrumClientPoolSpec extends TestKit(ActorSystem("test")) with FunSuiteL
}, max = 15 seconds, interval = 1000 millis) }
test("get transaction") {
probe.send(pool, GetTransaction(ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")))
probe.send(pool, GetTransaction(referenceTx.txid))
val GetTransactionResponse(tx) = probe.expectMsgType[GetTransactionResponse]
assert(tx.txid == ByteVector32.fromValidHex("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"))
assert(tx == referenceTx)
}
test("get merkle tree") {
probe.send(pool, GetMerkle(ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"), 1210223))
probe.send(pool, GetMerkle(referenceTx.txid, 500000))
val response = probe.expectMsgType[GetMerkleResponse]
assert(response.txid == ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"))
assert(response.block_height == 1210223)
assert(response.pos == 28)
assert(response.root == ByteVector32(hex"203a52cf3cc071467e5b8780d62d5dfb672bf7bc0841bc823691961ea23402fb"))
assert(response.txid == referenceTx.txid)
assert(response.block_height == 500000)
assert(response.pos == 2690)
assert(response.root == ByteVector32(hex"1f6231ed3de07345b607ec2a39b2d01bec2fe10dfb7f516ba4958a42691c9531"))
}
test("header subscription") {
@ -87,12 +90,12 @@ class ElectrumClientPoolSpec extends TestKit(ActorSystem("test")) with FunSuiteL
test("get scripthash history") {
probe.send(pool, GetScriptHashHistory(scriptHash))
val GetScriptHashHistoryResponse(scriptHash1, history) = probe.expectMsgType[GetScriptHashHistoryResponse]
assert(history.contains((TransactionHistoryItem(1210224, ByteVector32(hex"3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0")))))
assert(history.contains((TransactionHistoryItem(500000, referenceTx.txid))))
}
test("list script unspents") {
probe.send(pool, ScriptHashListUnspent(scriptHash))
val ScriptHashListUnspentResponse(scriptHash1, unspents) = probe.expectMsgType[ScriptHashListUnspentResponse]
assert(unspents.contains(UnspentItem(ByteVector32(hex"3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0"), 0, 10000000L, 1210224L)))
assert(unspents.isEmpty)
}
}

View file

@ -35,32 +35,33 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
var client: ActorRef = _
val probe = TestProbe()
val referenceTx = Transaction.read("0200000003947e307df3ab452d23f02b5a65f4ada1804ee733e168e6197b0bd6cc79932b6c010000006a473044022069346ec6526454a481690a3664609f9e8032c34553015cfa2e9b25ebb420a33002206998f21a2aa771ad92a0c1083f4181a3acdb0d42ca51d01be1309da2ffb9cecf012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff966d9d969cd5f95bfd53003a35fcc1a50f4fb51f211596e6472583fdc5d38470000000006b4830450221009c9757515009c5709b5b678d678185202b817ef9a69ffb954144615ab11762210220732216384da4bf79340e9c46d0effba6ba92982cca998adfc3f354cec7715f800121035f7c3e077108035026f4ebd5d6ca696ef088d4f34d45d94eab4c41202ec74f9bfefffffff8d5062f5b04455c6cfa7e3f250e5a4fb44308ba2b86baf77f9ad0d782f57071010000006a47304402207f9f7dd91fe537a26d5554105977e3949a5c8c4ef53a6a3bff6da2d36eff928f02202b9427bef487a1825fd0c3c6851d17d5f19e6d73dfee22bf06db591929a2044d012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff02809698000000000017a914c82753548fdf4be1c3c7b14872c90b5198e67eaa876e642500000000001976a914e2365ec29471b3e271388b22eadf0e7f54d307a788ac6f771200")
// this is tx #2690 of block #500000
val referenceTx = Transaction.read("0200000001983c5b32ced1de5ae97d3ce9b7436f8bb0487d15bf81e5cae97b1e238dc395c6000000006a47304402205957c75766e391350eba2c7b752f0056cb34b353648ecd0992a8a81fc9bcfe980220629c286592842d152cdde71177cd83086619744a533f262473298cacf60193500121021b8b51f74dbf0ac1e766d162c8707b5e8d89fc59da0796f3b4505e7c0fb4cf31feffffff0276bd0101000000001976a914219de672ba773aa0bc2e15cdd9d2e69b734138fa88ac3e692001000000001976a914301706dede031e9fb4b60836e073a4761855f6b188ac09a10700")
val scriptHash = Crypto.sha256(referenceTx.txOut(0).publicKeyScript).reverse
override protected def beforeAll(): Unit = {
client = system.actorOf(Props(new ElectrumClient(new InetSocketAddress("testnet.qtornado.com", 51002), SSL.LOOSE)), "electrum-client")
client = system.actorOf(Props(new ElectrumClient(new InetSocketAddress("electrum.acinq.co", 50002), SSL.STRICT)), "electrum-client")
}
override protected def afterAll(): Unit = {
TestKit.shutdownActorSystem(system)
}
test("connect to an electrumx testnet server") {
test("connect to an electrumx mainnet server") {
probe.send(client, AddStatusListener(probe.ref))
probe.expectMsgType[ElectrumReady](15 seconds)
}
test("get transaction") {
probe.send(client, GetTransaction(ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")))
probe.send(client, GetTransaction(referenceTx.txid))
val GetTransactionResponse(tx) = probe.expectMsgType[GetTransactionResponse]
assert(tx.txid == ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"))
assert(tx == referenceTx)
}
test("get header") {
probe.send(client, GetHeader(10000))
probe.send(client, GetHeader(100000))
val GetHeaderResponse(height, header) = probe.expectMsgType[GetHeaderResponse]
assert(header.blockId == ByteVector32(hex"000000000058b74204bb9d59128e7975b683ac73910660b6531e59523fb4a102"))
assert(header.blockId == ByteVector32(hex"000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"))
}
test("get headers") {
@ -72,12 +73,12 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
}
test("get merkle tree") {
probe.send(client, GetMerkle(ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"), 1210223))
probe.send(client, GetMerkle(referenceTx.txid, 500000))
val response = probe.expectMsgType[GetMerkleResponse]
assert(response.txid == ByteVector32(hex"c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202"))
assert(response.block_height == 1210223)
assert(response.pos == 28)
assert(response.root == ByteVector32(hex"203a52cf3cc071467e5b8780d62d5dfb672bf7bc0841bc823691961ea23402fb"))
assert(response.txid == referenceTx.txid)
assert(response.block_height == 500000)
assert(response.pos == 2690)
assert(response.root == ByteVector32(hex"1f6231ed3de07345b607ec2a39b2d01bec2fe10dfb7f516ba4958a42691c9531"))
}
test("header subscription") {
@ -97,12 +98,12 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
test("get scripthash history") {
probe.send(client, GetScriptHashHistory(scriptHash))
val GetScriptHashHistoryResponse(scriptHash1, history) = probe.expectMsgType[GetScriptHashHistoryResponse]
assert(history.contains((TransactionHistoryItem(1210224, ByteVector32(hex"3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0")))))
assert(history.contains((TransactionHistoryItem(500000, referenceTx.txid))))
}
test("list script unspents") {
probe.send(client, ScriptHashListUnspent(scriptHash))
val ScriptHashListUnspentResponse(scriptHash1, unspents) = probe.expectMsgType[ScriptHashListUnspentResponse]
assert(unspents.contains(UnspentItem(ByteVector32(hex"3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0"), 0, 10000000L, 1210224L)))
assert(unspents.isEmpty)
}
}

View file

@ -74,7 +74,7 @@ class ElectrumWalletSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
probe.expectMsgType[GetBalanceResponse]
}
test("generate 500 blocks") {
test("generate 150 blocks") {
val sender = TestProbe()
logger.info(s"waiting for bitcoind to initialize...")
awaitCond({
@ -82,9 +82,9 @@ class ElectrumWalletSpec extends TestKit(ActorSystem("test")) with FunSuiteLike
sender.receiveOne(5 second).isInstanceOf[JValue]
}, max = 30 seconds, interval = 500 millis)
logger.info(s"generating initial blocks...")
sender.send(bitcoincli, BitcoinReq("generate", 500))
sender.send(bitcoincli, BitcoinReq("generate", 150))
sender.expectMsgType[JValue](30 seconds)
DockerReadyChecker.LogLineContains("INFO:BlockProcessor:height: 501").looped(attempts = 15, delay = 1 second)
DockerReadyChecker.LogLineContains("INFO:BlockProcessor:height: 151").looped(attempts = 15, delay = 1 second)
}
test("wait until wallet is ready") {

View file

@ -114,7 +114,7 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
sender.receiveOne(5 second).isInstanceOf[JValue]
}, max = 30 seconds, interval = 500 millis)
logger.info(s"generating initial blocks...")
sender.send(bitcoincli, BitcoinReq("generate", 500))
sender.send(bitcoincli, BitcoinReq("generate", 150))
sender.expectMsgType[JValue](30 seconds)
}