1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-03-13 19:37:35 +01:00

Merge commit '3b7afd92d47bad552de7f93ce34e244939ed1fdc' into android

This commit is contained in:
pm47 2019-03-27 14:54:29 +01:00
commit 48a5ac2e16
No known key found for this signature in database
GPG key ID: E434ED292E85643A
12 changed files with 54 additions and 51 deletions

View file

@ -8,9 +8,9 @@ scala:
env:
- export LD_LIBRARY_PATH=/usr/local/lib
before_install:
- wget http://mirror.ibcp.fr/pub/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.zip
- unzip -qq apache-maven-3.5.4-bin.zip
- export M2_HOME=$PWD/apache-maven-3.5.4
- wget http://apache.crihan.fr/dist/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.zip
- unzip -qq apache-maven-3.6.0-bin.zip
- export M2_HOME=$PWD/apache-maven-3.6.0
- export PATH=$M2_HOME/bin:$PATH
script:
- mvn install

View file

@ -2,7 +2,7 @@
## Requirements
- [OpenJDK 11](https://jdk.java.net/11/).
- [Maven](https://maven.apache.org/download.cgi) 3.5.4 or newer
- [Maven](https://maven.apache.org/download.cgi) 3.6.0 or newer
- [Docker](https://www.docker.com/) 18.03 or newer (optional) if you want to run all tests
:warning: You can also use [Oracle JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) to build and run eclair, but we recommend you use Open JDK11.

View file

@ -6,7 +6,7 @@ FROM openjdk:8u171-jdk-alpine as BUILD
RUN apk add --no-cache curl tar bash
ARG MAVEN_VERSION=3.5.4
ARG MAVEN_VERSION=3.6.0
ARG USER_HOME_DIR="/root"
ARG SHA=ce50b1c91364cb77efe3776f756a6d92b76d9038b0a0782f7d53acf1e997a14d
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries

View file

@ -339,7 +339,7 @@ class Peer(nodeParams: NodeParams, remoteNodeId: PublicKey, authenticator: Actor
case (count, (_, origins)) if origins.contains(self) =>
// the announcement came from this peer, we don't send it back
count
case (count, (msg: HasTimestamp, _)) if !timestampInRange(msg, d.gossipTimestampFilter) =>
case (count, (msg, _)) if !timestampInRange(msg, d.gossipTimestampFilter) =>
// the peer has set up a filter on timestamp and this message is out of range
count
case (count, (msg, _)) =>
@ -606,14 +606,15 @@ object Peer {
*
* @param gossipTimestampFilter_opt optional gossip timestamp range
* @return
* - true if the msg's timestamp is in the requested range, or if there is no filtering
* - true if there is a filter and msg has no timestamp, or has one that matches the filter
* - false otherwise
*/
def timestampInRange(msg: HasTimestamp, gossipTimestampFilter_opt: Option[GossipTimestampFilter]): Boolean = {
def timestampInRange(msg: RoutingMessage, gossipTimestampFilter_opt: Option[GossipTimestampFilter]): Boolean = {
// check if this message has a timestamp that matches our timestamp filter
gossipTimestampFilter_opt match {
case None => true // no filtering
case Some(GossipTimestampFilter(_, firstTimestamp, timestampRange)) => msg.timestamp >= firstTimestamp && msg.timestamp <= firstTimestamp + timestampRange
(msg, gossipTimestampFilter_opt) match {
case (_, None) => false // BOLT 7: A node which wants any gossip messages would have to send this, otherwise [...] no gossip messages would be received.
case (hasTs: HasTimestamp, Some(GossipTimestampFilter(_, firstTimestamp, timestampRange))) => hasTs.timestamp >= firstTimestamp && hasTs.timestamp <= firstTimestamp + timestampRange
case _ => true // if there is a filter and message doesn't have a timestamp (e.g. channel_announcement), then we send it
}
}
}

View file

@ -47,7 +47,7 @@ trait StateTestsHelperMethods extends TestKitBase {
relayerB: TestProbe,
channelUpdateListener: TestProbe)
def init(nodeParamsA: NodeParams = TestConstants.Alice.nodeParams, nodeParamsB: NodeParams = TestConstants.Bob.nodeParams): SetupFixture = {
def init(nodeParamsA: NodeParams = TestConstants.Alice.nodeParams, nodeParamsB: NodeParams = TestConstants.Bob.nodeParams, wallet: EclairWallet = new TestWallet): SetupFixture = {
Globals.feeratesPerKw.set(FeeratesPerKw.single(TestConstants.feeratePerKw))
val alice2bob = TestProbe()
val bob2alice = TestProbe()
@ -59,7 +59,6 @@ trait StateTestsHelperMethods extends TestKitBase {
system.eventStream.subscribe(channelUpdateListener.ref, classOf[LocalChannelUpdate])
system.eventStream.subscribe(channelUpdateListener.ref, classOf[LocalChannelDown])
val router = TestProbe()
val wallet = new TestWallet
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(nodeParamsA, wallet, Bob.nodeParams.nodeId, alice2blockchain.ref, router.ref, relayerA.ref))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(nodeParamsB, wallet, Alice.nodeParams.nodeId, bob2blockchain.ref, router.ref, relayerB.ref))
SetupFixture(alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain, router, relayerA, relayerB, channelUpdateListener)

View file

@ -17,14 +17,17 @@
package fr.acinq.eclair.channel.states.a
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.{Block, ByteVector32}
import fr.acinq.bitcoin.{Block, ByteVector32, Satoshi}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.{MakeFundingTxResponse, TestWallet}
import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{WAIT_FOR_FUNDING_INTERNAL, _}
import fr.acinq.eclair.wire.{AcceptChannel, Error, Init, OpenChannel}
import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.scalatest.{Outcome, Tag}
import scodec.bits.ByteVector
import scala.concurrent.{Future, Promise}
import scala.concurrent.duration._
/**
@ -36,10 +39,13 @@ class WaitForAcceptChannelStateSpec extends TestkitBaseClass with StateTestsHelp
case class FixtureParam(alice: TestFSMRef[State, Data, Channel], alice2bob: TestProbe, bob2alice: TestProbe, alice2blockchain: TestProbe)
override def withFixture(test: OneArgTest): Outcome = {
val noopWallet = new TestWallet {
override def makeFundingTx(pubkeyScript: ByteVector, amount: Satoshi, feeRatePerKw: Long): Future[MakeFundingTxResponse] = Promise[MakeFundingTxResponse].future // will never be completed
}
val setup = if (test.tags.contains("mainnet")) {
init(TestConstants.Alice.nodeParams.copy(chainHash = Block.LivenetGenesisBlock.hash), TestConstants.Bob.nodeParams.copy(chainHash = Block.LivenetGenesisBlock.hash))
init(TestConstants.Alice.nodeParams.copy(chainHash = Block.LivenetGenesisBlock.hash), TestConstants.Bob.nodeParams.copy(chainHash = Block.LivenetGenesisBlock.hash), wallet = noopWallet)
} else {
init()
init(wallet = noopWallet)
}
import setup._
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)

View file

@ -17,14 +17,17 @@
package fr.acinq.eclair.channel.states.b
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.ByteVector32
import fr.acinq.bitcoin.{ByteVector32, Satoshi}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.{MakeFundingTxResponse, TestWallet}
import fr.acinq.eclair.channel._
import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.scalatest.Outcome
import scodec.bits.ByteVector
import scala.concurrent.{Future, Promise}
import scala.concurrent.duration._
/**
@ -36,7 +39,10 @@ class WaitForFundingCreatedInternalStateSpec extends TestkitBaseClass with State
case class FixtureParam(alice: TestFSMRef[State, Data, Channel], alice2bob: TestProbe, bob2alice: TestProbe, alice2blockchain: TestProbe)
override def withFixture(test: OneArgTest): Outcome = {
val setup = init()
val noopWallet = new TestWallet {
override def makeFundingTx(pubkeyScript: ByteVector, amount: Satoshi, feeRatePerKw: Long): Future[MakeFundingTxResponse] = Promise[MakeFundingTxResponse].future // will never be completed
}
val setup = init(wallet = noopWallet)
import setup._
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)

View file

@ -67,7 +67,7 @@ class SqliteNetworkDbSpec extends FunSuite {
val sqlite = inmem
val db = new SqliteNetworkDb(sqlite)
def sig = Crypto.encodeSignature(Crypto.sign(randomKey.toBin, randomKey)) :+ 1.toByte
def sig = Crypto.encodeSignature(Crypto.sign(randomBytes32, randomKey)) :+ 1.toByte
val channel_1 = Announcements.makeChannelAnnouncement(Block.RegtestGenesisBlock.hash, ShortChannelId(42), randomKey.publicKey, randomKey.publicKey, randomKey.publicKey, randomKey.publicKey, sig, sig, sig, sig)
val channel_2 = Announcements.makeChannelAnnouncement(Block.RegtestGenesisBlock.hash, ShortChannelId(43), randomKey.publicKey, randomKey.publicKey, randomKey.publicKey, randomKey.publicKey, sig, sig, sig, sig)
@ -107,7 +107,7 @@ class SqliteNetworkDbSpec extends FunSuite {
test("remove many channels") {
val sqlite = inmem
val db = new SqliteNetworkDb(sqlite)
val sig = Crypto.encodeSignature(Crypto.sign(randomKey.toBin, randomKey)) :+ 1.toByte
val sig = Crypto.encodeSignature(Crypto.sign(randomBytes32, randomKey)) :+ 1.toByte
val priv = randomKey
val pub = priv.publicKey
val capacity = Satoshi(10000)

View file

@ -149,6 +149,7 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
instantiateEclairNode("F3", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F3", "eclair.expiry-delta-blocks" -> 137, "eclair.server.port" -> 29737, "eclair.api.port" -> 28087, "eclair.payment-handler" -> "noop")).withFallback(commonConfig))
instantiateEclairNode("F4", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F4", "eclair.expiry-delta-blocks" -> 138, "eclair.server.port" -> 29738, "eclair.api.port" -> 28088, "eclair.payment-handler" -> "noop")).withFallback(commonConfig))
instantiateEclairNode("F5", ConfigFactory.parseMap(Map("eclair.node-alias" -> "F5", "eclair.expiry-delta-blocks" -> 139, "eclair.server.port" -> 29739, "eclair.api.port" -> 28089, "eclair.payment-handler" -> "noop")).withFallback(commonConfig))
instantiateEclairNode("G", ConfigFactory.parseMap(Map("eclair.node-alias" -> "G", "eclair.expiry-delta-blocks" -> 140, "eclair.server.port" -> 29740, "eclair.api.port" -> 28090, "eclair.fee-base-msat" -> 1010, "eclair.fee-proportional-millionths" -> 102)).withFallback(commonConfig))
// by default C has a normal payment handler, but this can be overriden in tests
val paymentHandlerC = nodes("C").system.actorOf(LocalPaymentHandler.props(nodes("C").nodeParams))
@ -172,7 +173,7 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
}
test("connect nodes") {
// ,--G--, // G is being added later in a test
// ,--G--,
// / \
// A---B ------- C ==== D
// \ / \
@ -182,7 +183,7 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
val eventListener = TestProbe()
nodes.values.foreach(_.system.eventStream.subscribe(eventListener.ref, classOf[ChannelStateChanged]))
connect(nodes("A"), nodes("B"), 10000000, 0)
connect(nodes("A"), nodes("B"), 11000000, 0)
connect(nodes("B"), nodes("C"), 2000000, 0)
connect(nodes("C"), nodes("D"), 5000000, 0)
connect(nodes("C"), nodes("D"), 5000000, 0)
@ -193,8 +194,10 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
connect(nodes("C"), nodes("F3"), 5000000, 0)
connect(nodes("C"), nodes("F4"), 5000000, 0)
connect(nodes("C"), nodes("F5"), 5000000, 0)
connect(nodes("B"), nodes("G"), 16000000, 0)
connect(nodes("G"), nodes("C"), 16000000, 0)
val numberOfChannels = 11
val numberOfChannels = 13
val channelEndpointsCount = 2 * numberOfChannels
// we make sure all channels have set up their WatchConfirmed for the funding tx
@ -246,8 +249,8 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
// A requires private channels, as a consequence:
// - only A and B know about channel A-B
// - A is not announced
awaitAnnouncements(nodes.filterKeys(key => List("A", "B").contains(key)), 9, 10, 22)
awaitAnnouncements(nodes.filterKeys(key => !List("A", "B").contains(key)), 9, 10, 20)
awaitAnnouncements(nodes.filterKeys(key => List("A", "B").contains(key)), 10, 12, 26)
awaitAnnouncements(nodes.filterKeys(key => !List("A", "B").contains(key)), 10, 12, 24)
}
test("send an HTLC A->D") {
@ -399,33 +402,21 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with BitcoindService
test("send an HTLC A->B->G->C using heuristics to select the route") {
val sender = TestProbe()
// G has very large channels but slightly more expensive than the others
instantiateEclairNode("G", ConfigFactory.parseMap(Map("eclair.node-alias" -> "G", "eclair.expiry-delta-blocks" -> 140, "eclair.server.port" -> 29740, "eclair.api.port" -> 28090, "eclair.fee-base-msat" -> 1010, "eclair.fee-proportional-millionths" -> 102)).withFallback(commonConfig))
connect(nodes("B"), nodes("G"), 16000000, 0)
connect(nodes("G"), nodes("C"), 16000000, 0)
sender.send(bitcoincli, BitcoinReq("generate", 10))
sender.expectMsgType[JValue](10 seconds)
awaitCond({
sender.send(nodes("A").router, 'channels)
sender.expectMsgType[Iterable[ChannelAnnouncement]](5 seconds).exists(chanAnn => chanAnn.nodeId1 == nodes("G").nodeParams.nodeId || chanAnn.nodeId2 == nodes("G").nodeParams.nodeId)
}, max = 60 seconds, interval = 3 seconds)
val amountMsat = MilliSatoshi(2000)
// first we retrieve a payment hash from C
val amountMsat = MilliSatoshi(2000)
sender.send(nodes("C").paymentHandler, ReceivePayment(Some(amountMsat), "Change from coffee"))
val pr = sender.expectMsgType[PaymentRequest](30 seconds)
// the payment is requesting to use a capacity-optimized route which will select node G even though it's a bit more expensive
sender.send(nodes("A").paymentInitiator,
SendPayment(amountMsat.amount, pr.paymentHash, nodes("C").nodeParams.nodeId, routeParams = integrationTestRouteParams.map(_.copy(ratios = Some(WeightRatios(0, 0, 1))))))
SendPayment(amountMsat.amount, pr.paymentHash, nodes("C").nodeParams.nodeId, maxAttempts = 1, routeParams = integrationTestRouteParams.map(_.copy(ratios = Some(WeightRatios(0, 0, 1))))))
awaitCond({
val route = sender.expectMsgType[PaymentSucceeded].route
route.exists(_.nodeId == nodes("G").nodeParams.nodeId) // assert the used route is actually going through G
}, max = 30 seconds, interval = 3 seconds)
sender.expectMsgType[PaymentResult](10 seconds) match {
case PaymentFailed(_, failures) => failures == Seq.empty // if something went wrong fail with a hint
case PaymentSucceeded(_, _, _, route) => route.exists(_.nodeId == nodes("G").nodeParams.nodeId)
}
}, max = 30 seconds, interval = 10 seconds)
}

View file

@ -109,9 +109,7 @@ class PeerSpec extends TestkitBaseClass {
connect(remoteNodeId, authenticator, watcher, router, relayer, connection, transport, peer)
val rebroadcast = Rebroadcast(channels.map(_ -> Set.empty[ActorRef]).toMap, updates.map(_ -> Set.empty[ActorRef]).toMap, nodes.map(_ -> Set.empty[ActorRef]).toMap)
probe.send(peer, rebroadcast)
channels.foreach(transport.expectMsg(_))
updates.foreach(transport.expectMsg(_))
nodes.foreach(transport.expectMsg(_))
transport.expectNoMsg(2 seconds)
}
test("filter gossip message (filtered by origin)") { f =>
@ -122,6 +120,8 @@ class PeerSpec extends TestkitBaseClass {
channels.map(_ -> Set.empty[ActorRef]).toMap + (channels(5) -> Set(peer)),
updates.map(_ -> Set.empty[ActorRef]).toMap + (updates(6) -> Set(peer)) + (updates(10) -> Set(peer)),
nodes.map(_ -> Set.empty[ActorRef]).toMap + (nodes(4) -> Set(peer)))
val filter = wire.GossipTimestampFilter(Alice.nodeParams.chainHash, 0, Long.MaxValue) // no filtering on timestamps
probe.send(peer, filter)
probe.send(peer, rebroadcast)
// peer won't send out announcements that came from itself
(channels.toSet - channels(5)).foreach(transport.expectMsg(_))

View file

@ -134,8 +134,8 @@ object RoutingSyncSpec {
val TxCoordinates(blockHeight, _, _) = ShortChannelId.coordinates(shortChannelId)
val channelUpdate_ab = makeChannelUpdate(Block.RegtestGenesisBlock.hash, priv_a, priv_b.publicKey, shortChannelId, cltvExpiryDelta = 7, 0, feeBaseMsat = 766000, feeProportionalMillionths = 10, 500000000L, timestamp = blockHeight)
val channelUpdate_ba = makeChannelUpdate(Block.RegtestGenesisBlock.hash, priv_b, priv_a.publicKey, shortChannelId, cltvExpiryDelta = 7, 0, feeBaseMsat = 766000, feeProportionalMillionths = 10, 500000000L, timestamp = blockHeight)
val nodeAnnouncement_a = makeNodeAnnouncement(priv_a, "a", Alice.nodeParams.color, List())
val nodeAnnouncement_b = makeNodeAnnouncement(priv_b, "b", Bob.nodeParams.color, List())
val nodeAnnouncement_a = makeNodeAnnouncement(priv_a, "a", Color(0, 0, 0), List())
val nodeAnnouncement_b = makeNodeAnnouncement(priv_b, "b", Color(0, 0, 0), List())
(channelAnn_ab, channelUpdate_ab, channelUpdate_ba, nodeAnnouncement_a, nodeAnnouncement_b)
}
}

View file

@ -66,7 +66,7 @@
<scala.version.short>2.11</scala.version.short>
<akka.version>2.3.14</akka.version>
<sttp.version>1.3.9</sttp.version>
<bitcoinlib.version>0.10</bitcoinlib.version>
<bitcoinlib.version>0.11</bitcoinlib.version>
<guava.version>24.0-android</guava.version>
</properties>